diff options
Diffstat (limited to '')
-rw-r--r-- | src/commands/mv.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/commands/mv.c b/src/commands/mv.c new file mode 100644 index 0000000..f3e759a --- /dev/null +++ b/src/commands/mv.c @@ -0,0 +1,108 @@ +#include "../command.h" + +static struct { + bool prompt; + bool dont_overwrite; + bool refuse_if_dir; + bool verbose; +} flags; + +static void help(void) { + printf("Usage: mv [-inT] SOURCE... DIRECTORY\n\n"); + printf("Rename SOURCE to DEST, or move SOURCEs to DIRECTORY\n"); + printf("\t-i\tInteractive, prompt before overwriting\n"); + printf("\t-n\tDon't overwrite an existing file\n"); + printf("\t-T\tRefuse to move if DEST is a directory\n"); + printf("\t-v\tVerbose\n"); +} + +static int short_arg(char c, char* next) { + UNUSED(next); + switch (c) { + case 't': + flags.prompt = true; + break; + case 'n': + flags.dont_overwrite = true; + break; + case 'T': + flags.refuse_if_dir = true; + break; + case 'v': + flags.verbose = true; + break; + default: + return ARG_UNUSED; + } + return ARG_USED; +} + +static void mv_dir(bool exists) { + if (exists && flags.dont_overwrite) { + if (flags.verbose) output("skipping '%s'; overwrise is false", get_path_buffer_2()); + return; + } + if (exists && flags.prompt) { + fprintf(stderr, "overwrite '%s'? ", get_path_buffer_2()); + fflush(stderr); + char c = getchar(); + if (c != 'y' && c != 'Y') { + if (flags.verbose) output("skipping..."); + return; + } + } + + if (rename(get_path_buffer(), get_path_buffer_2()) < 0) { + error_s("cannot move '%s': %s", get_path_buffer(), strerror(errno)); + } else if (flags.verbose) { + output("moved '%s'", get_path_buffer()); + } +} + +COMMAND(mv) { + + flags.refuse_if_dir = false; + flags.dont_overwrite = false; + flags.prompt = false; + flags.verbose = false; + + int start = parse_args(argc, argv, help, short_arg, NULL); + + if (argc - start < 2) { + global_help(help); + } + + push_path_buffer_2(argv[argc-1]); + + bool dest = true; + struct stat s; + if (lstat(get_path_buffer_2(), &s) < 0 && argc - start > 2) { + dest = false; + error("cannot stat '%s': %s", get_path_buffer_2(), strerror(errno)); + } + + if (dest && flags.refuse_if_dir) { + if (S_ISDIR(s.st_mode)) { + error("target '%s': Is A Directory", get_path_buffer_2()); + } + } + + if (argc - start == 2) { + push_path_buffer(argv[argc-2]); + mv_dir(dest); + return EXIT_SUCCESS; + } + + if (dest && !S_ISDIR(s.st_mode)) { + error("target '%s': Is Not A Directory", get_path_buffer_2()); + } + + for (int i = start; i < argc - 1; i++) { + int save = push_path_buffer(argv[i]); + bool exists = lstat(get_path_buffer(), &s) >= 0; + mv_dir(exists); + pop_path_buffer(save); + } + + return EXIT_SUCCESS; +} |