diff options
author | Manuel Novoa III <mjn3@codepoet.org> | 2003-03-19 09:13:01 +0000 |
---|---|---|
committer | Manuel Novoa III <mjn3@codepoet.org> | 2003-03-19 09:13:01 +0000 |
commit | cad5364599eb5062d59e0c397ed638ddd61a8d5d (patch) | |
tree | a318d0f03aa076c74b576ea45dc543a5669e8e91 /coreutils/mv.c | |
parent | e01f9662a5bd5d91be4f6b3941b57fff73cd5af1 (diff) | |
download | busybox-w32-cad5364599eb5062d59e0c397ed638ddd61a8d5d.tar.gz busybox-w32-cad5364599eb5062d59e0c397ed638ddd61a8d5d.tar.bz2 busybox-w32-cad5364599eb5062d59e0c397ed638ddd61a8d5d.zip |
Major coreutils update.
Diffstat (limited to 'coreutils/mv.c')
-rw-r--r-- | coreutils/mv.c | 203 |
1 files changed, 88 insertions, 115 deletions
diff --git a/coreutils/mv.c b/coreutils/mv.c index 1c4a34788..ae0ee92e4 100644 --- a/coreutils/mv.c +++ b/coreutils/mv.c | |||
@@ -2,7 +2,6 @@ | |||
2 | /* | 2 | /* |
3 | * Mini mv implementation for busybox | 3 | * Mini mv implementation for busybox |
4 | * | 4 | * |
5 | * | ||
6 | * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> | 5 | * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> |
7 | * | 6 | * |
8 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -21,148 +20,122 @@ | |||
21 | * | 20 | * |
22 | */ | 21 | */ |
23 | 22 | ||
23 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | ||
24 | * | ||
25 | * Size reduction and improved error checking. | ||
26 | */ | ||
27 | |||
24 | #include <sys/types.h> | 28 | #include <sys/types.h> |
25 | #include <sys/stat.h> | 29 | #include <sys/stat.h> |
26 | #include <unistd.h> | 30 | #include <unistd.h> |
27 | #include <dirent.h> | 31 | #include <dirent.h> |
28 | #include <errno.h> | 32 | #include <errno.h> |
29 | #include <stdlib.h> | 33 | #include <stdlib.h> |
30 | |||
31 | #include "busybox.h" | 34 | #include "busybox.h" |
35 | #include "libcoreutils/coreutils.h" | ||
32 | 36 | ||
33 | static int flags; | 37 | static const char *fmt = "cannot overwrite %sdirectory with %sdirectory"; |
34 | 38 | ||
35 | static int manual_rename(const char *source, const char *dest) | 39 | extern int mv_main(int argc, char **argv) |
36 | { | 40 | { |
37 | struct stat source_stat; | 41 | struct stat source_stat; |
38 | struct stat dest_stat; | 42 | struct stat dest_stat; |
39 | int source_exists = 1; | 43 | const char *last; |
40 | int dest_exists = 1; | 44 | const char *dest; |
45 | int dest_exists; | ||
46 | int source_exists; | ||
47 | int opt; | ||
48 | int flags = 0; | ||
49 | int status = 0; | ||
41 | 50 | ||
42 | if (stat(source, &source_stat) < 0) { | 51 | while ((opt = getopt(argc, argv, "fi")) > 0) { |
43 | if (errno != ENOENT) { | 52 | flags &= ~(FILEUTILS_INTERACTIVE | FILEUTILS_FORCE); |
44 | perror_msg("unable to stat `%s'", source); | 53 | if (opt == 'i') { |
45 | return -1; | 54 | flags |= FILEUTILS_INTERACTIVE; |
55 | } else if (opt == 'f') { | ||
56 | flags |= FILEUTILS_FORCE; | ||
57 | } else { | ||
58 | bb_show_usage(); | ||
46 | } | 59 | } |
47 | source_exists = 0; | ||
48 | } | 60 | } |
49 | 61 | ||
50 | if (stat(dest, &dest_stat) < 0) { | 62 | if (optind + 2 > argc) |
51 | if (errno != ENOENT) { | 63 | bb_show_usage(); |
52 | perror_msg("unable to stat `%s'", dest); | ||
53 | return -1; | ||
54 | } | ||
55 | dest_exists = 0; | ||
56 | } | ||
57 | 64 | ||
58 | if (dest_exists) { | 65 | last = argv[argc - 1]; |
59 | if (S_ISDIR(dest_stat.st_mode) && | 66 | argv += optind; |
60 | (!source_exists || !S_ISDIR(source_stat.st_mode))) { | ||
61 | error_msg("cannot overwrite directory with non-directory"); | ||
62 | return -1; | ||
63 | } | ||
64 | 67 | ||
65 | if (!S_ISDIR(dest_stat.st_mode) && source_exists && | 68 | if (optind + 2 == argc) { |
66 | S_ISDIR(source_stat.st_mode)) { | 69 | if ((dest_exists = cp_mv_stat(last, &dest_stat)) < 0) { |
67 | error_msg("cannot overwrite non-directory with directory"); | 70 | return 1; |
68 | return -1; | ||
69 | } | 71 | } |
70 | 72 | ||
71 | if (unlink(dest) < 0) { | 73 | if (!(dest_exists & 2)) { |
72 | perror_msg("cannot remove `%s'", dest); | 74 | dest = last; |
73 | return -1; | 75 | goto DO_MOVE; |
74 | } | 76 | } |
75 | } | 77 | } |
78 | |||
79 | do { | ||
80 | dest = concat_path_file(last, | ||
81 | bb_get_last_path_component(*argv)); | ||
76 | 82 | ||
77 | if (copy_file(source, dest, | 83 | if ((dest_exists = cp_mv_stat(dest, &dest_stat)) < 0) { |
78 | FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) < 0) | 84 | goto RET_1; |
79 | return -1; | ||
80 | |||
81 | if (remove_file(source, FILEUTILS_RECUR | FILEUTILS_FORCE) < 0) | ||
82 | return -1; | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int move_file(const char *source, const char *dest) | ||
88 | { | ||
89 | struct stat dest_stat; | ||
90 | int dest_exists = 1; | ||
91 | |||
92 | if (stat(dest, &dest_stat) < 0) { | ||
93 | if (errno != ENOENT) { | ||
94 | perror_msg("unable to stat `%s'", dest); | ||
95 | return -1; | ||
96 | } | 85 | } |
97 | dest_exists = 0; | ||
98 | } | ||
99 | 86 | ||
100 | if (dest_exists && !(flags & FILEUTILS_FORCE) && | 87 | DO_MOVE: |
88 | |||
89 | if (dest_exists && !(flags & FILEUTILS_FORCE) && | ||
101 | ((access(dest, W_OK) < 0 && isatty(0)) || | 90 | ((access(dest, W_OK) < 0 && isatty(0)) || |
102 | (flags & FILEUTILS_INTERACTIVE))) { | 91 | (flags & FILEUTILS_INTERACTIVE))) { |
103 | fprintf(stderr, "mv: overwrite `%s'? ", dest); | 92 | if (fprintf(stderr, "mv: overwrite `%s'? ", dest) < 0) { |
104 | if (!ask_confirmation()) | 93 | goto RET_1; /* Ouch! fprintf failed! */ |
105 | return 0; | 94 | } |
106 | } | 95 | if (!bb_ask_confirmation()) |
107 | 96 | goto RET_0; | |
108 | if (rename(source, dest) < 0) { | 97 | } |
109 | if (errno == EXDEV) | 98 | |
110 | return manual_rename(source, dest); | 99 | if (rename(*argv, dest) < 0) { |
111 | 100 | if (errno != EXDEV) { | |
112 | perror_msg("unable to rename `%s'", source); | 101 | bb_perror_msg("unable to rename `%s'", *argv); |
113 | return -1; | 102 | } else if ((source_exists = cp_mv_stat(*argv, &source_stat)) >= 0) { |
114 | } | 103 | if (dest_exists) { |
115 | 104 | if (dest_exists & 2) { | |
116 | return 0; | 105 | if (!(source_exists & 2)) { |
117 | } | 106 | bb_error_msg(fmt, "", "non-"); |
118 | 107 | goto RET_1; | |
119 | extern int mv_main(int argc, char **argv) | 108 | } |
120 | { | 109 | } else { |
121 | int status = 0; | 110 | if (source_exists & 2) { |
122 | int opt; | 111 | bb_error_msg(fmt, "non-", ""); |
123 | int i; | 112 | goto RET_1; |
124 | 113 | } | |
125 | while ((opt = getopt(argc, argv, "fi")) != -1) | 114 | } |
126 | switch (opt) { | 115 | if (unlink(dest) < 0) { |
127 | case 'f': | 116 | bb_perror_msg("cannot remove `%s'", dest); |
128 | flags &= ~FILEUTILS_INTERACTIVE; | 117 | goto RET_1; |
129 | flags |= FILEUTILS_FORCE; | 118 | } |
130 | break; | 119 | } |
131 | case 'i': | 120 | |
132 | flags &= ~FILEUTILS_FORCE; | 121 | if ((copy_file(*argv, dest, |
133 | flags |= FILEUTILS_INTERACTIVE; | 122 | FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) >= 0) |
134 | break; | 123 | && (remove_file(*argv, FILEUTILS_RECUR | FILEUTILS_FORCE) >= 0) |
135 | default: | 124 | ) { |
136 | show_usage(); | 125 | goto RET_0; |
137 | } | 126 | } |
138 | 127 | ||
139 | if (optind + 2 > argc) | 128 | } |
140 | show_usage(); | 129 | RET_1: |
141 | 130 | status = 1; | |
142 | if (optind + 2 == argc) { | ||
143 | struct stat dest_stat; | ||
144 | int dest_exists = 1; | ||
145 | |||
146 | if (stat(argv[optind + 1], &dest_stat) < 0) { | ||
147 | if (errno != ENOENT) | ||
148 | perror_msg_and_die("unable to stat `%s'", argv[optind + 1]); | ||
149 | dest_exists = 0; | ||
150 | } | 131 | } |
151 | 132 | ||
152 | if (!dest_exists || !S_ISDIR(dest_stat.st_mode)) { | 133 | RET_0: |
153 | if (move_file(argv[optind], argv[optind + 1]) < 0) | 134 | if (dest != last) { |
154 | status = 1; | 135 | free((void *) dest); |
155 | return status; | ||
156 | } | 136 | } |
157 | } | 137 | |
158 | 138 | } while (*++argv != last); | |
159 | for (i = optind; i < argc - 1; i++) { | 139 | |
160 | char *dest = concat_path_file(argv[argc - 1], | 140 | exit(status); |
161 | get_last_path_component(argv[i])); | ||
162 | if (move_file(argv[i], dest) < 0) | ||
163 | status = 1; | ||
164 | free(dest); | ||
165 | } | ||
166 | |||
167 | return status; | ||
168 | } | 141 | } |