diff options
author | Tyler Murphy <tylerm@tylerm.dev> | 2023-05-06 00:39:44 -0400 |
---|---|---|
committer | Tyler Murphy <tylerm@tylerm.dev> | 2023-05-06 00:39:44 -0400 |
commit | d8f2c10b7108fff6b7e437291093a1cadc15ab9f (patch) | |
tree | 3fc50a19d6fbb9c94a8fe147cd2a6c4ba7f59b8d /command/rm.c | |
parent | ansii c (diff) | |
download | lazysphere-d8f2c10b7108fff6b7e437291093a1cadc15ab9f.tar.gz lazysphere-d8f2c10b7108fff6b7e437291093a1cadc15ab9f.tar.bz2 lazysphere-d8f2c10b7108fff6b7e437291093a1cadc15ab9f.zip |
refactor
Diffstat (limited to 'command/rm.c')
-rw-r--r-- | command/rm.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/command/rm.c b/command/rm.c new file mode 100644 index 0000000..81a956a --- /dev/null +++ b/command/rm.c @@ -0,0 +1,140 @@ +#include "command.h" +#include "lslib.h" + +#include <dirent.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +static struct { + bool force; + bool prompt; + bool verbose; + bool recurse; +} flags; + +static void help(void) { + printf("Usage: rm [-irfv] FILE...\n\n"); + printf("Remove (unlink) FILESs\n\n"); + printf("\t-i\tAlways prompt before removing\n"); + printf("\t-f\tForce, never prompt\n"); + printf("\t-v\tVerbose\n"); + printf("\t-R,-r\tRecurse\n"); +} + +static int short_arg(char c, char* next) { + UNUSED(next); + switch (c) { + case 'i': + flags.prompt = true; + break; + case 'f': + flags.force = true; + break; + case 'v': + flags.verbose = true; + break; + case 'R': + case 'r': + flags.recurse = true; + break; + default: + return ARG_INVALID; + } + return ARG_UNUSED; +} + +static void rm_file (char* path); + +static bool rm_dir (void) { + DIR* d; + struct dirent* file; + + d = opendir(get_path_buffer()); + if (d == NULL) { + error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno)); + return false; + } + + while ((file = readdir(d)) != NULL) { + if (is_dot_dir(file->d_name)) continue; + rm_file(file->d_name); + } + + closedir(d); + return true; +} + +static void rm_file(char* path) { + int save = push_path_buffer(path); + + struct stat s; + if (lstat(get_path_buffer(), &s) < 0) { + pop_path_buffer(save); + error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno)); + return; + } + + if (S_ISDIR(s.st_mode)) { + if (!flags.force) { + error_s("cannot delete '%s': Is a directory\n", get_path_buffer()); + pop_path_buffer(save); + return; + } + if (flags.recurse && !rm_dir()) { + pop_path_buffer(save); + return; + } + } + + if (flags.prompt) { + char c; + + fprintf(stderr, "delete '%s'? ", get_path_buffer()); + fflush(stderr); + + c = getchar(); + if (c != 'y' && c != 'Y') { + fprintf(stderr, "Skipping...\n"); + pop_path_buffer(save); + return; + } + } + + if (remove(get_path_buffer()) < 0) { + error_s("failed to delete '%s': %s\n", get_path_buffer(), strerror(errno)); + } else if (flags.verbose) { + output("deleted '%s'\n", get_path_buffer()); + } + + pop_path_buffer(save); +} + +COMMAND(rm) { + + int start, i; + + if (argc < 1) { + global_help(help); + return EXIT_SUCCESS; + } + + flags.prompt = false; + flags.force = false; + flags.verbose = false; + flags.recurse = false; + + start = parse_args(argc, argv, help, short_arg, NULL); + +#ifdef FRENCH + if (streql(argv[0], "-fr")) { + printf("\x1b[94mremoving \x1b[97mthe \x1b[91mfrench \x1b[93m(baguette noises)\x1b[0m\n"); + } +#endif + + for (i = start; i < argc; i++) { + rm_file(argv[i]); + } + + return EXIT_SUCCESS; +} |