diff options
Diffstat (limited to 'coreutils/cp.c')
-rw-r--r-- | coreutils/cp.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/coreutils/cp.c b/coreutils/cp.c new file mode 100644 index 0000000..078a57c --- /dev/null +++ b/coreutils/cp.c @@ -0,0 +1,89 @@ +#include "internal.h" +#include <stdio.h> +#include <sys/stat.h> +#include <sys/fcntl.h> +#include <sys/param.h> +#include <errno.h> + +const char cp_usage[] = "cp [-r] source-file destination-file\n" +"\t\tcp [-r] source-file [source-file ...] destination-directory\n" +"\n" +"\tCopy the source files to the destination.\n" +"\n" +"\t-r:\tRecursively copy all files and directories\n" +"\t\tunder the argument directory."; + +extern int +cp_fn(const struct FileInfo * i) +{ + int sourceFd; + int destinationFd; + const char * destination = i->destination; + struct stat destination_stat; + int status; + char buf[8192]; + char d[PATH_MAX]; + + if ( (i->stat.st_mode & S_IFMT) == S_IFDIR ) { + if ( mkdir(destination, i->stat.st_mode & ~S_IFMT) + != 0 && errno != EEXIST ) { + name_and_error(destination); + return 1; + } + return 0; + } + if ( (sourceFd = open(i->source, O_RDONLY)) < 0 ) { + name_and_error(i->source); + return 1; + } + if ( stat(destination, &destination_stat) == 0 ) { + if ( i->stat.st_ino == destination_stat.st_ino + && i->stat.st_dev == destination_stat.st_dev ) { + fprintf(stderr + ,"copy of %s to %s would copy file to itself.\n" + ,i->source + ,destination); + close(sourceFd); + return 1; + } + } + /* + * If the destination is a directory, create a file within it. + */ + if ( (destination_stat.st_mode & S_IFMT) == S_IFDIR ) { + destination = join_paths( + d + ,i->destination + ,&i->source[i->directoryLength]); + + if ( stat(destination, &destination_stat) == 0 ) { + if ( i->stat.st_ino == destination_stat.st_ino + && i->stat.st_dev == destination_stat.st_dev ) { + fprintf(stderr + ,"copy of %s to %s would copy file to itself.\n" + ,i->source + ,destination); + close(sourceFd); + return 1; + } + } + } + + destinationFd = creat(destination, i->stat.st_mode & 07777); + + while ( (status = read(sourceFd, buf, sizeof(buf))) > 0 ) { + if ( write(destinationFd, buf, status) != status ) { + name_and_error(destination); + close(sourceFd); + close(destinationFd); + return 1; + } + } + close(sourceFd); + close(destinationFd); + if ( status < 0 ) { + name_and_error(i->source); + return 1; + } + return 0; +} |