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
  10#include "libbb.h"
  11
  12/* Used from NOFORK applets. Must not allocate anything */
  13
  14int FAST_FUNC remove_file(const char *path, int flags)
  15{
  16        struct stat path_stat;
  17
  18        if (lstat(path, &path_stat) < 0) {
  19                if (errno != ENOENT) {
  20                        bb_perror_msg("can't stat '%s'", path);
  21                        return -1;
  22                }
  23                if (!(flags & FILEUTILS_FORCE)) {
  24                        bb_perror_msg("can't remove '%s'", path);
  25                        return -1;
  26                }
  27                return 0;
  28        }
  29
  30        if (S_ISDIR(path_stat.st_mode)) {
  31                DIR *dp;
  32                struct dirent *d;
  33                int status = 0;
  34
  35                if (!(flags & FILEUTILS_RECUR)) {
  36                        bb_error_msg("'%s' is a directory", path);
  37                        return -1;
  38                }
  39
  40                if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 && isatty(0))
  41                 || (flags & FILEUTILS_INTERACTIVE)
  42                ) {
  43                        fprintf(stderr, "%s: descend into directory '%s'? ", applet_name,
  44                                        path);
  45                        if (!bb_ask_confirmation())
  46                                return 0;
  47                }
  48
  49                dp = opendir(path);
  50                if (dp == NULL) {
  51                        return -1;
  52                }
  53
  54                while ((d = readdir(dp)) != NULL) {
  55                        char *new_path;
  56
  57                        new_path = concat_subpath_file(path, d->d_name);
  58                        if (new_path == NULL)
  59                                continue;
  60                        if (remove_file(new_path, flags) < 0)
  61                                status = -1;
  62                        free(new_path);
  63                }
  64
  65                if (closedir(dp) < 0) {
  66                        bb_perror_msg("can't close '%s'", path);
  67                        return -1;
  68                }
  69
  70                if (flags & FILEUTILS_INTERACTIVE) {
  71                        fprintf(stderr, "%s: remove directory '%s'? ", applet_name, path);
  72                        if (!bb_ask_confirmation())
  73                                return status;
  74                }
  75
  76                if (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_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