.
[coreutils.git] / src / rmdir.c
blob7853aa08010faf79be55c3a826493a8b30e756b5
1 /* rmdir -- remove directories
2 Copyright (C) 90, 91, 95, 96, 97, 1998 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Options:
19 -p, --parent Remove any parent dirs that are explicitly mentioned
20 in an argument, if they become empty after the
21 argument file is removed.
23 David MacKenzie <djm@ai.mit.edu> */
25 #include <config.h>
26 #include <stdio.h>
27 #include <getopt.h>
28 #include <sys/types.h>
30 #include "system.h"
31 #include "closeout.h"
32 #include "error.h"
34 void strip_trailing_slashes ();
36 /* The name this program was run with. */
37 char *program_name;
39 /* If nonzero, remove empty parent directories. */
40 static int empty_paths;
42 /* If nonzero, don't treat failure to remove a nonempty directory
43 as an error. */
44 static int ignore_fail_on_non_empty;
46 /* If nonzero, output a diagnostic for every directory processed. */
47 static int verbose;
49 /* If nonzero, display usage information and exit. */
50 static int show_help;
52 /* If nonzero, print the version on standard output and exit. */
53 static int show_version;
55 static struct option const longopts[] =
57 /* Don't name this `--force' because it's not close enough in meaning
58 to e.g. rm's -f option. */
59 {"ignore-fail-on-non-empty", no_argument, NULL, 13},
61 {"path", no_argument, NULL, 'p'},
62 {"parents", no_argument, NULL, 'p'},
63 {"verbose", no_argument, NULL, 14},
64 {"help", no_argument, &show_help, 1},
65 {"version", no_argument, &show_version, 1},
66 {NULL, 0, NULL, 0}
69 /* Remove any empty parent directories of PATH.
70 If PATH contains slash characters, at least one of them
71 (beginning with the rightmost) is replaced with a NUL byte. */
73 static int
74 remove_parents (char *path)
76 char *slash;
77 int fail = 0;
79 while (1)
81 slash = strrchr (path, '/');
82 if (slash == NULL)
83 break;
84 /* Remove any characters after the slash, skipping any extra
85 slashes in a row. */
86 while (slash > path && *slash == '/')
87 --slash;
88 slash[1] = 0;
89 fail = rmdir (path);
91 /* Give a diagnostic for each successful removal if --verbose. */
92 if (verbose && !fail)
93 error (0, errno, _("removed directory, %s"), path);
95 if (fail)
97 /* Give a diagnostic and set fail if not --ignore. */
98 if (!ignore_fail_on_non_empty || errno != ENOTEMPTY)
100 error (0, errno, "%s", path);
101 fail = 1;
103 break;
106 return fail;
109 static void
110 usage (int status)
112 if (status != 0)
113 fprintf (stderr, _("Try `%s --help' for more information.\n"),
114 program_name);
115 else
117 printf (_("Usage: %s [OPTION]... DIRECTORY...\n"), program_name);
118 printf (_("\
119 Remove the DIRECTORY(ies), if they are empty.\n\
121 --ignore-fail-on-non-empty\n\
122 ignore each failure that is solely because the\n\
123 directory is non-empty\n\
124 -p, --parents remove explicit parent directories if being emptied\n\
125 --verbose output a diagnostic for every directory processed\n\
126 --help display this help and exit\n\
127 --version output version information and exit\n\
128 "));
129 puts (_("\nReport bugs to <fileutils-bugs@gnu.org>."));
130 close_stdout ();
132 exit (status);
136 main (int argc, char **argv)
138 int errors = 0;
139 int optc;
141 program_name = argv[0];
142 setlocale (LC_ALL, "");
143 bindtextdomain (PACKAGE, LOCALEDIR);
144 textdomain (PACKAGE);
146 empty_paths = 0;
148 while ((optc = getopt_long (argc, argv, "p", longopts, NULL)) != -1)
150 switch (optc)
152 case 0: /* Long option. */
153 break;
154 case 'p':
155 empty_paths = 1;
156 break;
157 case 13:
158 ignore_fail_on_non_empty = 1;
159 break;
160 case 14:
161 verbose = 1;
162 break;
163 default:
164 usage (1);
168 if (show_version)
170 printf ("rmdir (%s) %s\n", GNU_PACKAGE, VERSION);
171 close_stdout ();
172 exit (0);
175 if (show_help)
176 usage (0);
178 if (optind == argc)
180 error (0, 0, _("too few arguments"));
181 usage (1);
184 for (; optind < argc; ++optind)
186 int fail;
187 char *dir = argv[optind];
189 /* Stripping slashes is harmless for rmdir;
190 if the arg is not a directory, it will fail with ENOTDIR. */
191 strip_trailing_slashes (dir);
192 fail = rmdir (dir);
194 /* Give a diagnostic for each successful removal if --verbose. */
195 if (verbose && !fail)
196 error (0, errno, _("removed directory, %s"), dir);
198 if (fail)
200 if (!ignore_fail_on_non_empty || errno != ENOTEMPTY)
202 error (0, errno, "%s", dir);
203 errors = 1;
206 else if (empty_paths)
207 errors += remove_parents (dir);
210 exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);