00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034 #include <getopt.h>
00035 #include <str.h>
00036 #include <fcntl.h>
00037 #include "config.h"
00038 #include "util.h"
00039 #include "errors.h"
00040 #include "entry.h"
00041 #include "cp.h"
00042 #include "cmds.h"
00043
00044 #define CP_VERSION "0.0.1"
00045 #define CP_DEFAULT_BUFLEN 1024
00046
00047 static const char *cmdname = "cp";
00048
00049 static struct option const long_options[] = {
00050 { "buffer", required_argument, 0, 'b' },
00051 { "force", no_argument, 0, 'f' },
00052 { "recursive", no_argument, 0, 'r' },
00053 { "help", no_argument, 0, 'h' },
00054 { "version", no_argument, 0, 'v' },
00055 { "verbose", no_argument, 0, 'V' },
00056 { 0, 0, 0, 0 }
00057 };
00058
00059 static int strtoint(const char *s1)
00060 {
00061 long t1;
00062
00063 if (-1 == (t1 = strtol(s1, (char **) NULL, 10)))
00064 return -1;
00065
00066 if (t1 <= 0)
00067 return -1;
00068
00069 return (int) t1;
00070 }
00071
00072 static int64_t copy_file(const char *src, const char *dest,
00073 size_t blen, int vb)
00074 {
00075 int fd1, fd2, bytes = 0;
00076 off64_t total = 0;
00077 int64_t copied = 0;
00078 char *buff = NULL;
00079
00080 if (vb)
00081 printf("Copying %s to %s\n", src, dest);
00082
00083 if (-1 == (fd1 = open(src, O_RDONLY))) {
00084 printf("Unable to open source file %s\n", src);
00085 return -1;
00086 }
00087
00088 if (-1 == (fd2 = open(dest, O_CREAT))) {
00089 printf("Unable to open destination file %s\n", dest);
00090 close(fd1);
00091 return -1;
00092 }
00093
00094 total = lseek(fd1, 0, SEEK_END);
00095
00096 if (vb)
00097 printf("%" PRIu64 " bytes to copy\n", total);
00098
00099 lseek(fd1, 0, SEEK_SET);
00100
00101 if (NULL == (buff = (char *) malloc(blen))) {
00102 printf("Unable to allocate enough memory to read %s\n",
00103 src);
00104 copied = -1;
00105 goto out;
00106 }
00107
00108 for (;;) {
00109 ssize_t res;
00110 size_t written = 0;
00111
00112 bytes = read(fd1, buff, blen);
00113 if (bytes <= 0)
00114 break;
00115 copied += bytes;
00116 res = bytes;
00117 do {
00118
00119
00120
00121
00122
00123 bytes = write(fd2, buff + written, res);
00124 if (bytes < 0)
00125 goto err;
00126 written += bytes;
00127 res -= bytes;
00128 } while (res > 0);
00129
00130
00131
00132
00133 if (res != 0) {
00134 printf("\n%zd more bytes than actually exist were copied\n", res);
00135 goto err;
00136 }
00137 }
00138
00139 if (bytes < 0) {
00140 err:
00141 printf("\nError copying %s, (%d)\n", src, bytes);
00142 copied = bytes;
00143 }
00144
00145 out:
00146 close(fd1);
00147 close(fd2);
00148 if (buff)
00149 free(buff);
00150 return copied;
00151 }
00152
00153 void help_cmd_cp(unsigned int level)
00154 {
00155 static char helpfmt[] =
00156 "Usage: %s [options] <source> <dest>\n"
00157 "Options: (* indicates not yet implemented)\n"
00158 " -h, --help A short option summary\n"
00159 " -v, --version Print version information and exit\n"
00160 "* -V, --verbose Be annoyingly noisy about what's being done\n"
00161 "* -f, --force Do not complain when <dest> exists\n"
00162 "* -r, --recursive Copy entire directories\n"
00163 " -b, --buffer ## Set the read buffer size to ##\n"
00164 "Currently, %s is under development, some options may not work.\n";
00165 if (level == HELP_SHORT) {
00166 printf("`%s' copies files and directories\n", cmdname);
00167 } else {
00168 help_cmd_cp(HELP_SHORT);
00169 printf(helpfmt, cmdname, cmdname);
00170 }
00171
00172 return;
00173 }
00174
00175 int cmd_cp(char **argv)
00176 {
00177 unsigned int argc, verbose = 0;
00178 int buffer = 0;
00179 int c, opt_ind;
00180 int64_t ret;
00181
00182 argc = cli_count_args(argv);
00183
00184 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
00185 c = getopt_long(argc, argv, "hvVfrb:", long_options, &opt_ind);
00186 switch (c) {
00187 case 'h':
00188 help_cmd_cp(1);
00189 return CMD_SUCCESS;
00190 case 'v':
00191 printf("%s\n", CP_VERSION);
00192 return CMD_SUCCESS;
00193 case 'V':
00194 verbose = 1;
00195 break;
00196 case 'f':
00197 break;
00198 case 'r':
00199 break;
00200 case 'b':
00201 if (-1 == (buffer = strtoint(optarg))) {
00202 printf("%s: Invalid buffer specification, "
00203 "(should be a number greater than zero)\n",
00204 cmdname);
00205 return CMD_FAILURE;
00206 }
00207 if (verbose)
00208 printf("Buffer = %d\n", buffer);
00209 break;
00210 }
00211 }
00212
00213 if (buffer == 0)
00214 buffer = CP_DEFAULT_BUFLEN;
00215
00216 argc -= optind;
00217
00218 if (argc != 2) {
00219 printf("%s: invalid number of arguments. Try %s --help\n",
00220 cmdname, cmdname);
00221 return CMD_FAILURE;
00222 }
00223
00224 ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose);
00225
00226 if (verbose)
00227 printf("%" PRId64 " bytes copied\n", ret);
00228
00229 if (ret >= 0)
00230 return CMD_SUCCESS;
00231 else
00232 return CMD_FAILURE;
00233 }
00234