login: re-enable Ctrl-^C before execing shell.
[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 <stdio.h>
11 #include <time.h>
12 #include <utime.h>
13 #include <dirent.h>
14 #include <errno.h>
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <getopt.h>
19 #include "libbb.h"
20
21 int remove_file(const char *path, int flags)
22 {
23         struct stat path_stat;
24         int path_exists = 1;
25
26         if (lstat(path, &path_stat) < 0) {
27                 if (errno != ENOENT) {
28                         bb_perror_msg("unable to stat `%s'", path);
29                         return -1;
30                 }
31
32                 path_exists = 0;
33         }
34
35         if (!path_exists) {
36                 if (!(flags & FILEUTILS_FORCE)) {
37                         bb_perror_msg("cannot remove `%s'", path);
38                         return -1;
39                 }
40                 return 0;
41         }
42
43         if (S_ISDIR(path_stat.st_mode)) {
44                 DIR *dp;
45                 struct dirent *d;
46                 int status = 0;
47
48                 if (!(flags & FILEUTILS_RECUR)) {
49                         bb_error_msg("%s: is a directory", path);
50                         return -1;
51                 }
52
53                 if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 &&
54                                         isatty(0)) ||
55                                 (flags & FILEUTILS_INTERACTIVE)) {
56                         fprintf(stderr, "%s: descend into directory `%s'? ", applet_name,
57                                         path);
58                         if (!bb_ask_confirmation())
59                                 return 0;
60                 }
61
62                 if ((dp = opendir(path)) == NULL) {
63                         return -1;
64                 }
65
66                 while ((d = readdir(dp)) != NULL) {
67                         char *new_path;
68
69                         new_path = concat_subpath_file(path, d->d_name);
70                         if(new_path == NULL)
71                                 continue;
72                         if (remove_file(new_path, flags) < 0)
73                                 status = -1;
74                         free(new_path);
75                 }
76
77                 if (closedir(dp) < 0) {
78                         bb_perror_msg("unable to close `%s'", path);
79                         return -1;
80                 }
81
82                 if (flags & FILEUTILS_INTERACTIVE) {
83                         fprintf(stderr, "%s: remove directory `%s'? ", applet_name, path);
84                         if (!bb_ask_confirmation())
85                                 return status;
86                 }
87
88                 if (rmdir(path) < 0) {
89                         bb_perror_msg("unable to remove `%s'", path);
90                         return -1;
91                 }
92
93                 return status;
94         } else {
95                 if ((!(flags & FILEUTILS_FORCE) && access(path, W_OK) < 0 &&
96                                         !S_ISLNK(path_stat.st_mode) &&
97                                         isatty(0)) ||
98                                 (flags & FILEUTILS_INTERACTIVE)) {
99                         fprintf(stderr, "%s: remove `%s'? ", applet_name, path);
100                         if (!bb_ask_confirmation())
101                                 return 0;
102                 }
103
104                 if (unlink(path) < 0) {
105                         bb_perror_msg("unable to remove `%s'", path);
106                         return -1;
107                 }
108
109                 return 0;
110         }
111 }