summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/cp.c30
-rw-r--r--coreutils/install.c6
-rw-r--r--coreutils/mv.c37
-rw-r--r--libbb/getopt32.c11
4 files changed, 45 insertions, 39 deletions
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 884fbf70f..5b575819c 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -40,12 +40,16 @@ int cp_main(int argc, char **argv)
40 OPT_L = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3), 40 OPT_L = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3),
41 }; 41 };
42 42
43 // Need at least two arguments
43 // Soft- and hardlinking don't mix 44 // Soft- and hardlinking don't mix
44 // -P and -d are the same (-P is POSIX, -d is GNU) 45 // -P and -d are the same (-P is POSIX, -d is GNU)
45 // -r and -R are the same 46 // -r and -R are the same
46 // -a = -pdR 47 // -a = -pdR
47 opt_complementary = "l--s:s--l:Pd:rR:apdR"; 48 opt_complementary = "-2:l--s:s--l:Pd:rR:apdR";
48 flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPHL"); 49 flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPHL");
50 argc -= optind;
51 argv += optind;
52 flags ^= FILEUTILS_DEREFERENCE; /* The sense of this flag was reversed. */
49 /* Default behavior of cp is to dereference, so we don't have to do 53 /* Default behavior of cp is to dereference, so we don't have to do
50 * anything special when we are given -L. 54 * anything special when we are given -L.
51 * The behavior of -H is *almost* like -L, but not quite, so let's 55 * The behavior of -H is *almost* like -L, but not quite, so let's
@@ -60,19 +64,12 @@ int cp_main(int argc, char **argv)
60 } 64 }
61#endif 65#endif
62 66
63 flags ^= FILEUTILS_DEREFERENCE; /* The sense of this flag was reversed. */
64
65 if (optind + 2 > argc) {
66 bb_show_usage();
67 }
68
69 last = argv[argc - 1]; 67 last = argv[argc - 1];
70 argv += optind;
71
72 /* If there are only two arguments and... */ 68 /* If there are only two arguments and... */
73 if (optind + 2 == argc) { 69 if (argc == 2) {
74 s_flags = cp_mv_stat2(*argv, &source_stat, 70 s_flags = cp_mv_stat2(*argv, &source_stat,
75 (flags & FILEUTILS_DEREFERENCE) ? stat : lstat); 71 (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
72 /* TODO: does coreutils cp exit? "cp BAD GOOD dir"... */
76 if (s_flags < 0) 73 if (s_flags < 0)
77 return EXIT_FAILURE; 74 return EXIT_FAILURE;
78 d_flags = cp_mv_stat(last, &dest_stat); 75 d_flags = cp_mv_stat(last, &dest_stat);
@@ -85,19 +82,24 @@ int cp_main(int argc, char **argv)
85 ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags) 82 ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags)
86 ) { 83 ) {
87 /* ...do a simple copy. */ 84 /* ...do a simple copy. */
88 dest = xstrdup(last); 85 dest = last;
89 goto DO_COPY; /* Note: optind+2==argc implies argv[1]==last below. */ 86 goto DO_COPY; /* NB: argc==2 -> *++argv==last */
90 } 87 }
91 } 88 }
92 89
93 do { 90 while (1) {
94 dest = concat_path_file(last, bb_get_last_path_component(*argv)); 91 dest = concat_path_file(last, bb_get_last_path_component(*argv));
95 DO_COPY: 92 DO_COPY:
96 if (copy_file(*argv, dest, flags) < 0) { 93 if (copy_file(*argv, dest, flags) < 0) {
97 status = 1; 94 status = 1;
98 } 95 }
96 if (*++argv == last) {
97 /* possibly leaking dest... */
98 break;
99 }
99 free((void*)dest); 100 free((void*)dest);
100 } while (*++argv != last); 101 }
101 102
103 /* Exit. We are NOEXEC, not NOFORK. We do exit at the end of main() */
102 return status; 104 return status;
103} 105}
diff --git a/coreutils/install.c b/coreutils/install.c
index cf62a0022..d087306d6 100644
--- a/coreutils/install.c
+++ b/coreutils/install.c
@@ -123,10 +123,12 @@ int install_main(int argc, char **argv)
123 copy_flags |= FILEUTILS_PRESERVE_STATUS; 123 copy_flags |= FILEUTILS_PRESERVE_STATUS;
124 } 124 }
125 mode = 0666; 125 mode = 0666;
126 if (flags & OPT_MODE) bb_parse_mode(mode_str, &mode); 126 if (flags & OPT_MODE)
127 bb_parse_mode(mode_str, &mode);
127 uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid(); 128 uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
128 gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid(); 129 gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
129 if (flags & (OPT_OWNER|OPT_GROUP)) umask(0); 130 if (flags & (OPT_OWNER|OPT_GROUP))
131 umask(0);
130 132
131 /* Create directories 133 /* Create directories
132 * don't use bb_make_directory() as it can't change uid or gid 134 * don't use bb_make_directory() as it can't change uid or gid
diff --git a/coreutils/mv.c b/coreutils/mv.c
index 553bb6ecb..1d2977060 100644
--- a/coreutils/mv.c
+++ b/coreutils/mv.c
@@ -47,16 +47,15 @@ int mv_main(int argc, char **argv)
47#if ENABLE_FEATURE_MV_LONG_OPTIONS 47#if ENABLE_FEATURE_MV_LONG_OPTIONS
48 applet_long_options = mv_longopts; 48 applet_long_options = mv_longopts;
49#endif 49#endif
50 opt_complementary = "f-i:i-f"; 50 // Need at least two arguments
51 // -f unsets -i, -i unsets -f
52 opt_complementary = "-2:f-i:i-f";
51 flags = getopt32(argv, "fi"); 53 flags = getopt32(argv, "fi");
52 if (optind + 2 > argc) { 54 argc -= optind;
53 bb_show_usage();
54 }
55
56 last = argv[argc - 1];
57 argv += optind; 55 argv += optind;
56 last = argv[argc - 1];
58 57
59 if (optind + 2 == argc) { 58 if (argc == 2) {
60 dest_exists = cp_mv_stat(last, &dest_stat); 59 dest_exists = cp_mv_stat(last, &dest_stat);
61 if (dest_exists < 0) { 60 if (dest_exists < 0) {
62 return 1; 61 return 1;
@@ -75,11 +74,11 @@ int mv_main(int argc, char **argv)
75 goto RET_1; 74 goto RET_1;
76 } 75 }
77 76
78DO_MOVE: 77 DO_MOVE:
79 78 if (dest_exists && !(flags & OPT_FILEUTILS_FORCE)
80 if (dest_exists && !(flags & OPT_FILEUTILS_FORCE) && 79 && ((access(dest, W_OK) < 0 && isatty(0))
81 ((access(dest, W_OK) < 0 && isatty(0)) || 80 || (flags & OPT_FILEUTILS_INTERACTIVE))
82 (flags & OPT_FILEUTILS_INTERACTIVE))) { 81 ) {
83 if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) { 82 if (fprintf(stderr, "mv: overwrite '%s'? ", dest) < 0) {
84 goto RET_1; /* Ouch! fprintf failed! */ 83 goto RET_1; /* Ouch! fprintf failed! */
85 } 84 }
@@ -91,8 +90,9 @@ DO_MOVE:
91 struct stat source_stat; 90 struct stat source_stat;
92 int source_exists; 91 int source_exists;
93 92
94 if (errno != EXDEV || 93 if (errno != EXDEV
95 (source_exists = cp_mv_stat(*argv, &source_stat)) < 1) { 94 || (source_exists = cp_mv_stat(*argv, &source_stat)) < 1
95 ) {
96 bb_perror_msg("cannot rename '%s'", *argv); 96 bb_perror_msg("cannot rename '%s'", *argv);
97 } else { 97 } else {
98 if (dest_exists) { 98 if (dest_exists) {
@@ -116,15 +116,16 @@ DO_MOVE:
116#if ENABLE_SELINUX 116#if ENABLE_SELINUX
117 copy_flag |= FILEUTILS_PRESERVE_SECURITY_CONTEXT; 117 copy_flag |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
118#endif 118#endif
119 if ((copy_file(*argv, dest, copy_flag) >= 0) && 119 if ((copy_file(*argv, dest, copy_flag) >= 0)
120 (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)) { 120 && (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0)
121 ) {
121 goto RET_0; 122 goto RET_0;
122 } 123 }
123 } 124 }
124RET_1: 125 RET_1:
125 status = 1; 126 status = 1;
126 } 127 }
127RET_0: 128 RET_0:
128 if (dest != last) { 129 if (dest != last) {
129 free((void *) dest); 130 free((void *) dest);
130 } 131 }
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index 3033bf11e..bcb7ea6a0 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -178,7 +178,7 @@ Special characters:
178 This is typically used to implement "print verbose usage message 178 This is typically used to implement "print verbose usage message
179 and exit" option. 179 and exit" option.
180 180
181 "-" A dash between two options causes the second of the two 181 "a-b" A dash between two options causes the second of the two
182 to be unset (and ignored) if it is given on the command line. 182 to be unset (and ignored) if it is given on the command line.
183 183
184 [FIXME: what if they are the same? like "x-x"? Is it ever useful?] 184 [FIXME: what if they are the same? like "x-x"? Is it ever useful?]
@@ -204,7 +204,7 @@ Special characters:
204 if (opt & 4) 204 if (opt & 4)
205 printf("Detected odd -x usage\n"); 205 printf("Detected odd -x usage\n");
206 206
207 "--" A double dash between two options, or between an option and a group 207 "a--b" A double dash between two options, or between an option and a group
208 of options, means that they are mutually exclusive. Unlike 208 of options, means that they are mutually exclusive. Unlike
209 the "-" case above, an error will be forced if the options 209 the "-" case above, an error will be forced if the options
210 are used together. 210 are used together.
@@ -220,7 +220,7 @@ Special characters:
220 "x--x" Variation of the above, it means that -x option should occur 220 "x--x" Variation of the above, it means that -x option should occur
221 at most once. 221 at most once.
222 222
223 "::" A double colon after a char in opt_complementary means that the 223 "a::" A double colon after a char in opt_complementary means that the
224 option can occur multiple times. Each occurrence will be saved as 224 option can occur multiple times. Each occurrence will be saved as
225 a llist_t element instead of char*. 225 a llist_t element instead of char*.
226 226
@@ -240,7 +240,7 @@ Special characters:
240 root:x:0:0:root:/root:/bin/bash 240 root:x:0:0:root:/root:/bin/bash
241 user:x:500:500::/home/user:/bin/bash 241 user:x:500:500::/home/user:/bin/bash
242 242
243 "?" An "?" between an option and a group of options means that 243 "a?b" A "?" between an option and a group of options means that
244 at least one of them is required to occur if the first option 244 at least one of them is required to occur if the first option
245 occurs in preceding command line arguments. 245 occurs in preceding command line arguments.
246 246
@@ -259,7 +259,7 @@ Special characters:
259 For example from "start-stop-daemon" applet: 259 For example from "start-stop-daemon" applet:
260 260
261 // Don't allow -KS -SK, but -S or -K is required 261 // Don't allow -KS -SK, but -S or -K is required
262 opt_complementary = "K:S:?K--S:S--K"; 262 opt_complementary = "K:S:K--S:S--K";
263 flags = getopt32(argv, "KS...); 263 flags = getopt32(argv, "KS...);
264 264
265 265
@@ -268,6 +268,7 @@ Special characters:
268 max 3 args; count uses of '-2'; min 2 args; if there is 268 max 3 args; count uses of '-2'; min 2 args; if there is
269 a '-2' option then unset '-3', '-X' and '-a'; if there is 269 a '-2' option then unset '-3', '-X' and '-a'; if there is
270 a '-2' and after it a '-x' then error out. 270 a '-2' and after it a '-x' then error out.
271 But it's far too obfuscated. Use ':' to separate groups.
271*/ 272*/
272 273
273/* Code here assumes that 'unsigned' is at least 32 bits wide */ 274/* Code here assumes that 'unsigned' is at least 32 bits wide */