busybox/libbb/remove_file.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Mini remove_file implementation for busybox
   4 *
   5 * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>
   6 *
   7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   8 */
   9#include "libbb.h"
  10
  11/* Used from NOFORK applets. Must not allocate anything */
  12
  13int FAST_FUNC remove_file(const char *path, int flags)
  14{
  15        struct stat path_stat;
  16
  17        if (lstat(path, &path_stat) < 0) {
  18                if (errno != ENOENT) {
  19                        bb_perror_msg("can't stat '%s'", path);
  20                        return -1;
  21                }
  22                if (!(flags & FILEUTILS_FORCE)) {
  23                        bb_perror_msg("can't remove '%s'", path);
  24                        return -1;
  25                }
  26                return 0;
  27        }
  28
  29        if (S_ISDIR(path_stat.st_mode)) {
  30                DIR *dp;
  31                struct dirent *d;
  32                int status = 0;
  33
  34                if (!(flags & FILEUTILS_RECUR)) {
  35                        bb_error_msg("'%s' is a directory", path);
  36                        return -1;
  37                }
  38
  39                if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 && isatty(0))
  40                 || (flags & FILEUTILS_INTERACTIVE)
  41                ) {
  42                        fprintf(stderr, "%s: descend into directory '%s'? ",
  43                                        applet_name, path);
  44                        if (!bb_ask_y_confirmation())
  45                                return 0;
  46                }
  47
  48                dp = opendir(path);
  49                if (dp == NULL) {
  50                        return -1;
  51                }
  52
  53                while ((d = readdir(dp)) != NULL) {
  54                        char *new_path;
  55
  56                        new_path = concat_subpath_file(path, d->d_name);
  57                        if (new_path == NULL)
  58                                continue;
  59                        if (remove_file(new_path, flags) < 0)
  60                                status = -1;
  61                        free(new_path);
  62                }
  63
  64                if (closedir(dp) < 0) {
  65                        bb_perror_msg("can't close '%s'", path);
  66                        return -1;
  67                }
  68
  69                if (flags & FILEUTILS_INTERACTIVE) {
  70                        fprintf(stderr, "%s: remove directory '%s'? ",
  71                                        applet_name, path);
  72                        if (!bb_ask_y_confirmation())
  73                                return status;
  74                }
  75
  76                if (status == 0 && rmdir(path) < 0) {
  77                        bb_perror_msg("can't remove '%s'", path);
  78                        return -1;
  79                }
  80
  81                if (flags & FILEUTILS_VERBOSE) {
  82                        printf("removed directory: '%s'\n", path);
  83                }
  84
  85                return status;
  86        }
  87
  88        /* !ISDIR */
  89        if ((!(flags & FILEUTILS_FORCE)
  90             && access(path, W_OK) < 0
  91             && !S_ISLNK(path_stat.st_mode)
  92             && isatty(0))
  93         || (flags & FILEUTILS_INTERACTIVE)
  94        ) {
  95                fprintf(stderr, "%s: remove '%s'? ", applet_name, path);
  96                if (!bb_ask_y_confirmation())
  97                        return 0;
  98        }
  99
 100        if (unlink(path) < 0) {
 101                bb_perror_msg("can't remove '%s'", path);
 102                return -1;
 103        }
 104
 105        if (flags & FILEUTILS_VERBOSE) {
 106                printf("removed '%s'\n", path);
 107        }
 108
 109        return 0;
 110}
 111