2023-05-06 04:39:44 +00:00
|
|
|
#include "command.h"
|
|
|
|
#include "lslib.h"
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2023-05-03 16:17:56 +00:00
|
|
|
|
|
|
|
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) {
|
2023-05-04 20:10:37 +00:00
|
|
|
|
|
|
|
char c;
|
|
|
|
|
2023-05-03 16:17:56 +00:00
|
|
|
if (exists && flags.dont_overwrite) {
|
|
|
|
if (flags.verbose) output("skipping '%s'; overwrise is false", get_path_buffer_2());
|
|
|
|
return;
|
|
|
|
}
|
2023-05-04 20:10:37 +00:00
|
|
|
|
2023-05-03 16:17:56 +00:00
|
|
|
if (exists && flags.prompt) {
|
|
|
|
fprintf(stderr, "overwrite '%s'? ", get_path_buffer_2());
|
|
|
|
fflush(stderr);
|
2023-05-04 20:10:37 +00:00
|
|
|
|
|
|
|
c = getchar();
|
2023-05-03 16:17:56 +00:00
|
|
|
if (c != 'y' && c != 'Y') {
|
|
|
|
if (flags.verbose) output("skipping...");
|
|
|
|
return;
|
|
|
|
}
|
2023-05-04 20:10:37 +00:00
|
|
|
|
2023-05-03 16:17:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (rename(get_path_buffer(), get_path_buffer_2()) < 0) {
|
2023-05-15 01:43:02 +00:00
|
|
|
error_s("cannot move '%s'", get_path_buffer());
|
2023-05-03 16:17:56 +00:00
|
|
|
} else if (flags.verbose) {
|
|
|
|
output("moved '%s'", get_path_buffer());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-15 14:57:33 +00:00
|
|
|
COMMAND(mv_main) {
|
2023-05-03 16:17:56 +00:00
|
|
|
|
2023-05-04 20:10:37 +00:00
|
|
|
int start, dest, i;
|
|
|
|
struct stat s;
|
|
|
|
|
2023-05-03 16:17:56 +00:00
|
|
|
flags.refuse_if_dir = false;
|
|
|
|
flags.dont_overwrite = false;
|
|
|
|
flags.prompt = false;
|
|
|
|
flags.verbose = false;
|
|
|
|
|
2023-05-04 20:10:37 +00:00
|
|
|
start = parse_args(argc, argv, help, short_arg, NULL);
|
2023-05-03 16:17:56 +00:00
|
|
|
|
|
|
|
if (argc - start < 2) {
|
|
|
|
global_help(help);
|
|
|
|
}
|
|
|
|
|
|
|
|
push_path_buffer_2(argv[argc-1]);
|
|
|
|
|
2023-05-04 20:10:37 +00:00
|
|
|
dest = true;
|
2023-05-03 16:17:56 +00:00
|
|
|
if (lstat(get_path_buffer_2(), &s) < 0 && argc - start > 2) {
|
|
|
|
dest = false;
|
2023-05-15 01:43:02 +00:00
|
|
|
error("cannot stat '%s'", get_path_buffer_2());
|
2023-05-03 16:17:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2023-05-04 20:10:37 +00:00
|
|
|
for (i = start; i < argc - 1; i++) {
|
2023-05-03 16:17:56 +00:00
|
|
|
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;
|
|
|
|
}
|