diff options
Diffstat (limited to 'src/commands/cp.c')
-rw-r--r-- | src/commands/cp.c | 240 |
1 files changed, 0 insertions, 240 deletions
diff --git a/src/commands/cp.c b/src/commands/cp.c deleted file mode 100644 index df88155..0000000 --- a/src/commands/cp.c +++ /dev/null @@ -1,240 +0,0 @@ -#include "../command.h" -#include <dirent.h> -#include <limits.h> -#include <stdio.h> -#include <sys/stat.h> -#include <unistd.h> - -static struct { - bool recurse; - bool preserve; - bool sym_link; - bool hard_link; - bool verbose; -} flags; - -static void help(void) { - printf("Usage: cp [-rplsv] SOURCE... DEST\n\n"); - printf("Copy SOURCEs to DEST\n\n"); - printf("\t-R,-r\tRecurse\n"); - printf("\t-p\tPreserve file attributes if possible\n"); - printf("\t-l,-s\tCreate (sym)links\n"); - printf("\t-v\tVerbose\n"); -} - -static int short_arg(char c, char* next) { - UNUSED(next); - switch (c) { - case 'R': - case 'r': - flags.recurse = true; - break; - case 'p': - flags.preserve = true; - break; - case 'l': - flags.hard_link = true; - flags.sym_link = false; - break; - case 's': - flags.sym_link = true; - flags.hard_link = false; - break; - case 'v': - flags.verbose = true; - break; - default: - return ARG_INVALID; - } - return ARG_UNUSED; -} - -static bool copy_file(char* from, char* to) { - #define BS 1024 - - FILE *from_f, *to_f; - char buf[BS]; - int read; - - from_f = get_file_s(from, "r"); - if (from_f == NULL) { return false; } - - to_f = get_file_s(to, "w"); - if (to_f == NULL) { fclose(from_f); return false; } - - - while ((read = fread(buf, 1, BS, from_f)) > 0) { - fwrite(buf, 1, read, to_f); - } - - if (flags.verbose) { - output("copied '%s'", from); - } - - return true; -} - -static bool symlink_file(char* from, char* to) { - if (symlink(from, to) < 0) { - error_s("failed to symlink '%s': %s", from, strerror(errno)); - return false; - } else if (flags.verbose) { - output("symlinked '%s'", from); - } - return true; -} - -static bool hardlink_file(char* from, char* to) { - if (link(from, to) < 0) { - error_s("failed to hardlink '%s': %s", from, strerror(errno)); - return false; - } else if (flags.verbose) { - output("hardlinked '%s'", from); - } - return true; -} - -static void run_copy(struct stat* s) { - - char* from = get_path_buffer(); - char* to = get_path_buffer_2(); - - bool result; - if (flags.sym_link) { - result = symlink_file(from, to); - } else if (flags.hard_link) { - result = hardlink_file(from, to); - } else { - result = copy_file(from, to); - } - - if (!result) return; - if (!flags.preserve) return; - - if (chmod(to, s->st_mode) < 0) { - error_s("cannot chmod '%s': %s", to, strerror(errno)); - return; - } - - if (chown(to, s->st_uid, s->st_gid) < 0) { - error_s("cannot chown '%s': %s", to, strerror(errno)); - return; - } -} - -static void cp_file(char* path); - -static void cp_directory(struct stat* s) { - - DIR* d; - struct dirent* file; - - if (!flags.recurse) { - error_s("-r not specified; omitting directory '%s'", get_path_buffer()); - return; - } - - if (mkdir(get_path_buffer_2(), s->st_mode) < 0 && errno != EEXIST) { - error_s("cannot create directory '%s': %s", get_path_buffer_2(), strerror(errno)); - return; - } - - d = opendir(get_path_buffer()); - - if (d == NULL) { - error_s("cannot open directory '%s': %s", get_path_buffer(), strerror(errno)); - return; - } - - while ((file = readdir(d)) != NULL) { - if (is_dot_dir(file->d_name)) continue; - cp_file(file->d_name); - } -} - -static char* get_file_name(char* path) { - int last = 0; - int i = 0; - - if (path[0] == '\0') return path; - - while (true) { - if (path[i+1] == '\0') break; - if (path[i] == '/') { - last = i; - } - i++; - } - - if (last == 0) return path; - else return path + last + 1; -} - -static void cp_file(char* path) { - - int save = push_path_buffer(path); - int save2 = push_path_buffer_2(get_file_name(path)); - - struct stat s; - if (lstat(get_path_buffer(), &s) < 0) { - pop_path_buffer(save); - error_s("cannot stat '%s': %s", get_path_buffer(), strerror(errno)); - return; - } - - if (S_ISDIR(s.st_mode)) { - cp_directory(&s); - } else { - run_copy(&s); - } - - pop_path_buffer(save); - pop_path_buffer_2(save2); -} - -COMMAND(cp) { - - int start, i; - struct stat s; - - flags.hard_link = false; - flags.sym_link = false; - flags.preserve = false; - flags.recurse = false; - flags.verbose = false; - - start = parse_args(argc, argv, help, short_arg, NULL); - - if (argc - start < 2) { - global_help(help); - } - - /* only when 2 args and first is a file, the 2nd will be a file */ - if (argc - start == 2) { - struct stat s; - if (lstat(argv[start], &s) < 0) { - error("cannot stat '%s': %s", argv[start], strerror(errno)); - } - push_path_buffer(argv[argc-2]); - push_path_buffer_2(argv[argc-1]); - if (!S_ISDIR(s.st_mode)) { - run_copy(&s); - } else { - cp_directory(&s); - } - return EXIT_SUCCESS; - } - - /* push directory */ - push_path_buffer_2(argv[argc-1]); - - if (lstat(get_path_buffer_2(), &s) < 0) { - error("target: '%s': %s", get_path_buffer_2(), strerror(errno)); - } - - for (i = start; i < argc - 1; i++) { - cp_file(argv[i]); - } - - return EXIT_SUCCESS; -} |