annotate toys/cp.c @ 562:4d802d438983

Match uint64_t with PRIu64 to avoid warnings on 64 bit builds.
author Rob Landley <rob@landley.net>
date Sat, 14 Apr 2012 21:27:00 -0500
parents 878b94b32866
children 44abf4d901f3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 *
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
7 * See http://www.opengroup.org/onlinepubs/009695399/utilities/cp.html
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"
282
a08f1affe016 Add -v to cp.
Rob Landley <rob@landley.net>
parents: 272
diff changeset
10 USE_CP(NEWTOY(cp, "<2vslrR+rdpa+d+p+rHLPif", 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
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
13 bool "cp"
269
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
14 default y
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
a08f1affe016 Add -v to cp.
Rob Landley <rob@landley.net>
parents: 272
diff changeset
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
da73bb464ce8 Implemented -i for cp
Bryce Fricke
parents: 435
diff changeset
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
a08f1affe016 Add -v to cp.
Rob Landley <rob@landley.net>
parents: 272
diff changeset
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
da73bb464ce8 Implemented -i for cp
Bryce Fricke
parents: 435
diff changeset
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
a08f1affe016 Add -v to cp.
Rob Landley <rob@landley.net>
parents: 272
diff changeset
67 if (toys.optflags & FLAG_v)
a08f1affe016 Add -v to cp.
Rob Landley <rob@landley.net>
parents: 272
diff changeset
68 printf("'%s' -> '%s'\n", src, dst);
a08f1affe016 Add -v to cp.
Rob Landley <rob@landley.net>
parents: 272
diff changeset
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
7c53152a483b Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents: 262
diff changeset
116 if (toys.optflags & FLAG_p) {
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
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
131 int cp_node(char *path, 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 {
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
133 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
134 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
135
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 // 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
137
271
7d625cbdde25 Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents: 269
diff changeset
138 n = node;
7d625cbdde25 Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents: 269
diff changeset
139 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
140 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
141 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
142 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
143 }
269
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
144 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
145 }
269
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
146 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
147
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
148 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
149 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
150 free(s);
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
151
262
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
152 return 0;
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
153 }
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
154
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
155 void cp_main(void)
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 struct stat st;
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
158 int i;
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
159
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
160 // 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
161
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
162 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
163
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
164 // 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
165
262
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
166 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
167 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
168 TT.destisnew++;
262
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
169
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
170 // 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
171
262
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
172 } else {
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
173 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
174 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
175 }
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
176
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
177 // 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
178
262
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
179 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
180 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
181 char *dst;
262
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
182
528
878b94b32866 Comment and whitespace tweaks.
Rob Landley <rob@landley.net>
parents: 503
diff changeset
183 // 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
184
7c53152a483b Make cp pass most of its test suite. Still need to add symlink support.
Rob Landley <rob@landley.net>
parents: 262
diff changeset
185 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
186
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
187 // 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
188
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
189 TT.keep_symlinks = toys.optflags & FLAG_d;
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
190 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
191 {
262
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
192 perror_msg("'%s'", src);
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
193 toys.exitval = 1;
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
194 continue;
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
195 }
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
196
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
197 // 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
198
271
7d625cbdde25 Update cp -r to work better, add relevant tests to test suite.
Rob Landley <rob@landley.net>
parents: 269
diff changeset
199 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
200 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
201 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
202 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
203 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
204 } 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
205 if (S_ISDIR(st.st_mode)) {
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
206 if (toys.optflags & FLAG_r) {
269
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
207 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
208
7b3d9594bf9c Fix -r logic, it needs both source and dest paths explicitly stated.
Rob Landley <rob@landley.net>
parents: 267
diff changeset
209 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
210 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
211 toybuf[sizeof(toybuf)-1]=0;
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 dirtree_read(toybuf, NULL, cp_node);
262
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
213 } 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
214 } 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
215 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
216 }
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
217
262
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
218 return;
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
219
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
220 error_notdir:
70f36d9c5387 Add first pass at cp, totally untested, unlikely to work yet. :)
Rob Landley <rob@landley.net>
parents:
diff changeset
221 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
222 }