diff --git a/commands/rm.c b/commands/rm.c index 4e765acf7..5486005d9 100644 --- a/commands/rm.c +++ b/commands/rm.c @@ -19,17 +19,36 @@ #include #include #include +#include #include 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 3d5714c1f..8ff730091 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 eb0af9248..635d52e65 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 5bc2595db..345d3db0c 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 000000000..a4885538c --- /dev/null +++ b/lib/unlink-recursive.c @@ -0,0 +1,56 @@ +#include +#include +#include + +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; +}