.
[coreutils.git] / src / mv.c
blobc431a688c865607d87221159466ecb4b7bae5d3c
1 /* mv -- move or rename files
2 Copyright (C) 86, 89, 90, 91, 95, 96, 97, 1998 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Options:
19 -f, --force Assume a 'y' answer to all questions it would
20 normally ask, and not ask the questions.
22 -i, --interactive Require confirmation from the user before
23 performing any move that would destroy an
24 existing file.
26 -u, --update Do not move a nondirectory that has an
27 existing destination with the same or newer
28 modification time.
30 -v, --verbose List the name of each file as it is moved, and
31 the name it is moved to.
33 -b, --backup
34 -S, --suffix
35 -V, --version-control
36 Backup file creation.
38 Written by Mike Parker and David MacKenzie */
40 #ifdef _AIX
41 #pragma alloca
42 #endif
44 #include <config.h>
45 #include <stdio.h>
46 #include <getopt.h>
47 #include <sys/types.h>
49 #include "system.h"
50 #include "path-concat.h"
51 #include "backupfile.h"
52 #include "closeout.h"
53 #include "error.h"
55 #ifdef HAVE_LCHOWN
56 # define chown(PATH, OWNER, GROUP) lchown(PATH, OWNER, GROUP)
57 #endif
59 char *base_name ();
60 enum backup_type get_version ();
61 int isdir ();
62 int yesno ();
63 int safe_read ();
64 int full_write ();
65 int euidaccess ();
67 /* The name this program was run with. */
68 char *program_name;
70 /* If nonzero, query the user before overwriting files. */
71 static int interactive;
73 /* If nonzero, do not query the user before overwriting unwritable
74 files. */
75 static int override_mode;
77 /* If nonzero, do not move a nondirectory that has an existing destination
78 with the same or newer modification time. */
79 static int update = 0;
81 /* If nonzero, list each file as it is moved. */
82 static int verbose;
84 /* If nonzero, stdin is a tty. */
85 static int stdin_tty;
87 /* If nonzero, display usage information and exit. */
88 static int show_help;
90 /* If nonzero, print the version on standard output and exit. */
91 static int show_version;
93 static struct option const long_options[] =
95 {"backup", no_argument, NULL, 'b'},
96 {"force", no_argument, NULL, 'f'},
97 {"interactive", no_argument, NULL, 'i'},
98 {"suffix", required_argument, NULL, 'S'},
99 {"update", no_argument, &update, 1},
100 {"verbose", no_argument, &verbose, 1},
101 {"version-control", required_argument, NULL, 'V'},
102 {"help", no_argument, &show_help, 1},
103 {"version", no_argument, &show_version, 1},
104 {NULL, 0, NULL, 0}
107 /* If PATH is an existing directory, return nonzero, else 0. */
109 static int
110 is_real_dir (const char *path)
112 struct stat stats;
114 return lstat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
117 /* Apply as many of the file attributes (the struct stat fields: st_atime,
118 st_mtime, st_uid, st_gid, st_mode) of ATTR to FILE as possible.
119 Return non-zero if any operation failed; return zero otherwise. */
121 static int
122 apply_attributes (const char *file, const struct stat *attr)
124 struct utimbuf tv;
125 mode_t mode = attr->st_mode;
126 int fail = 0;
128 /* Try to apply the modtime and access time. */
129 tv.actime = attr->st_atime;
130 tv.modtime = attr->st_mtime;
131 if (utime (file, &tv))
133 error (0, errno, "%s: unable to restore file times", file);
134 fail = 1;
137 /* chown would turn off set[ug]id bits for non-root, so do the
138 chown before the chmod. */
140 /* Try to apply group ID and owner ID. */
141 if (chown (file, attr->st_uid, attr->st_gid))
143 error (0, errno, "%s: unable to restore owner and group IDs", file);
145 /* If the owner and group cannot be preserved, then mask off
146 any setgid and setuid bits. */
147 mode &= (~(S_ISUID | S_ISGID));
148 fail = 1;
151 /* Try to apply file mode. */
152 if (chmod (file, mode & 07777))
154 error (0, errno, "%s: unable to restore file mode", file);
155 fail = 1;
158 return fail;
161 /* Copy regular file SOURCE onto file DEST. SOURCE_STATS must be
162 the result of calling lstat on SOURCE.
163 Return 1 if an error occurred, 0 if successful. */
165 static int
166 copy_reg (const char *source, const char *dest, const struct stat *source_stats)
168 int ifd;
169 int ofd;
170 char buf[1024 * 8];
171 int len; /* Number of bytes read into `buf'. */
173 if (!S_ISREG (source_stats->st_mode))
175 error (0, 0,
176 _("cannot move `%s' across filesystems: Not a regular file"),
177 source);
178 return 1;
181 if (unlink (dest) && errno != ENOENT)
183 error (0, errno, _("cannot remove `%s'"), dest);
184 return 1;
187 ifd = open (source, O_RDONLY, 0);
188 if (ifd < 0)
190 error (0, errno, "%s", source);
191 return 1;
193 ofd = open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600);
194 if (ofd < 0)
196 error (0, errno, "%s", dest);
197 close (ifd);
198 return 1;
201 while ((len = safe_read (ifd, buf, sizeof (buf))) > 0)
203 if (full_write (ofd, buf, len) < 0)
205 error (0, errno, "%s", dest);
206 close (ifd);
207 close (ofd);
208 unlink (dest);
209 return 1;
212 if (len < 0)
214 error (0, errno, "%s", source);
215 close (ifd);
216 close (ofd);
217 unlink (dest);
218 return 1;
221 if (close (ifd) < 0)
223 error (0, errno, "%s", source);
224 close (ofd);
225 return 1;
227 if (close (ofd) < 0)
229 error (0, errno, "%s", dest);
230 return 1;
233 /* Try to apply the attributes of SOURCE to DEST.
234 Each failure gets a diagnostic, but POSIX requires that failure
235 to preserve attributes not change mv's exit status. */
236 apply_attributes (dest, source_stats);
238 return 0;
241 /* Move SOURCE onto DEST. Handles cross-filesystem moves.
242 If SOURCE is a directory, DEST must not exist.
243 Return 0 if successful, non-zero if an error occurred. */
245 static int
246 do_move (const char *source, const char *dest)
248 char *dest_backup = NULL;
249 struct stat source_stats;
250 struct stat dest_stats;
251 int fail;
253 if (lstat (source, &source_stats) != 0)
255 error (0, errno, "%s", source);
256 return 1;
259 if (lstat (dest, &dest_stats) == 0)
262 if (source_stats.st_dev == dest_stats.st_dev
263 && source_stats.st_ino == dest_stats.st_ino)
265 error (0, 0, _("`%s' and `%s' are the same file"), source, dest);
266 return 1;
269 if (S_ISDIR (dest_stats.st_mode))
271 error (0, 0, _("%s: cannot overwrite directory"), dest);
272 return 1;
275 if (!S_ISDIR (source_stats.st_mode) && update
276 && source_stats.st_mtime <= dest_stats.st_mtime)
277 return 0;
279 if (!override_mode && (interactive || stdin_tty)
280 && euidaccess (dest, W_OK))
282 fprintf (stderr, _("%s: replace `%s', overriding mode %04o? "),
283 program_name, dest,
284 (unsigned int) (dest_stats.st_mode & 07777));
285 if (!yesno ())
286 return 0;
288 else if (interactive)
290 fprintf (stderr, _("%s: replace `%s'? "), program_name, dest);
291 if (!yesno ())
292 return 0;
295 if (backup_type != none)
297 char *tmp_backup = find_backup_file_name (dest);
298 if (tmp_backup == NULL)
299 error (1, 0, _("virtual memory exhausted"));
300 dest_backup = (char *) alloca (strlen (tmp_backup) + 1);
301 strcpy (dest_backup, tmp_backup);
302 free (tmp_backup);
303 if (rename (dest, dest_backup))
305 if (errno != ENOENT)
307 error (0, errno, _("cannot backup `%s'"), dest);
308 return 1;
310 else
311 dest_backup = NULL;
315 else if (errno != ENOENT)
317 error (0, errno, "%s", dest);
318 return 1;
321 if (verbose)
322 printf ("%s -> %s\n", source, dest);
324 /* Always try rename first. */
325 fail = rename (source, dest);
327 if (fail)
329 /* This may mean SOURCE and DEST are on different devices.
330 It may also (conceivably) mean that even though they are
331 on the same device, rename isn't implemented for that device.
333 E.g., (from Joel N. Weber),
334 [...] there might someday be cases where you can't rename but you
335 can copy where the device name is the same, especially on Hurd.
336 Consider an ftpfs with a primitive ftp server that supports
337 uploading, downloading and deleting, but not renaming.
339 Also, note that comparing device numbers is not a reliable check
340 for `can-rename'. Some systems can be set up so that files from
341 many different physical devices all have the same st_dev field.
342 This is a feature of some NFS mounting configurations.
344 Try copying-then-removing SOURCE instead.
346 This function used to resort to copying only when rename failed
347 and set errno to EXDEV. */
349 fail = copy_reg (source, dest, &source_stats);
350 if (fail)
352 /* Restore original destination file DEST if made a backup. */
353 if (dest_backup && rename (dest_backup, dest))
354 error (0, errno, _("cannot un-backup `%s'"), dest);
356 else
358 fail = unlink (source);
359 if (fail)
360 error (0, errno, _("cannot remove `%s'"), source);
364 return fail;
367 static int
368 strip_trailing_slashes_2 (char *path)
370 char *end_p = path + strlen (path) - 1;
371 char *slash = end_p;
373 while (slash > path && *slash == '/')
374 *slash-- = '\0';
376 return slash < end_p;
379 /* Move file SOURCE onto DEST. Handles the case when DEST is a directory.
380 DEST_IS_DIR must be nonzero when DEST is a directory or a symlink to a
381 directory and zero otherwise.
382 Return 0 if successful, non-zero if an error occurred. */
384 static int
385 movefile (char *source, char *dest, int dest_is_dir)
387 int dest_had_trailing_slash = strip_trailing_slashes_2 (dest);
388 int fail;
390 /* In addition to when DEST is a directory, if DEST has a trailing
391 slash and neither SOURCE nor DEST is a directory, presume the target
392 is DEST/`basename source`. This converts `mv x y/' to `mv x y/x'.
393 This change means that the command `mv any file/' will now fail
394 rather than performing the move. The case when SOURCE is a
395 directory and DEST is not is properly diagnosed by do_move. */
397 if (dest_is_dir || (dest_had_trailing_slash && !is_real_dir (source)))
399 /* DEST is a directory; build full target filename. */
400 char *src_basename;
401 char *new_dest;
403 /* Remove trailing slashes before taking base_name.
404 Otherwise, base_name ("a/") returns "". */
405 strip_trailing_slashes_2 (source);
407 src_basename = base_name (source);
408 new_dest = path_concat (dest, src_basename, NULL);
409 if (new_dest == NULL)
410 error (1, 0, _("virtual memory exhausted"));
411 fail = do_move (source, new_dest);
412 free (new_dest);
414 else
416 fail = do_move (source, dest);
419 return fail;
422 static void
423 usage (int status)
425 if (status != 0)
426 fprintf (stderr, _("Try `%s --help' for more information.\n"),
427 program_name);
428 else
430 printf (_("\
431 Usage: %s [OPTION]... SOURCE DEST\n\
432 or: %s [OPTION]... SOURCE... DIRECTORY\n\
434 program_name, program_name);
435 printf (_("\
436 Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\
438 -b, --backup make backup before removal\n\
439 -f, --force remove existing destinations, never prompt\n\
440 -i, --interactive prompt before overwrite\n\
441 -S, --suffix=SUFFIX override the usual backup suffix\n\
442 -u, --update move only older or brand new files\n\
443 -v, --verbose explain what is being done\n\
444 -V, --version-control=WORD override the usual version control\n\
445 --help display this help and exit\n\
446 --version output version information and exit\n\
448 "));
449 printf (_("\
450 The backup suffix is ~, unless set with SIMPLE_BACKUP_SUFFIX. The\n\
451 version control may be set with VERSION_CONTROL, values are:\n\
453 t, numbered make numbered backups\n\
454 nil, existing numbered if numbered backups exist, simple otherwise\n\
455 never, simple always make simple backups\n\
456 "));
457 puts (_("\nReport bugs to <fileutils-bugs@gnu.org>."));
458 close_stdout ();
460 exit (status);
464 main (int argc, char **argv)
466 int c;
467 int errors;
468 int make_backups = 0;
469 int dest_is_dir;
470 char *version;
472 program_name = argv[0];
473 setlocale (LC_ALL, "");
474 bindtextdomain (PACKAGE, LOCALEDIR);
475 textdomain (PACKAGE);
477 version = getenv ("SIMPLE_BACKUP_SUFFIX");
478 if (version)
479 simple_backup_suffix = version;
480 version = getenv ("VERSION_CONTROL");
482 interactive = override_mode = verbose = update = 0;
483 errors = 0;
485 while ((c = getopt_long (argc, argv, "bfiuvS:V:", long_options, NULL)) != -1)
487 switch (c)
489 case 0:
490 break;
491 case 'b':
492 make_backups = 1;
493 break;
494 case 'f':
495 interactive = 0;
496 override_mode = 1;
497 break;
498 case 'i':
499 interactive = 1;
500 override_mode = 0;
501 break;
502 case 'u':
503 update = 1;
504 break;
505 case 'v':
506 verbose = 1;
507 break;
508 case 'S':
509 simple_backup_suffix = optarg;
510 break;
511 case 'V':
512 version = optarg;
513 break;
514 default:
515 usage (1);
519 if (show_version)
521 printf ("mv (%s) %s\n", GNU_PACKAGE, VERSION);
522 close_stdout ();
523 exit (0);
526 if (show_help)
527 usage (0);
529 if (argc < optind + 2)
531 error (0, 0, "%s", (argc == optind
532 ? _("missing file arguments")
533 : _("missing file argument")));
534 usage (1);
537 if (make_backups)
538 backup_type = get_version (version);
540 stdin_tty = isatty (STDIN_FILENO);
541 dest_is_dir = isdir (argv[argc - 1]);
543 if (argc > optind + 2 && !dest_is_dir)
544 error (1, 0,
545 _("when moving multiple files, last argument must be a directory"));
547 /* Move each arg but the last onto the last. */
548 for (; optind < argc - 1; ++optind)
549 errors |= movefile (argv[optind], argv[argc - 1], dest_is_dir);
551 if (verbose)
552 close_stdout ();
553 exit (errors);