summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2012-11-29 20:21:26 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2012-11-29 20:21:29 +0100
commit5a9d53c47e3c6ce5bc7d38c60501a37ce2c2b276 (patch)
treee04c756e01daa0e71a209a5ed60e464395268d85
parent159109f5ff2e3b0ee7c44685e2241605ae41b662 (diff)
downloadbarebox-5a9d53c47e3c6ce5bc7d38c60501a37ce2c2b276.tar.gz
barebox-5a9d53c47e3c6ce5bc7d38c60501a37ce2c2b276.tar.xz
rm: implement -r
To recursively remove files and directories. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--commands/rm.c28
-rw-r--r--include/fs.h2
-rw-r--r--lib/Makefile1
-rw-r--r--lib/recursive_action.c1
-rw-r--r--lib/unlink-recursive.c56
5 files changed, 83 insertions, 5 deletions
diff --git a/commands/rm.c b/commands/rm.c
index 4e765acf7a..5486005d9b 100644
--- a/commands/rm.c
+++ b/commands/rm.c
@@ -19,17 +19,36 @@
#include <common.h>
#include <command.h>
#include <fs.h>
+#include <getopt.h>
#include <errno.h>
static int do_rm(int argc, char *argv[])
{
- int i = 1;
+ int i, opt, recursive = 0;
+
+ while ((opt = getopt(argc, argv, "r")) > 0) {
+ switch (opt) {
+ case 'r':
+ recursive = 1;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
if (argc < 2)
return COMMAND_ERROR_USAGE;
+ i = optind;
+
while (i < argc) {
- if (unlink(argv[i])) {
+ int ret;
+
+ if (recursive)
+ ret = unlink_recursive(argv[i], NULL);
+ else
+ ret = unlink(argv[i]);
+ if (ret) {
printf("could not remove %s: %s\n", argv[i], errno_str());
return 1;
}
@@ -40,8 +59,9 @@ static int do_rm(int argc, char *argv[])
}
static const __maybe_unused char cmd_rm_help[] =
-"Usage: rm [FILES]\n"
-"Remove files\n";
+"Usage: rm [OPTIONS] [FILES]\n"
+"Remove files\n"
+"-r remove directories and their contents recursively\n";
BAREBOX_CMD_START(rm)
.cmd = do_rm,
diff --git a/include/fs.h b/include/fs.h
index 3d5714c1fb..8ff7300919 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -182,4 +182,6 @@ void automount_remove(const char *_path);
int automount_add(const char *path, const char *cmd);
void automount_print(void);
+int unlink_recursive(const char *path, char **failedpath);
+
#endif /* __FS_H */
diff --git a/lib/Makefile b/lib/Makefile
index eb0af9248e..635d52e653 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -36,3 +36,4 @@ obj-$(CONFIG_BITREV) += bitrev.o
obj-$(CONFIG_QSORT) += qsort.o
obj-y += gui/
obj-$(CONFIG_XYMODEM) += xymodem.o
+obj-y += unlink-recursive.o
diff --git a/lib/recursive_action.c b/lib/recursive_action.c
index 5bc2595db9..345d3db0ce 100644
--- a/lib/recursive_action.c
+++ b/lib/recursive_action.c
@@ -130,7 +130,6 @@ int recursive_action(const char *fileName,
return 0;
return 1;
done_nak_warn:
- printf("%s", fileName);
return 0;
}
diff --git a/lib/unlink-recursive.c b/lib/unlink-recursive.c
new file mode 100644
index 0000000000..a4885538c0
--- /dev/null
+++ b/lib/unlink-recursive.c
@@ -0,0 +1,56 @@
+#include <common.h>
+#include <libbb.h>
+#include <fs.h>
+
+static char unlink_recursive_failedpath[PATH_MAX];
+
+struct data {
+ int error;
+};
+
+static int file_action(const char *filename, struct stat *statbuf,
+ void *userdata, int depth)
+{
+ struct data *data = userdata;
+ int ret;
+
+ ret = unlink(filename);
+ if (ret) {
+ strcpy(unlink_recursive_failedpath, filename);
+ data->error = ret;
+ }
+
+ return ret ? 0 : 1;
+}
+
+static int dir_action(const char *dirname, struct stat *statbuf,
+ void *userdata, int depth)
+{
+ struct data *data = userdata;
+ int ret;
+
+ ret = rmdir(dirname);
+ if (ret) {
+ strcpy(unlink_recursive_failedpath, dirname);
+ data->error = ret;
+ }
+
+ return ret ? 0 : 1;
+}
+
+int unlink_recursive(const char *path, char **failedpath)
+{
+ struct data data = {};
+ int ret;
+
+ if (failedpath)
+ *failedpath = NULL;
+
+ ret = recursive_action(path, ACTION_RECURSE | ACTION_DEPTHFIRST,
+ file_action, dir_action, &data, 0);
+
+ if (!ret && failedpath)
+ *failedpath = unlink_recursive_failedpath;
+
+ return ret ? 0 : errno;
+}