aboutsummaryrefslogtreecommitdiff
path: root/coreutils/rmdir.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/rmdir.c')
-rw-r--r--coreutils/rmdir.c105
1 files changed, 41 insertions, 64 deletions
diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c
index 83b27c9bd..3f6037170 100644
--- a/coreutils/rmdir.c
+++ b/coreutils/rmdir.c
@@ -1,9 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Mini rmdir implementation for busybox 3 * rmdir implementation for busybox
4 * 4 *
5 * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen 5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -21,76 +20,54 @@
21 * 20 *
22 */ 21 */
23 22
24#include <getopt.h> 23/* BB_AUDIT SUSv3 compliant */
25#include <unistd.h> 24/* http://www.opengroup.org/onlinepubs/007904975/utilities/rmdir.html */
26#include <stdlib.h>
27 25
26#include <stdlib.h>
27#include <unistd.h>
28#include <libgen.h>
28#include "busybox.h" 29#include "busybox.h"
29 30
30 31extern int rmdir_main(int argc, char **argv)
31/* Return true if a path is composed of multiple components. */
32
33static int
34multiple_components_p (const char *path)
35{
36 const char *s = path;
37
38 while (s[0] != '\0' && s[0] != '/')
39 s++;
40
41 while (s[0] == '/')
42 s++;
43
44 return (s[0] != '\0');
45}
46
47
48/* Remove a directory. Returns 0 if successful, -1 on error. */
49
50static int
51remove_directory (char *path, int flags)
52{
53 if (!(flags & FILEUTILS_RECUR)) {
54 if (rmdir (path) < 0) {
55 perror_msg ("unable to remove `%s'", path);
56 return -1;
57 }
58 } else {
59 if (remove_directory (path, 0) < 0)
60 return -1;
61
62 if (multiple_components_p (path))
63 if (remove_directory (dirname (path), flags) < 0)
64 return -1;
65 }
66
67 return 0;
68}
69
70
71extern int
72rmdir_main (int argc, char **argv)
73{ 32{
74 int status = EXIT_SUCCESS; 33 int status = EXIT_SUCCESS;
75 int flags = 0; 34 int flags;
76 int i, opt; 35 int do_dot;
36 char *path;
77 37
78 while ((opt = getopt (argc, argv, "p")) != -1) 38 flags = bb_getopt_ulflags(argc, argv, "p");
79 switch (opt) {
80 case 'p':
81 flags |= FILEUTILS_RECUR;
82 break;
83 39
84 default: 40 argv += optind;
85 show_usage ();
86 }
87 41
88 if (optind == argc) 42 if (!*argv) {
89 show_usage(); 43 bb_show_usage();
44 }
90 45
91 for (i = optind; i < argc; i++) 46 do {
92 if (remove_directory (argv[i], flags) < 0) 47 path = *argv;
93 status = EXIT_FAILURE; 48
49 /* Record if the first char was a '.' so we can use dirname later. */
50 do_dot = (*path == '.');
51
52 do {
53 if (rmdir(path) < 0) {
54 bb_perror_msg("`%s'", path); /* Match gnu rmdir msg. */
55 status = EXIT_FAILURE;
56 } else if (flags) {
57 /* Note: path was not empty or null since rmdir succeeded. */
58 path = dirname(path);
59 /* Path is now just the parent component. Note that dirname
60 * returns "." if there are no parents. We must distinguish
61 * this from the case of the original path starting with '.'.
62 */
63 if (do_dot || (*path != '.') || path[1]) {
64 continue;
65 }
66 }
67 break;
68 } while (1);
69
70 } while (*++argv);
94 71
95 return status; 72 return status;
96} 73}