1 /* 2 0280420002000: TODO: Add GNU options support. 3 0280420002001: TODO: Fix support for the Preserve option (s[ug]id, access time) 4 5 */ 6 7 #include <stdio.h> 8 #include <unistd.h> 9 #include <stdlib.h> 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 #include <fcntl.h> 13 #include <string.h> 14 #include "version.h" 15 #include "cp.h" 16 17 extern char *optarg; 18 extern int optind, opterr, optopt; 19 20 int cp_main (int argc, char **argv) { 21 struct stat statinf; 22 struct stat statinf2; 23 char *destdir=NULL; 24 char buff[4096]; 25 char read_buff[127]; 26 char option_force=0; 27 char option_try_again=0; 28 char option_interactive=0; 29 char option_preserve=0; 30 char option_recurse=0; 31 char ch; 32 int in_fd=-1, out_fd=-1; 33 int i,x; 34 int error_code=0; 35 36 while ( (ch=getopt(argc,argv,"fipRr")) != -1) { 37 switch (ch) { 38 case 'f': 39 option_force=1; 40 break; 41 case 'i': 42 option_interactive=1; 43 break; 44 case 'p': 45 46 option_preserve=1; 47 break; 48 case 'R': 49 case 'r': 50 /* TODO: Make recursive copying work. */ 51 option_recurse=1; 52 break; 53 default: 54 } 55 } 56 57 if ((argc-optind)<2) { 58 write(STDERR_FILENO, "cp: missing file argument\n", 26); 59 return(-1); 60 } 61 62 statinf.st_mode=0; 63 stat(argv[argc-1], &statinf); 64 if (S_ISDIR(statinf.st_mode)) { 65 destdir=argv[argc-1]; 66 } else { 67 if ((argc-optind)!=2) { 68 write(STDERR_FILENO, "cp: when copying multiple files, last argument must be a directory\n", 67); 69 return(-1); 70 } 71 } 72 73 for (i=optind;i<argc-1;i++) { 74 if (destdir==NULL) { 75 strncpy(buff,argv[argc-1],sizeof(buff)-1); 76 } else { 77 sprintf(buff, "%s/%s", destdir, argv[i]); 78 } 79 80 if (option_interactive) { 81 if (!access(buff,F_OK)) { 82 write(STDERR_FILENO, "cp: overwrite `", 15); 83 write(STDERR_FILENO, buff, strlen(buff)); 84 write(STDERR_FILENO, "'? ", 3); 85 read(STDIN_FILENO, &read_buff, sizeof(read_buff)); 86 if (read_buff[0]!='Y' && read_buff[0]!='y') goto loop; 87 } 88 } 89 90 stat(argv[i], &statinf); 91 stat(buff, &statinf2); 92 if (statinf.st_ino==statinf2.st_ino) { 93 write(STDERR_FILENO, "cp: `", 5); 94 write(STDERR_FILENO, argv[i], strlen(argv[i])); 95 write(STDERR_FILENO, "' and `", 7); 96 write(STDERR_FILENO, buff, strlen(buff)); 97 write(STDERR_FILENO, "' are the same file\n", 20); 98 error_code=-1; 99 goto loop; 100 } 101 102 top: 103 if ((out_fd=open(buff, O_WRONLY|O_CREAT|O_TRUNC, statinf.st_mode))<0) { 104 if (option_force && option_try_again==0) { 105 option_try_again=1; 106 unlink(buff); 107 goto top; 108 } 109 option_try_again=0; 110 write(STDERR_FILENO, "cp: ", 4); 111 perror(buff); 112 error_code=-1; 113 goto loop; 114 } 115 if (option_preserve) { 116 #ifndef GO32 117 fchown(out_fd, statinf.st_uid, statinf.st_gid); 118 #endif 119 } 120 if ((in_fd=open(argv[i], O_RDONLY))<0) { 121 write(STDERR_FILENO, "cp: ", 4); 122 perror(argv[i]); 123 close(out_fd); 124 goto loop; 125 } 126 while (1) { 127 if ((x=read(in_fd, &buff, sizeof(buff)))<1) break; 128 write(out_fd, &buff, x); 129 } 130 close(in_fd); 131 close(out_fd); 132 out_fd=-1; 133 loop: 134 } 135 136 137 return(error_code); 138 } |