summaryrefslogtreecommitdiff
path: root/command/mv.c
diff options
context:
space:
mode:
Diffstat (limited to 'command/mv.c')
-rw-r--r--command/mv.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/command/mv.c b/command/mv.c
new file mode 100644
index 0000000..adce2b7
--- /dev/null
+++ b/command/mv.c
@@ -0,0 +1,121 @@
+#include "command.h"
+#include "lslib.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.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) {
+
+ char c;
+
+ 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);
+
+ 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) {
+
+ int start, dest, i;
+ struct stat s;
+
+ flags.refuse_if_dir = false;
+ flags.dont_overwrite = false;
+ flags.prompt = false;
+ flags.verbose = false;
+
+ start = parse_args(argc, argv, help, short_arg, NULL);
+
+ if (argc - start < 2) {
+ global_help(help);
+ }
+
+ push_path_buffer_2(argv[argc-1]);
+
+ dest = true;
+ 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 (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;
+}