Arrange to call close_stdout only upon exit.
[platform/upstream/coreutils.git] / src / mv.c
1 /* mv -- move or rename files
2    Copyright (C) 86, 89, 90, 91, 1995-2000 Free Software Foundation, Inc.
3
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.
8
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.
13
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.  */
17
18 /* Options:
19    -f, --force          Assume a 'y' answer to all questions it would
20                         normally ask, and not ask the questions.
21
22    -i, --interactive    Require confirmation from the user before
23                         performing any move that would destroy an
24                         existing file.
25
26    -u, --update         Do not move a nondirectory that has an
27                         existing destination with the same or newer
28                         modification time.
29
30    -v, --verbose                List the name of each file as it is moved, and
31                         the name it is moved to.
32
33    -b, --backup
34    -S, --suffix
35    -V, --version-control
36                         Backup file creation.
37
38    Written by Mike Parker, David MacKenzie, and Jim Meyering */
39
40 #ifdef _AIX
41  #pragma alloca
42 #endif
43
44 #include <config.h>
45 #include <stdio.h>
46 #include <getopt.h>
47 #include <sys/types.h>
48 #include <assert.h>
49
50 #include "system.h"
51 #include "backupfile.h"
52 #include "copy.h"
53 #include "cp-hash.h"
54 #include "error.h"
55 #include "path-concat.h"
56 #include "remove.h"
57
58 /* The official name of this program (e.g., no `g' prefix).  */
59 #define PROGRAM_NAME "mv"
60
61 #define AUTHORS "Mike Parker, David MacKenzie, and Jim Meyering"
62
63 /* Initial number of entries in each hash table entry's table of inodes.  */
64 #define INITIAL_HASH_MODULE 100
65
66 /* Initial number of entries in the inode hash table.  */
67 #define INITIAL_ENTRY_TAB_SIZE 70
68
69 /* For long options that have no equivalent short option, use a
70    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
71 enum
72 {
73   TARGET_DIRECTORY_OPTION = CHAR_MAX + 1,
74   STRIP_TRAILING_SLASHES_OPTION
75 };
76
77 int euidaccess ();
78 int full_write ();
79 int isdir ();
80 int lstat ();
81 int yesno ();
82
83 /* The name this program was run with. */
84 char *program_name;
85
86 /* Remove any trailing slashes from each SOURCE argument.  */
87 static int remove_trailing_slashes;
88
89 static struct option const long_options[] =
90 {
91   {"backup", optional_argument, NULL, 'b'},
92   {"force", no_argument, NULL, 'f'},
93   {"interactive", no_argument, NULL, 'i'},
94   {"strip-trailing-slash", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION},
95   {"suffix", required_argument, NULL, 'S'},
96   {"target-directory", required_argument, NULL, TARGET_DIRECTORY_OPTION},
97   {"update", no_argument, NULL, 'u'},
98   {"verbose", no_argument, NULL, 'v'},
99   {"version-control", required_argument, NULL, 'V'},
100   {GETOPT_HELP_OPTION_DECL},
101   {GETOPT_VERSION_OPTION_DECL},
102   {NULL, 0, NULL, 0}
103 };
104
105 static void
106 rm_option_init (struct rm_options *x)
107 {
108   x->unlink_dirs = 0;
109
110   /* FIXME: maybe this should be 1.  The POSIX spec doesn't specify.  */
111   x->ignore_missing_files = 0;
112
113   x->recursive = 1;
114
115   /* Should we prompt for removal, too?  No.  Prompting for the `move'
116      part is enough.  It implies removal.  */
117   x->interactive = 0;
118   x->stdin_tty = 0;
119
120   x->verbose = 0;
121 }
122
123 static void
124 cp_option_init (struct cp_options *x)
125 {
126   x->copy_as_regular = 0;  /* FIXME: maybe make this an option */
127   x->dereference = 0;
128   x->force = 0;
129   x->failed_unlink_is_fatal = 1;
130   x->hard_link = 0;
131   x->interactive = 0;
132   x->move_mode = 1;
133   x->myeuid = geteuid ();
134   x->one_file_system = 0;
135   x->preserve_owner_and_group = 1;
136   x->preserve_chmod_bits = 1;
137   x->preserve_timestamps = 1;
138   x->require_preserve = 0;  /* FIXME: maybe make this an option */
139   x->recursive = 1;
140   x->sparse_mode = SPARSE_AUTO;  /* FIXME: maybe make this an option */
141   x->symbolic_link = 0;
142   x->set_mode = 0;
143   x->mode = 0;
144
145   /* Find out the current file creation mask, to knock the right bits
146      when using chmod.  The creation mask is set to be liberal, so
147      that created directories can be written, even if it would not
148      have been allowed with the mask this process was started with.  */
149   x->umask_kill = ~ umask (0);
150
151   x->update = 0;
152   x->verbose = 0;
153   x->xstat = lstat;
154 }
155
156 /* If PATH is an existing directory, return nonzero, else 0.  */
157
158 static int
159 is_real_dir (const char *path)
160 {
161   struct stat stats;
162
163   return lstat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
164 }
165
166 /* Move SOURCE onto DEST.  Handles cross-filesystem moves.
167    If SOURCE is a directory, DEST must not exist.
168    Return 0 if successful, non-zero if an error occurred.  */
169
170 static int
171 do_move (const char *source, const char *dest, const struct cp_options *x)
172 {
173   static int first = 1;
174   int copy_into_self;
175   int rename_succeeded;
176   int fail;
177
178   if (first)
179     {
180       first = 0;
181
182       /* Allocate space for remembering copied and created files.  */
183       hash_init (INITIAL_HASH_MODULE, INITIAL_ENTRY_TAB_SIZE);
184     }
185
186   fail = copy (source, dest, 0, x, &copy_into_self, &rename_succeeded);
187
188   if (!fail)
189     {
190       const char *dir_to_remove;
191       if (copy_into_self)
192         {
193           /* In general, when copy returns with copy_into_self set, SOURCE is
194              the same as, or a parent of DEST.  In this case we know it's a
195              parent.  It doesn't make sense to move a directory into itself, and
196              besides in some situations doing so would give highly nonintuitive
197              results.  Run this `mkdir b; touch a c; mv * b' in an empty
198              directory.  Here's the result of running echo `find b -print`:
199              b b/a b/b b/b/a b/c.  Notice that only file `a' was copied
200              into b/b.  Handle this by giving a diagnostic, removing the
201              copied-into-self directory, DEST (`b/b' in the example),
202              and failing.  */
203
204           dir_to_remove = NULL;
205           error (0, 0,
206                  _("cannot move `%s' to a subdirectory of itself, `%s'"),
207                  source, dest);
208         }
209       else if (rename_succeeded)
210         {
211           /* No need to remove anything.  SOURCE was successfully
212              renamed to DEST.  */
213           dir_to_remove = NULL;
214         }
215       else
216         {
217           /* This may mean SOURCE and DEST referred to different devices.
218              It may also conceivably mean that even though they referred
219              to the same device, rename wasn't implemented for that device.
220
221              E.g., (from Joel N. Weber),
222              [...] there might someday be cases where you can't rename
223              but you can copy where the device name is the same, especially
224              on Hurd.  Consider an ftpfs with a primitive ftp server that
225              supports uploading, downloading and deleting, but not renaming.
226
227              Also, note that comparing device numbers is not a reliable
228              check for `can-rename'.  Some systems can be set up so that
229              files from many different physical devices all have the same
230              st_dev field.  This is a feature of some NFS mounting
231              configurations.
232
233              We reach this point if SOURCE has been successfully copied
234              to DEST.  Now we have to remove SOURCE.
235
236              This function used to resort to copying only when rename
237              failed and set errno to EXDEV.  */
238
239           dir_to_remove = source;
240         }
241
242       if (dir_to_remove != NULL)
243         {
244           struct rm_options rm_options;
245           struct File_spec fs;
246           enum RM_status status;
247
248           rm_option_init (&rm_options);
249           rm_options.verbose = x->verbose;
250
251           remove_init ();
252
253           fspec_init_file (&fs, dir_to_remove);
254           status = rm (&fs, 1, &rm_options);
255           assert (VALID_STATUS (status));
256           if (status == RM_ERROR)
257             fail = 1;
258
259           remove_fini ();
260
261           if (fail)
262             error (0, errno, _("cannot remove `%s'"), dir_to_remove);
263         }
264
265       if (copy_into_self)
266         fail = 1;
267     }
268
269   return fail;
270 }
271
272 static int
273 strip_trailing_slashes_2 (char *path)
274 {
275   char *end_p = path + strlen (path) - 1;
276   char *slash = end_p;
277
278   while (slash > path && *slash == '/')
279     *slash-- = '\0';
280
281   return slash < end_p;
282 }
283
284 /* Move file SOURCE onto DEST.  Handles the case when DEST is a directory.
285    DEST_IS_DIR must be nonzero when DEST is a directory or a symlink to a
286    directory and zero otherwise.
287    Return 0 if successful, non-zero if an error occurred.  */
288
289 static int
290 movefile (char *source, char *dest, int dest_is_dir,
291           const struct cp_options *x)
292 {
293   int dest_had_trailing_slash = strip_trailing_slashes_2 (dest);
294   int fail;
295
296   /* This code was introduced to handle the ambiguity in the semantics
297      of mv that is induced by the varying semantics of the rename function.
298      Some systems (e.g., Linux) have a rename function that honors a
299      trailing slash, while others (like Solaris 5,6,7) have a rename
300      function that ignores a trailing slash.  I believe the Linux
301      rename semantics are POSIX and susv2 compliant.  */
302
303   if (remove_trailing_slashes)
304     strip_trailing_slashes_2 (source);
305
306   /* In addition to when DEST is a directory, if DEST has a trailing
307      slash and neither SOURCE nor DEST is a directory, presume the target
308      is DEST/`basename source`.  This converts `mv x y/' to `mv x y/x'.
309      This change means that the command `mv any file/' will now fail
310      rather than performing the move.  The case when SOURCE is a
311      directory and DEST is not is properly diagnosed by do_move.  */
312
313   if (dest_is_dir || (dest_had_trailing_slash && !is_real_dir (source)))
314     {
315       /* DEST is a directory; build full target filename. */
316       char *src_basename;
317       char *new_dest;
318
319       /* Remove trailing slashes before taking base_name.
320          Otherwise, base_name ("a/") returns "".  */
321       strip_trailing_slashes_2 (source);
322
323       src_basename = base_name (source);
324       new_dest = path_concat (dest, src_basename, NULL);
325       if (new_dest == NULL)
326         error (1, 0, _("virtual memory exhausted"));
327       fail = do_move (source, new_dest, x);
328
329       /* Do not free new_dest.  It may have been squirelled away by
330          the remember_copied function.  */
331     }
332   else
333     {
334       fail = do_move (source, dest, x);
335     }
336
337   return fail;
338 }
339
340 void
341 usage (int status)
342 {
343   if (status != 0)
344     fprintf (stderr, _("Try `%s --help' for more information.\n"),
345              program_name);
346   else
347     {
348       printf (_("\
349 Usage: %s [OPTION]... SOURCE DEST\n\
350   or:  %s [OPTION]... SOURCE... DIRECTORY\n\
351   or:  %s [OPTION]... --target-directory=DIRECTORY SOURCE...\n\
352 "),
353               program_name, program_name, program_name);
354       printf (_("\
355 Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\
356 \n\
357       --backup[=CONTROL]       make a backup of each existing destination file\n\
358   -b                           like --backup but does not accept an argument\n\
359   -f, --force                  remove existing destinations, never prompt\n\
360   -i, --interactive            prompt before overwrite\n\
361       --strip-trailing-slashes  remove any trailing slashes from each SOURCE\n\
362                                  argument\n\
363   -S, --suffix=SUFFIX          override the usual backup suffix\n\
364       --target-directory=DIRECTORY  move all SOURCE arguments into DIRECTORY\n\
365   -u, --update                 move only older or brand new non-directories\n\
366   -v, --verbose                explain what is being done\n\
367       --help                   display this help and exit\n\
368       --version                output version information and exit\n\
369 \n\
370 "));
371       printf (_("\
372 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
373 The version control method may be selected via the --backup option or through\n\
374 the VERSION_CONTROL environment variable.  Here are the values:\n\
375 \n\
376   none, off       never make backups (even if --backup is given)\n\
377   numbered, t     make numbered backups\n\
378   existing, nil   numbered if numbered backups exist, simple otherwise\n\
379   simple, never   always make simple backups\n\
380 "));
381       puts (_("\nReport bugs to <bug-fileutils@gnu.org>."));
382     }
383   exit (status);
384 }
385
386 int
387 main (int argc, char **argv)
388 {
389   int c;
390   int errors;
391   int make_backups = 0;
392   int dest_is_dir;
393   char *backup_suffix_string;
394   char *version_control_string = NULL;
395   struct cp_options x;
396   char *target_directory = NULL;
397   int target_directory_specified;
398   unsigned int n_files;
399   char **file;
400
401   program_name = argv[0];
402   setlocale (LC_ALL, "");
403   bindtextdomain (PACKAGE, LOCALEDIR);
404   textdomain (PACKAGE);
405
406   atexit (close_stdout);
407
408   cp_option_init (&x);
409
410   /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
411      we'll actually use backup_suffix_string.  */
412   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
413
414   errors = 0;
415
416   while ((c = getopt_long (argc, argv, "bfiuvS:V:", long_options, NULL)) != -1)
417     {
418       switch (c)
419         {
420         case 0:
421           break;
422
423         case 'V':  /* FIXME: this is deprecated.  Remove it in 2001.  */
424           error (0, 0,
425                  _("warning: --version-control (-V) is obsolete;  support for\
426  it\nwill be removed in some future release.  Use --backup=%s instead."
427                    ), optarg);
428           /* Fall through.  */
429
430         case 'b':
431           make_backups = 1;
432           if (optarg)
433             version_control_string = optarg;
434           break;
435         case 'f':
436           x.interactive = 0;
437           x.force = 1;
438           break;
439         case 'i':
440           x.interactive = 1;
441           x.force = 0;
442           break;
443         case STRIP_TRAILING_SLASHES_OPTION:
444           remove_trailing_slashes = 1;
445           break;
446         case TARGET_DIRECTORY_OPTION:
447           target_directory = optarg;
448           break;
449         case 'u':
450           x.update = 1;
451           break;
452         case 'v':
453           x.verbose = 1;
454           break;
455         case 'S':
456           make_backups = 1;
457           backup_suffix_string = optarg;
458           break;
459         case_GETOPT_HELP_CHAR;
460         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
461         default:
462           usage (1);
463         }
464     }
465
466   n_files = argc - optind;
467   file = argv + optind;
468
469   target_directory_specified = (target_directory != NULL);
470   if (target_directory == NULL && n_files != 0)
471     target_directory = file[n_files - 1];
472
473   dest_is_dir = (n_files > 0 && isdir (target_directory));
474
475   if (target_directory_specified)
476     {
477       if (!dest_is_dir)
478         {
479           error (0, 0, _("specified target, `%s' is not a directory"),
480                  target_directory);
481           usage (1);
482         }
483
484       if (n_files == 0)
485         {
486           error (0, 0, "%s", _("missing file argument"));
487           usage (1);
488         }
489     }
490   else
491     {
492       if (n_files < 2)
493         {
494           error (0, 0, "%s", (n_files == 0
495                               ? _("missing file arguments")
496                               : _("missing file argument")));
497           usage (1);
498         }
499
500       if (n_files > 2 && !dest_is_dir)
501         {
502           error (0, 0,
503            _("when moving multiple files, last argument must be a directory"));
504           usage (1);
505         }
506     }
507
508   if (backup_suffix_string)
509     simple_backup_suffix = xstrdup (backup_suffix_string);
510
511   x.backup_type = (make_backups
512                    ? xget_version (_("backup type"),
513                                    version_control_string)
514                    : none);
515
516   /* Move each arg but the last into the target_directory.  */
517   {
518     unsigned int last_file_idx = (target_directory_specified
519                                   ? n_files - 1
520                                   : n_files - 2);
521     unsigned int i;
522     for (i = 0; i <= last_file_idx; ++i)
523       errors |= movefile (file[i], target_directory, dest_is_dir, &x);
524   }
525
526   exit (errors);
527 }