remove_file: cosmetic code improvement, a few bytes saved
[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 int remove_file(const char *path, int flags)
13 {
14         struct stat path_stat;
15
16         if (lstat(path, &path_stat) < 0) {
17                 if (errno != ENOENT) {
18                         bb_perror_msg("cannot stat '%s'", path);
19                         return -1;
20                 }
21                 if (!(flags & FILEUTILS_FORCE)) {
22                         bb_perror_msg("cannot remove '%s'", path);
23                         return -1;
24                 }
25                 return 0;
26         }
27
28         if (S_ISDIR(path_stat.st_mode)) {
29                 DIR *dp;
30                 struct dirent *d;
31                 int status = 0;
32
33                 if (!(flags & FILEUTILS_RECUR)) {
34                         bb_error_msg("%s: is a directory", path);
35                         return -1;
36                 }
37
38                 if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 && isatty(0))
39                  || (flags & FILEUTILS_INTERACTIVE)
40                 ) {
41                         fprintf(stderr, "%s: descend into directory '%s'? ", applet_name,
42                                         path);
43                         if (!bb_ask_confirmation())
44                                 return 0;
45                 }
46
47                 dp = opendir(path);
48                 if (dp == NULL) {
49                         return -1;
50                 }
51
52                 while ((d = readdir(dp)) != NULL) {
53                         char *new_path;
54
55                         new_path = concat_subpath_file(path, d->d_name);
56                         if (new_path == NULL)
57                                 continue;
58                         if (remove_file(new_path, flags) < 0)
59                                 status = -1;
60                         free(new_path);
61                 }
62
63                 if (closedir(dp) < 0) {
64                         bb_perror_msg("cannot close '%s'", path);
65                         return -1;
66                 }
67
68                 if (flags & FILEUTILS_INTERACTIVE) {
69                         fprintf(stderr, "%s: remove directory '%s'? ", applet_name, path);
70                         if (!bb_ask_confirmation())
71                                 return status;
72                 }
73
74                 if (rmdir(path) < 0) {
75                         bb_perror_msg("cannot remove '%s'", path);
76                         return -1;
77                 }
78
79                 return status;
80         }
81
82         /* !ISDIR */
83         if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0
84                         && !S_ISLNK(path_stat.st_mode) && isatty(0))
85          || (flags & FILEUTILS_INTERACTIVE)
86         ) {
87                 fprintf(stderr, "%s: remove '%s'? ", applet_name, path);
88                 if (!bb_ask_confirmation())
89                         return 0;
90         }
91
92         if (unlink(path) < 0) {
93                 bb_perror_msg("cannot remove '%s'", path);
94                 return -1;
95         }
96
97         return 0;
98 }