comparison toys/posix/cp.c @ 1388:c4f5f82adce6 draft

Implement -HL for cp.
author Rob Landley <rob@landley.net>
date Mon, 14 Jul 2014 05:38:27 -0500
parents 37ea9dff9c27
children ffc7f606ce5b
comparison
equal deleted inserted replaced
1387:a0d26c5e3271 1388:c4f5f82adce6
1 /* Copyright 2008 Rob Landley <rob@landley.net> 1 /* Copyright 2008 Rob Landley <rob@landley.net>
2 * 2 *
3 * See http://opengroup.org/onlinepubs/9699919799/utilities/cp.html 3 * See http://opengroup.org/onlinepubs/9699919799/utilities/cp.html
4 * 4 *
5 * TODO: sHLP 5 * Posix says "cp -Rf dir file" shouldn't delete file, but our -f does.
6 6
7 // This is subtle: MV options must be in same order (right to left) as CP 7 // This is subtle: MV options must be in same order (right to left) as CP
8 // for FLAG_X macros to work out right. 8 // for FLAG_X macros to work out right.
9 9
10 USE_CP(NEWTOY(cp, "<2RHLPp"USE_CP_MORE("rdaslvn")"fi"USE_CP_MORE("[-ni]"), TOYFLAG_BIN)) 10 USE_CP(NEWTOY(cp, "<2RHLPp"USE_CP_MORE("rdaslvn")"fi[-HLPd]"USE_CP_MORE("[-ni]"), TOYFLAG_BIN))
11 USE_CP_MV(OLDTOY(mv, cp, "<2"USE_CP_MORE("vn")"fi"USE_CP_MORE("[-ni]"), TOYFLAG_BIN)) 11 USE_CP_MV(OLDTOY(mv, cp, "<2"USE_CP_MORE("vn")"fi"USE_CP_MORE("[-ni]"), TOYFLAG_BIN))
12 12
13 config CP 13 config CP
14 bool "cp" 14 bool "cp"
15 default y 15 default y
63 -n no clobber (don't overwrite DEST) 63 -n no clobber (don't overwrite DEST)
64 */ 64 */
65 65
66 #define FOR_cp 66 #define FOR_cp
67 #include "toys.h" 67 #include "toys.h"
68
69 // TODO: PLHlsd
70 68
71 GLOBALS( 69 GLOBALS(
72 char *destname; 70 char *destname;
73 struct stat top; 71 struct stat top;
74 ) 72 )
153 // we created. The closest we can do to closing this is make sure 151 // we created. The closest we can do to closing this is make sure
154 // that what we open _is_ a directory rather than something else. 152 // that what we open _is_ a directory rather than something else.
155 153
156 if (!mkdirat(cfd, catch, try->st.st_mode | 0200) || errno == EEXIST) 154 if (!mkdirat(cfd, catch, try->st.st_mode | 0200) || errno == EEXIST)
157 if (-1 != (try->extra = openat(cfd, catch, O_NOFOLLOW))) 155 if (-1 != (try->extra = openat(cfd, catch, O_NOFOLLOW)))
158 if (!fstat(try->extra, &st2)) 156 if (!fstat(try->extra, &st2) && S_ISDIR(st2.st_mode))
159 if (S_ISDIR(st2.st_mode)) return DIRTREE_COMEAGAIN; 157 return DIRTREE_COMEAGAIN
158 | (DIRTREE_SYMFOLLOW*!!(toys.optflags&FLAG_L));
160 159
161 // Hardlink 160 // Hardlink
162 161
163 } else if (flags & FLAG_l) { 162 } else if (flags & FLAG_l) {
164 if (!linkat(tfd, try->name, cfd, catch, 0)) err = 0; 163 if (!linkat(tfd, try->name, cfd, catch, 0)) err = 0;
281 errno = EXDEV; 280 errno = EXDEV;
282 if (toys.which->name[0] == 'm') rc = rename(src, TT.destname); 281 if (toys.which->name[0] == 'm') rc = rename(src, TT.destname);
283 282
284 // Skip nonexistent sources 283 // Skip nonexistent sources
285 if (rc) { 284 if (rc) {
286 if (errno != EXDEV || 285 int symfollow = toys.optflags & (FLAG_H|FLAG_L);
287 !(new = dirtree_add_node(0, src, !(toys.optflags & (FLAG_d|FLAG_a))))) 286
287 if (errno != EXDEV || !(new = dirtree_add_node(0, src, symfollow)))
288 perror_msg("bad '%s'", src); 288 perror_msg("bad '%s'", src);
289 else dirtree_handle_callback(new, cp_node); 289 else dirtree_handle_callback(new, cp_node);
290 } 290 }
291 if (destdir) free(TT.destname); 291 if (destdir) free(TT.destname);
292 } 292 }