hush: get rid of charmap[]
[oweals/busybox.git] / libbb / remove_file.c
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 tarball for details.
8  */
9
10 #include "libbb.h"
11
12 /* Used from NOFORK applets. Must not allocate anything */
13
14 int 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("cannot stat '%s'", path);
21                         return -1;
22                 }
23                 if (!(flags & FILEUTILS_FORCE)) {
24                         bb_perror_msg("cannot 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("cannot 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("cannot remove '%s'", path);
78                         return -1;
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_confirmation())
93                         return 0;
94         }
95
96         if (unlink(path) < 0) {
97                 bb_perror_msg("cannot remove '%s'", path);
98                 return -1;
99         }
100
101         return 0;
102 }