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                closedir(dp);
  64
  65                if (flags & FILEUTILS_INTERACTIVE) {
  66                        fprintf(stderr, "%s: remove directory '%s'? ",
  67                                        applet_name, path);
  68                        if (!bb_ask_y_confirmation())
  69                                return status;
  70                }
  71
  72                if (status == 0 && rmdir(path) < 0) {
  73                        bb_perror_msg("can't remove '%s'", path);
  74                        return -1;
  75                }
  76
  77                if (flags & FILEUTILS_VERBOSE) {
  78                        printf("removed directory: '%s'\n", path);
  79                }
  80
  81                return status;
  82        }
  83
  84        /* !ISDIR */
  85        if ((!(flags & FILEUTILS_FORCE)
  86             && access(path, W_OK) < 0
  87             && !S_ISLNK(path_stat.st_mode)
  88             && isatty(0))
  89         || (flags & FILEUTILS_INTERACTIVE)
  90        ) {
  91                fprintf(stderr, "%s: remove '%s'? ", applet_name, path);
  92                if (!bb_ask_y_confirmation())
  93                        return 0;
  94        }
  95
  96        if (unlink(path) < 0) {
  97                bb_perror_msg("can't remove '%s'", path);
  98                return -1;
  99        }
 100
 101        if (flags & FILEUTILS_VERBOSE) {
 102                printf("removed '%s'\n", path);
 103        }
 104
 105        return 0;
 106}
 107