Commit | Line | Data |
---|---|---|
31cef89c | 1 | static char *sccsid = "@(#)cp.c 4.1 (Berkeley) 10/1/80"; |
84592a94 BJ |
2 | /* |
3 | * cp oldfile newfile | |
4 | */ | |
5 | ||
6 | #define BSIZE 1024 | |
7 | #include <stdio.h> | |
8 | #include <sys/types.h> | |
9 | #include <sys/stat.h> | |
10 | struct stat stbuf1, stbuf2; | |
11 | char iobuf[BSIZE]; | |
12 | int iflag = 0; /* interactive flag. If this flag is set, | |
13 | * the user is queried before files are | |
14 | * destroyed by cp. | |
15 | */ | |
16 | ||
17 | main(argc, argv) | |
18 | char *argv[]; | |
19 | { | |
20 | register i, r; | |
21 | ||
22 | /* get the flag(s) */ | |
23 | ||
24 | if (argc < 2) | |
25 | goto usage; | |
26 | if (*argv[1] == '-') { | |
27 | argc--; | |
28 | while (*++argv[1] != '\0') | |
29 | switch (*argv[1]) { | |
30 | ||
31 | /* interactive mode */ | |
32 | case 'i': | |
33 | iflag++; | |
34 | break; | |
35 | ||
36 | /* don't live with bad options */ | |
37 | default: | |
38 | goto usage; | |
39 | } | |
40 | argv++; | |
41 | } | |
42 | if (argc < 3) | |
43 | goto usage; | |
44 | if (argc > 3) { | |
45 | if (stat(argv[argc-1], &stbuf2) < 0) | |
46 | goto usage; | |
47 | if ((stbuf2.st_mode&S_IFMT) != S_IFDIR) | |
48 | goto usage; | |
49 | } | |
50 | r = 0; | |
51 | for(i=1; i<argc-1;i++) | |
52 | r |= copy(argv[i], argv[argc-1]); | |
53 | exit(r); | |
54 | usage: | |
55 | fprintf(stderr, "Usage: cp: f1 f2; or cp f1 ... fn d2\n"); | |
56 | exit(1); | |
57 | } | |
58 | ||
59 | copy(from, to) | |
60 | char *from, *to; | |
61 | { | |
62 | int fold, fnew, n; | |
63 | register char *p1, *p2, *bp; | |
64 | int mode; | |
65 | char c,i; | |
66 | if ((fold = open(from, 0)) < 0) { | |
67 | fprintf(stderr, "cp: cannot open %s\n", from); | |
68 | return(1); | |
69 | } | |
70 | fstat(fold, &stbuf1); | |
71 | mode = stbuf1.st_mode; | |
72 | /* is target a directory? */ | |
73 | if (stat(to, &stbuf2) >=0 && | |
74 | (stbuf2.st_mode&S_IFMT) == S_IFDIR) { | |
75 | p1 = from; | |
76 | p2 = to; | |
77 | bp = iobuf; | |
78 | while(*bp++ = *p2++) | |
79 | ; | |
80 | bp[-1] = '/'; | |
81 | p2 = bp; | |
82 | while(*bp = *p1++) | |
83 | if (*bp++ == '/') | |
84 | bp = p2; | |
85 | to = iobuf; | |
86 | } | |
87 | if (stat(to, &stbuf2) >= 0) { | |
88 | if (stbuf1.st_dev == stbuf2.st_dev && | |
89 | stbuf1.st_ino == stbuf2.st_ino) { | |
90 | fprintf(stderr, "cp: cannot copy file to itself.\n"); | |
91 | return(1); | |
92 | } else if (iflag) { | |
93 | fprintf (stderr, "overwrite %s? ", to); | |
94 | i = c = getchar(); | |
95 | while (c != '\n' && c != EOF) | |
96 | c = getchar(); | |
97 | if (i != 'y') | |
98 | return(1); | |
99 | } | |
100 | } | |
101 | if ((fnew = creat(to, mode)) < 0) { | |
102 | fprintf(stderr, "cp: cannot create %s\n", to); | |
103 | close(fold); | |
104 | return(1); | |
105 | } | |
106 | while(n = read(fold, iobuf, BSIZE)) { | |
107 | if (n < 0) { | |
108 | perror("cp: read"); | |
109 | close(fold); | |
110 | close(fnew); | |
111 | return(1); | |
112 | } else | |
113 | if (write(fnew, iobuf, n) != n) { | |
114 | perror("cp: write"); | |
115 | close(fold); | |
116 | close(fnew); | |
117 | return(1); | |
118 | } | |
119 | } | |
120 | close(fold); | |
121 | close(fnew); | |
122 | return(0); | |
123 | } |