diff --git a/coreutils/cp.c b/coreutils/cp.c index 5d6689d..aff13d5 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -22,11 +22,25 @@ char *make_path(const char *src, const char *dst) { } int write_buffer(int ifd, int ofd) { - char buf[4096]; - size_t bytes = 0; - while ((bytes = read(ifd, buf, sizeof(buf))) > 0) - if (write(ofd, buf, bytes) != bytes) - return 1; + off_t len = lseek(ifd, 0, SEEK_END); + if (len <= 0) + return 1; + + if (ftruncate(ofd, len) < 0) + return 1; + + void *buf_in = mmap(NULL, len, PROT_READ, MAP_SHARED, ifd, 0); + if (buf_in == MAP_FAILED) + return 1; + + void *buf_out = mmap(NULL, len, PROT_WRITE, MAP_SHARED, ofd, 0); + if (buf_out == MAP_FAILED) + return 1; + + memcpy(buf_out, buf_in, len); + + if (munmap(buf_in, len) || munmap(buf_out, len)) + return 1; return 0; @@ -37,7 +51,7 @@ int copy(const char *src, const char *dst) { if (ifd < 0) return 1; - int ofd = open(dst, O_CREAT | O_TRUNC | O_WRONLY, 0666); + int ofd = open(dst, O_CREAT | O_TRUNC | O_RDWR, 0644); if (ofd < 0) { close(ifd); return 1; @@ -62,7 +76,8 @@ int get_stat(const char *path, struct stat *stat_path) { int cptree(const char *src, const char *dst) { struct stat stat_path; - get_stat(src, &stat_path); + if (get_stat(src, &stat_path)) + return 1; if (S_ISDIR(stat_path.st_mode) == 0) { if (copy(src, dst)) { @@ -73,9 +88,8 @@ int cptree(const char *src, const char *dst) { return 0; } - else if (mkdir(dst, 0777) < 0) { + else if (mkdir(dst, 0777) < 0) fprintf(stderr, "cp: %s\n", strerror(errno)); - } DIR *dir = opendir(src); if (dir == NULL) { @@ -107,10 +121,34 @@ int cptree(const char *src, const char *dst) { } int main(const int argc, const char **argv) { - if (argc < 2 || !strcmp(argv[1], "-h")) { - printf("cp [Src] [Dst]\n"); - return 0; + + int i; + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') + break; + + else if (!strcmp(argv[i], "-h")) { + printf("cp [Src] [Dst]\n"); + return 0; + } } - return cptree(argv[1], argv[2]); + int ret = 0; + if (argc - i == 2) + ret = cptree(argv[i], argv[argc - 1]); + + else { + for (; i < argc - 1; i++) { + char *new_path = make_path(argv[argc - 1], basename(argv[i])); + if (new_path == NULL) + return 1; + + if (copy(argv[i], new_path)) + ret = 1; + + free(new_path); + } + } + + return ret; }