1 #ifndef lint 2 static char *sccsid = "@(#)cp.c 4.8 83/07/01"; 3 #endif 4 5 /* 6 * cp 7 */ 8 #include <stdio.h> 9 #include <sys/param.h> 10 #include <sys/stat.h> 11 #include <sys/dir.h> 12 13 #define BSIZE 8192 14 15 int iflag; 16 int rflag; 17 char *rindex(), *sprintf(); 18 19 main(argc, argv) 20 int argc; 21 char **argv; 22 { 23 struct stat stb; 24 int rc, i; 25 26 argc--, argv++; 27 while (argc > 0 && **argv == '-') { 28 (*argv)++; 29 while (**argv) switch (*(*argv)++) { 30 31 case 'i': 32 iflag++; break; 33 34 case 'r': 35 rflag++; break; 36 37 default: 38 goto usage; 39 } 40 argc--; argv++; 41 } 42 if (argc < 2) 43 goto usage; 44 if (argc > 2 || rflag) { 45 if (stat(argv[argc-1], &stb) < 0) 46 goto usage; 47 if ((stb.st_mode&S_IFMT) != S_IFDIR) 48 goto usage; 49 } 50 rc = 0; 51 for (i = 0; i < argc-1; i++) 52 rc |= copy(argv[i], argv[argc-1]); 53 exit(rc); 54 usage: 55 fprintf(stderr, 56 "Usage: cp f1 f2; or cp [ -r ] f1 ... fn d2\n"); 57 exit(1); 58 } 59 60 copy(from, to) 61 char *from, *to; 62 { 63 int fold, fnew, n; 64 char *last, destname[BSIZE], buf[BSIZE]; 65 struct stat stfrom, stto; 66 67 fold = open(from, 0); 68 if (fold < 0) { 69 Perror(from); 70 return (1); 71 } 72 if (fstat(fold, &stfrom) < 0) { 73 Perror(from); 74 (void) close(fold); 75 return (1); 76 } 77 if (stat(to, &stto) >= 0 && 78 (stto.st_mode&S_IFMT) == S_IFDIR) { 79 last = rindex(from, '/'); 80 if (last) last++; else last = from; 81 if (strlen(to) + strlen(last) >= BSIZE - 1) { 82 fprintf(stderr, "cp: %s/%s: Name too long", to, last); 83 (void) close(fold); 84 return(1); 85 } 86 (void) sprintf(destname, "%s/%s", to, last); 87 to = destname; 88 } 89 if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) { 90 (void) close(fold); 91 if (stat(to, &stto) < 0) { 92 if (mkdir(to, (int)stfrom.st_mode) < 0) { 93 Perror(to); 94 return (1); 95 } 96 } else if ((stto.st_mode&S_IFMT) != S_IFDIR) { 97 fprintf(stderr, "cp: %s: Not a directory.\n", to); 98 return (1); 99 } 100 return (rcopy(from, to)); 101 } 102 if (stat(to, &stto) >= 0) { 103 if (stfrom.st_dev == stto.st_dev && 104 stfrom.st_ino == stto.st_ino) { 105 fprintf(stderr, "cp: Cannot copy file to itself.\n"); 106 (void) close(fold); 107 return (1); 108 } 109 if (iflag) { 110 int i, c; 111 112 fprintf (stderr, "overwrite %s? ", to); 113 i = c = getchar(); 114 while (c != '\n' && c != EOF) 115 c = getchar(); 116 if (i != 'y') { 117 (void) close(fold); 118 return(1); 119 } 120 } 121 } 122 fnew = creat(to, (int)stfrom.st_mode); 123 if (fnew < 0) { 124 Perror(to); 125 (void) close(fold); return(1); 126 } 127 for (;;) { 128 n = read(fold, buf, BSIZE); 129 if (n == 0) 130 break; 131 if (n < 0) { 132 Perror(from); 133 (void) close(fold); (void) close(fnew); return (1); 134 } 135 if (write(fnew, buf, n) != n) { 136 Perror(to); 137 (void) close(fold); (void) close(fnew); return (1); 138 } 139 } 140 (void) close(fold); (void) close(fnew); return (0); 141 } 142 143 rcopy(from, to) 144 char *from, *to; 145 { 146 DIR *fold = opendir(from); 147 struct direct *dp; 148 int errs = 0; 149 char fromname[BUFSIZ]; 150 151 if (fold == 0) { 152 Perror(from); 153 return (1); 154 } 155 for (;;) { 156 dp = readdir(fold); 157 if (dp == 0) { 158 closedir(fold); 159 return (errs); 160 } 161 if (dp->d_ino == 0) 162 continue; 163 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 164 continue; 165 if (strlen(from) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) { 166 fprintf(stderr, "cp: %s/%s: Name too long.\n", 167 from, dp->d_name); 168 errs++; 169 continue; 170 } 171 (void) sprintf(fromname, "%s/%s", from, dp->d_name); 172 errs += copy(fromname, to); 173 } 174 } 175 176 Perror(s) 177 char *s; 178 { 179 180 fprintf(stderr, "cp: "); 181 perror(s); 182 } 183