Mercurial > hg > toybox
annotate toys/posix/cp.c @ 656:6df4ccc0acbe
Regularize command headers, update links to standards documents.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sat, 25 Aug 2012 18:08:51 -0500 |
parents | 2986aa63a021 |
children | 7e846e281e38 |
rev | line source |
---|---|
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
1 /* vi: set sw=4 ts=4: |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
2 * |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
3 * cp.c - Copy files. |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
4 * |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
5 * Copyright 2008 Rob Landley <rob@landley.net> |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
6 * |
656
6df4ccc0acbe
Regularize command headers, update links to standards documents.
Rob Landley <rob@landley.net>
parents:
653
diff
changeset
|
7 * See http://opengroup.org/onlinepubs/9699919799/utilities/cp.html |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
8 * |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
9 * "R+ra+d+p+r" |
583
9802b2afbce8
cp doesn't really need the optstring + logic. Still needs to be updated for new dirtree, though.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
10 USE_CP(NEWTOY(cp, "<2vslrRdpaHLPif", TOYFLAG_BIN)) |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
11 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
12 config CP |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
528
diff
changeset
|
13 bool "cp (broken by dirtree changes)" |
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
528
diff
changeset
|
14 default n |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
15 help |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
16 usage: cp -fiprdal SOURCE... DEST |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
17 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
18 Copy files from SOURCE to DEST. If more than one SOURCE, DEST must |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
19 be a directory. |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
20 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
21 -f force copy by deleting destination file |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
22 -i interactive, prompt before overwriting existing DEST |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
23 -p preserve timestamps, ownership, and permissions |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
24 -r recurse into subdirectories (DEST must be a directory) |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
25 -d don't dereference symlinks |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
26 -a same as -dpr |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
27 -l hard link instead of copying |
282 | 28 -v verbose |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
29 */ |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
30 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
31 #include "toys.h" |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
32 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
33 #define FLAG_f 1 |
497 | 34 #define FLAG_i 2 |
267
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
35 #define FLAG_P 4 // todo |
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
36 #define FLAG_L 8 // todo |
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
37 #define FLAG_H 16 // todo |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
38 #define FLAG_a 32 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
39 #define FLAG_p 64 |
267
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
40 #define FLAG_d 128 // todo |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
41 #define FLAG_R 256 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
42 #define FLAG_r 512 |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
43 #define FLAG_l 1024 // todo |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
44 #define FLAG_s 2048 // todo |
282 | 45 #define FLAG_v 4098 |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
46 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
47 DEFINE_GLOBALS( |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
48 char *destname; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
49 int destisdir; |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
50 int destisnew; |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
51 int keep_symlinks; |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
52 ) |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
53 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
54 #define TT this.cp |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
55 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
56 // Copy an individual file or directory to target. |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
57 |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
58 void cp_file(char *src, char *dst, struct stat *srcst) |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
59 { |
267
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
60 int fdout = -1; |
497 | 61 |
503
3b9dea897dc0
Upgrade yesno() and make cp -i use it.
Rob Landley <rob@landley.net>
parents:
497
diff
changeset
|
62 // -i flag is specified and dst file exists. |
3b9dea897dc0
Upgrade yesno() and make cp -i use it.
Rob Landley <rob@landley.net>
parents:
497
diff
changeset
|
63 if ((toys.optflags&FLAG_i) && !access(dst, R_OK) |
3b9dea897dc0
Upgrade yesno() and make cp -i use it.
Rob Landley <rob@landley.net>
parents:
497
diff
changeset
|
64 && !yesno("cp: overwrite", 1)) |
3b9dea897dc0
Upgrade yesno() and make cp -i use it.
Rob Landley <rob@landley.net>
parents:
497
diff
changeset
|
65 return; |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
66 |
282 | 67 if (toys.optflags & FLAG_v) |
68 printf("'%s' -> '%s'\n", src, dst); | |
69 | |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
70 // Copy directory or file to destination. |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
71 |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
72 if (S_ISDIR(srcst->st_mode)) { |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
73 struct stat st2; |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
74 |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
75 // Always make directory writeable to us, so we can create files in it. |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
76 // |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
77 // Yes, there's a race window between mkdir() and open() so it's |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
78 // possible that -p can be made to chown a directory other than the one |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
79 // we created. The closest we can do to closing this is make sure |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
80 // that what we open _is_ a directory rather than something else. |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
81 |
272
a5652aa22f38
Another cp -r fix, another test case...
Rob Landley <rob@landley.net>
parents:
271
diff
changeset
|
82 if ((mkdir(dst, srcst->st_mode | 0200) && errno != EEXIST) |
a5652aa22f38
Another cp -r fix, another test case...
Rob Landley <rob@landley.net>
parents:
271
diff
changeset
|
83 || 0>(fdout=open(dst, 0)) || fstat(fdout, &st2) |
a5652aa22f38
Another cp -r fix, another test case...
Rob Landley <rob@landley.net>
parents:
271
diff
changeset
|
84 || !S_ISDIR(st2.st_mode)) |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
85 { |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
86 perror_exit("mkdir '%s'", dst); |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
87 } |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
88 } else if (TT.keep_symlinks && S_ISLNK(srcst->st_mode)) { |
267
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
89 char *link = xreadlink(src); |
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
90 |
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
91 // Note: -p currently has no effect on symlinks. How do you get a |
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
92 // filehandle to them? O_NOFOLLOW causes the open to fail. |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
93 if (!link || symlink(link, dst)) perror_msg("link '%s'", dst); |
267
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
94 free(link); |
283
2134fa02ec00
We don't open a destination filehandle for symlinks, so xclose() would barf.
Rob Landley <rob@landley.net>
parents:
282
diff
changeset
|
95 return; |
267
784bc9b0d6df
Make cp pass the rest of its test suite. Needs a bigger test suite (-lsHPLi
Rob Landley <rob@landley.net>
parents:
263
diff
changeset
|
96 } else if (toys.optflags & FLAG_l) { |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
97 if (link(src, dst)) perror_msg("link '%s'"); |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
98 return; |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
99 } else { |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
100 int fdin, i; |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
101 |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
102 fdin = xopen(src, O_RDONLY); |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
103 for (i=2 ; i; i--) { |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
104 fdout = open(dst, O_RDWR|O_CREAT|O_TRUNC, srcst->st_mode); |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
105 if (fdout>=0 || !(toys.optflags & FLAG_f)) break; |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
106 unlink(dst); |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
107 } |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
108 if (fdout<0) perror_exit("%s", dst); |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
109 xsendfile(fdin, fdout); |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
110 close(fdin); |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
111 } |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
112 |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
113 // Inability to set these isn't fatal, some require root access. |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
114 // Can't do fchmod() etc here because -p works on mkdir, too. |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
115 |
583
9802b2afbce8
cp doesn't really need the optstring + logic. Still needs to be updated for new dirtree, though.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
116 if (toys.optflags & (FLAG_p|FLAG_a)) { |
435
e134aebe79c1
Silence really boring compiler warning.
Luis Felipe Strano Moraes <lfelipe@profusion.mobi>
parents:
329
diff
changeset
|
117 int mask = umask(0); |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
118 struct utimbuf ut; |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
119 |
435
e134aebe79c1
Silence really boring compiler warning.
Luis Felipe Strano Moraes <lfelipe@profusion.mobi>
parents:
329
diff
changeset
|
120 (void) fchown(fdout,srcst->st_uid, srcst->st_gid); |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
121 ut.actime = srcst->st_atime; |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
122 ut.modtime = srcst->st_mtime; |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
123 utime(dst, &ut); |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
124 umask(mask); |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
125 } |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
126 xclose(fdout); |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
127 } |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
128 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
129 // Callback from dirtree_read() for each file/directory under a source dir. |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
130 |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
528
diff
changeset
|
131 int cp_node(struct dirtree *node) |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
132 { |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
528
diff
changeset
|
133 char *path = dirtree_path(node, 0); // TODO: use openat() instead |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
134 char *s = path+strlen(path); |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
135 struct dirtree *n; |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
136 |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
137 // Find appropriate chunk of path for destination. |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
138 |
271
7d625cbdde25
Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents:
269
diff
changeset
|
139 n = node; |
7d625cbdde25
Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents:
269
diff
changeset
|
140 if (!TT.destisdir) n = n->parent; |
7d625cbdde25
Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents:
269
diff
changeset
|
141 for (;;n = n->parent) { |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
142 while (s!=path) { |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
143 if (*(--s)=='/') break; |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
144 } |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
145 if (!n) break; |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
146 } |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
147 if (s != path) s++; |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
148 |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
149 s = xmsprintf("%s/%s", TT.destname, s); |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
150 cp_file(path, s, &(node->st)); |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
151 free(s); |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
528
diff
changeset
|
152 free(path); // redo this whole darn function. |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
153 |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
154 return 0; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
155 } |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
156 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
157 void cp_main(void) |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
158 { |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
159 struct stat st; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
160 int i; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
161 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
162 // Grab target argument. (Guaranteed to be there due to "<2" above.) |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
163 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
164 TT.destname = toys.optargs[--toys.optc]; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
165 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
166 // If destination doesn't exist, are we ok with that? |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
167 |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
168 if (stat(TT.destname, &st)) { |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
169 if (toys.optc>1) goto error_notdir; |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
170 TT.destisnew++; |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
171 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
172 // If destination exists... |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
173 |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
174 } else { |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
175 if (S_ISDIR(st.st_mode)) TT.destisdir++; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
176 else if (toys.optc > 1) goto error_notdir; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
177 } |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
178 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
179 // Handle sources |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
180 |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
181 for (i=0; i<toys.optc; i++) { |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
182 char *src = toys.optargs[i]; |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
183 char *dst; |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
184 |
528
878b94b32866
Comment and whitespace tweaks.
Rob Landley <rob@landley.net>
parents:
503
diff
changeset
|
185 // Skip src==dest (TODO check inodes to catch "cp blah ./blah"). |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
186 |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
187 if (!strcmp(src, TT.destname)) continue; |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
188 |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
189 // Skip nonexistent sources. |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
190 |
583
9802b2afbce8
cp doesn't really need the optstring + logic. Still needs to be updated for new dirtree, though.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
191 TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a); |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
192 if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st)) |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
193 { |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
194 perror_msg("'%s'", src); |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
195 toys.exitval = 1; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
196 continue; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
197 } |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
198 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
199 // Copy directory or file. |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
200 |
271
7d625cbdde25
Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents:
269
diff
changeset
|
201 if (TT.destisdir) { |
7d625cbdde25
Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents:
269
diff
changeset
|
202 dst = strrchr(src, '/'); |
7d625cbdde25
Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents:
269
diff
changeset
|
203 if (dst) dst++; |
7d625cbdde25
Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents:
269
diff
changeset
|
204 else dst=src; |
7d625cbdde25
Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents:
269
diff
changeset
|
205 dst = xmsprintf("%s/%s", TT.destname, dst); |
7d625cbdde25
Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents:
269
diff
changeset
|
206 } else dst = TT.destname; |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
207 if (S_ISDIR(st.st_mode)) { |
583
9802b2afbce8
cp doesn't really need the optstring + logic. Still needs to be updated for new dirtree, though.
Rob Landley <rob@landley.net>
parents:
565
diff
changeset
|
208 if (toys.optflags & (FLAG_r|FLAG_R|FLAG_a)) { |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
209 cp_file(src, dst, &st); |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
210 |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
211 TT.keep_symlinks++; |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
212 strncpy(toybuf, src, sizeof(toybuf)-1); |
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
213 toybuf[sizeof(toybuf)-1]=0; |
565
44abf4d901f3
Rewrite dirtree so we don't need readdir, scandir, and fts.h. Rewrite ls (from scratch) to use new dirtree infrastructure. (This breaks everything else that currently uses dirtree.)
Rob Landley <rob@landley.net>
parents:
528
diff
changeset
|
214 dirtree_read(toybuf, cp_node); |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
215 } else error_msg("Skipped dir '%s'", src); |
269
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
216 } else cp_file(src, dst, &st); |
7b3d9594bf9c
Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents:
267
diff
changeset
|
217 if (TT.destisdir) free(dst); |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
218 } |
263
7c53152a483b
Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents:
262
diff
changeset
|
219 |
262
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
220 return; |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
221 |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
222 error_notdir: |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
223 error_exit("'%s' isn't a directory", TT.destname); |
70f36d9c5387
Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff
changeset
|
224 } |