aboutsummaryrefslogtreecommitdiff
path: root/coreutils/mv.c
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2003-03-19 09:13:01 +0000
committerManuel Novoa III <mjn3@codepoet.org>2003-03-19 09:13:01 +0000
commitcad5364599eb5062d59e0c397ed638ddd61a8d5d (patch)
treea318d0f03aa076c74b576ea45dc543a5669e8e91 /coreutils/mv.c
parente01f9662a5bd5d91be4f6b3941b57fff73cd5af1 (diff)
downloadbusybox-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.c203
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
33static int flags; 37static const char *fmt = "cannot overwrite %sdirectory with %sdirectory";
34 38
35static int manual_rename(const char *source, const char *dest) 39extern 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
87static 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;
119extern 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}