1 #ifndef lint 2 static char *sccsid = "@(#)cp.c 4.5 82/05/07"; 3 #endif 4 5 /* 6 * cp 7 */ 8 #include <stdio.h> 9 #include <sys/param.h> 10 #include <sys/stat.h> 11 #include <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 fprintf(stderr, "cp: "); perror(from); 70 return (1); 71 } 72 if (fstat(fold, &stfrom) < 0) { 73 fprintf(stderr, "cp: "); perror(from); 74 return (1); 75 } 76 if (stat(to, &stto) >= 0 && 77 (stto.st_mode&S_IFMT) == S_IFDIR) { 78 last = rindex(from, '/'); 79 if (last) last++; else last = from; 80 if (strlen(to) + strlen(last) >= BSIZE - 1) { 81 fprintf(stderr, "cp: %s/%s: Name too long", to, last); 82 return(1); 83 } 84 (void) sprintf(destname, "%s/%s", to, last); 85 to = destname; 86 } 87 if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) { 88 (void) close(fold); 89 if (stat(to, &stto) < 0) { 90 if (mkdir(to, (int)stfrom.st_mode) < 0) 91 return (1); 92 } else if ((stto.st_mode&S_IFMT) != S_IFDIR) { 93 fprintf(stderr, "cp: %s: Not a directory.\n", to); 94 return (1); 95 } 96 return (rcopy(from, to)); 97 } 98 if (stat(to, &stto) >= 0) { 99 if (stfrom.st_dev == stto.st_dev && 100 stfrom.st_ino == stto.st_ino) { 101 fprintf(stderr, "cp: Cannot copy file to itself.\n"); 102 return (1); 103 } 104 if (iflag) { 105 int i, c; 106 107 fprintf (stderr, "overwrite %s? ", to); 108 i = c = getchar(); 109 while (c != '\n' && c != EOF) 110 c = getchar(); 111 if (i != 'y') 112 return(1); 113 } 114 } 115 fnew = creat(to, (int)stfrom.st_mode); 116 if (fnew < 0) { 117 fprintf(stderr, "cp: "); 118 perror(to); 119 (void) close(fold); return(1); 120 } 121 for (;;) { 122 n = read(fold, buf, BSIZE); 123 if (n == 0) 124 break; 125 if (n < 0) { 126 fprintf(stderr, "cp: "); perror(from); 127 (void) close(fold); (void) close(fnew); return (1); 128 } 129 if (write(fnew, buf, n) != n) { 130 fprintf(stderr, "cp: "); perror(to); 131 (void) close(fold); (void) close(fnew); return (1); 132 } 133 } 134 (void) close(fold); (void) close(fnew); return (0); 135 } 136 137 rcopy(from, to) 138 char *from, *to; 139 { 140 DIR *fold = opendir(from); 141 struct direct *dp; 142 int errs = 0; 143 char fromname[BUFSIZ]; 144 145 if (fold == 0) { 146 perror(from); 147 return (1); 148 } 149 for (;;) { 150 dp = readdir(fold); 151 if (dp == 0) { 152 closedir(fold); 153 return (errs); 154 } 155 if (dp->d_ino == 0) 156 continue; 157 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 158 continue; 159 if (strlen(from) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) { 160 fprintf(stderr, "cp: %s/%s: Name too long.\n", 161 from, dp->d_name); 162 errs++; 163 continue; 164 } 165 (void) sprintf(fromname, "%s/%s", from, dp->d_name); 166 errs += copy(fromname, to); 167 } 168 } 169 170 mkdir(name, mode) 171 char *name; 172 int mode; 173 { 174 char *argv[4]; 175 int pid, rc; 176 177 argv[0] = "mkdir"; 178 argv[1] = name; 179 argv[2] = 0; 180 pid = fork(); 181 if (pid < 0) { 182 perror("cp"); 183 return (1); 184 } 185 if (pid) { 186 while (wait(&rc) != pid) 187 continue; 188 if (rc == 0) 189 if (chmod(name, mode) < 0) { 190 perror(name); 191 rc = 1; 192 } 193 return (rc); 194 } 195 execv("/bin/mkdir", argv); 196 execv("/usr/bin/mkdir", argv); 197 perror("mkdir"); 198 _exit(1); 199 /*NOTREACHED*/ 200 } 201