*** empty log message ***
[platform/upstream/coreutils.git] / src / mv.c
1 /* mv -- move or rename files
2    Copyright (C) 86, 89, 90, 91, 1995-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Mike Parker, David MacKenzie, and Jim Meyering */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <getopt.h>
23 #include <sys/types.h>
24 #include <assert.h>
25
26 #include "system.h"
27 #include "argmatch.h"
28 #include "backupfile.h"
29 #include "copy.h"
30 #include "cp-hash.h"
31 #include "dirname.h"
32 #include "error.h"
33 #include "filenamecat.h"
34 #include "quote.h"
35 #include "remove.h"
36
37 /* The official name of this program (e.g., no `g' prefix).  */
38 #define PROGRAM_NAME "mv"
39
40 #define AUTHORS "Mike Parker", "David MacKenzie", "Jim Meyering"
41
42 /* Initial number of entries in each hash table entry's table of inodes.  */
43 #define INITIAL_HASH_MODULE 100
44
45 /* Initial number of entries in the inode hash table.  */
46 #define INITIAL_ENTRY_TAB_SIZE 70
47
48 /* For long options that have no equivalent short option, use a
49    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
50 enum
51 {
52   REPLY_OPTION = CHAR_MAX + 1,
53   STRIP_TRAILING_SLASHES_OPTION
54 };
55
56 /* The name this program was run with. */
57 char *program_name;
58
59 /* Remove any trailing slashes from each SOURCE argument.  */
60 static bool remove_trailing_slashes;
61
62 /* Valid arguments to the `--reply' option. */
63 static char const* const reply_args[] =
64 {
65   "yes", "no", "query", NULL
66 };
67
68 /* The values that correspond to the above strings. */
69 static int const reply_vals[] =
70 {
71   I_ALWAYS_YES, I_ALWAYS_NO, I_ASK_USER
72 };
73
74 static struct option const long_options[] =
75 {
76   {"backup", optional_argument, NULL, 'b'},
77   {"force", no_argument, NULL, 'f'},
78   {"interactive", no_argument, NULL, 'i'},
79   {"no-target-directory", no_argument, NULL, 'T'},
80   {"reply", required_argument, NULL, REPLY_OPTION}, /* Deprecated 2005-07-03,
81                                                        remove in 2008. */
82   {"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION},
83   {"suffix", required_argument, NULL, 'S'},
84   {"target-directory", required_argument, NULL, 't'},
85   {"update", no_argument, NULL, 'u'},
86   {"verbose", no_argument, NULL, 'v'},
87   {GETOPT_HELP_OPTION_DECL},
88   {GETOPT_VERSION_OPTION_DECL},
89   {NULL, 0, NULL, 0}
90 };
91
92 static void
93 rm_option_init (struct rm_options *x)
94 {
95   x->ignore_missing_files = false;
96   x->root_dev_ino = NULL;
97   x->recursive = true;
98
99   /* Should we prompt for removal, too?  No.  Prompting for the `move'
100      part is enough.  It implies removal.  */
101   x->interactive = 0;
102   x->stdin_tty = false;
103
104   x->verbose = false;
105
106   /* Since this program may well have to process additional command
107      line arguments after any call to `rm', that function must preserve
108      the initial working directory, in case one of those is a
109      `.'-relative name.  */
110   x->require_restore_cwd = true;
111 }
112
113 static void
114 cp_option_init (struct cp_options *x)
115 {
116   x->copy_as_regular = false;  /* FIXME: maybe make this an option */
117   x->dereference = DEREF_NEVER;
118   x->unlink_dest_before_opening = false;
119   x->unlink_dest_after_failed_open = false;
120   x->hard_link = false;
121   x->interactive = I_UNSPECIFIED;
122   x->move_mode = true;
123   x->chown_privileges = chown_privileges ();
124   x->one_file_system = false;
125   x->preserve_ownership = true;
126   x->preserve_links = true;
127   x->preserve_mode = true;
128   x->preserve_timestamps = true;
129   x->require_preserve = false;  /* FIXME: maybe make this an option */
130   x->recursive = true;
131   x->sparse_mode = SPARSE_AUTO;  /* FIXME: maybe make this an option */
132   x->symbolic_link = false;
133   x->set_mode = false;
134   x->mode = 0;
135   x->stdin_tty = isatty (STDIN_FILENO);
136
137   x->update = false;
138   x->verbose = false;
139   x->dest_info = NULL;
140   x->src_info = NULL;
141 }
142
143 /* FILE is the last operand of this command.  Return true if FILE is a
144    directory.  But report an error there is a problem accessing FILE,
145    or if FILE does not exist but would have to refer to an existing
146    directory if it referred to anything at all.  */
147
148 static bool
149 target_directory_operand (char const *file)
150 {
151   char const *b = last_component (file);
152   size_t blen = strlen (b);
153   bool looks_like_a_dir = (blen == 0 || ISSLASH (b[blen - 1]));
154   struct stat st;
155   int err = (stat (file, &st) == 0 ? 0 : errno);
156   bool is_a_dir = !err && S_ISDIR (st.st_mode);
157   if (err && err != ENOENT)
158     error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
159   if (is_a_dir < looks_like_a_dir)
160     error (EXIT_FAILURE, err, _("target %s is not a directory"), quote (file));
161   return is_a_dir;
162 }
163
164 /* Move SOURCE onto DEST.  Handles cross-file-system moves.
165    If SOURCE is a directory, DEST must not exist.
166    Return true if successful.  */
167
168 static bool
169 do_move (const char *source, const char *dest, const struct cp_options *x)
170 {
171   bool copy_into_self;
172   bool rename_succeeded;
173   bool ok = copy (source, dest, false, x, &copy_into_self, &rename_succeeded);
174
175   if (ok)
176     {
177       char const *dir_to_remove;
178       if (copy_into_self)
179         {
180           /* In general, when copy returns with copy_into_self set, SOURCE is
181              the same as, or a parent of DEST.  In this case we know it's a
182              parent.  It doesn't make sense to move a directory into itself, and
183              besides in some situations doing so would give highly nonintuitive
184              results.  Run this `mkdir b; touch a c; mv * b' in an empty
185              directory.  Here's the result of running echo `find b -print`:
186              b b/a b/b b/b/a b/c.  Notice that only file `a' was copied
187              into b/b.  Handle this by giving a diagnostic, removing the
188              copied-into-self directory, DEST (`b/b' in the example),
189              and failing.  */
190
191           dir_to_remove = NULL;
192           ok = false;
193         }
194       else if (rename_succeeded)
195         {
196           /* No need to remove anything.  SOURCE was successfully
197              renamed to DEST.  Or the user declined to rename a file.  */
198           dir_to_remove = NULL;
199         }
200       else
201         {
202           /* This may mean SOURCE and DEST referred to different devices.
203              It may also conceivably mean that even though they referred
204              to the same device, rename wasn't implemented for that device.
205
206              E.g., (from Joel N. Weber),
207              [...] there might someday be cases where you can't rename
208              but you can copy where the device name is the same, especially
209              on Hurd.  Consider an ftpfs with a primitive ftp server that
210              supports uploading, downloading and deleting, but not renaming.
211
212              Also, note that comparing device numbers is not a reliable
213              check for `can-rename'.  Some systems can be set up so that
214              files from many different physical devices all have the same
215              st_dev field.  This is a feature of some NFS mounting
216              configurations.
217
218              We reach this point if SOURCE has been successfully copied
219              to DEST.  Now we have to remove SOURCE.
220
221              This function used to resort to copying only when rename
222              failed and set errno to EXDEV.  */
223
224           dir_to_remove = source;
225         }
226
227       if (dir_to_remove != NULL)
228         {
229           struct rm_options rm_options;
230           enum RM_status status;
231
232           rm_option_init (&rm_options);
233           rm_options.verbose = x->verbose;
234
235           status = rm (1, &dir_to_remove, &rm_options);
236           assert (VALID_STATUS (status));
237           if (status == RM_ERROR)
238             ok = false;
239         }
240     }
241
242   return ok;
243 }
244
245 /* Move file SOURCE onto DEST.  Handles the case when DEST is a directory.
246    Treat DEST as a directory if DEST_IS_DIR.
247    Return true if successful.  */
248
249 static bool
250 movefile (char *source, char *dest, bool dest_is_dir,
251           const struct cp_options *x)
252 {
253   bool ok;
254
255   /* This code was introduced to handle the ambiguity in the semantics
256      of mv that is induced by the varying semantics of the rename function.
257      Some systems (e.g., Linux) have a rename function that honors a
258      trailing slash, while others (like Solaris 5,6,7) have a rename
259      function that ignores a trailing slash.  I believe the Linux
260      rename semantics are POSIX and susv2 compliant.  */
261
262   strip_trailing_slashes (dest);
263   if (remove_trailing_slashes)
264     strip_trailing_slashes (source);
265
266   if (dest_is_dir)
267     {
268       /* Treat DEST as a directory; build the full filename.  */
269       char const *src_basename = last_component (source);
270       char *new_dest = file_name_concat (dest, src_basename, NULL);
271       strip_trailing_slashes (new_dest);
272       ok = do_move (source, new_dest, x);
273       free (new_dest);
274     }
275   else
276     {
277       ok = do_move (source, dest, x);
278     }
279
280   return ok;
281 }
282
283 void
284 usage (int status)
285 {
286   if (status != EXIT_SUCCESS)
287     fprintf (stderr, _("Try `%s --help' for more information.\n"),
288              program_name);
289   else
290     {
291       printf (_("\
292 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
293   or:  %s [OPTION]... SOURCE... DIRECTORY\n\
294   or:  %s [OPTION]... -t DIRECTORY SOURCE...\n\
295 "),
296               program_name, program_name, program_name);
297       fputs (_("\
298 Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\
299 \n\
300 "), stdout);
301       fputs (_("\
302 Mandatory arguments to long options are mandatory for short options too.\n\
303 "), stdout);
304       fputs (_("\
305       --backup[=CONTROL]       make a backup of each existing destination file\n\
306   -b                           like --backup but does not accept an argument\n\
307   -f, --force                  do not prompt before overwriting\n\
308   -i, --interactive            prompt before overwrite\n\
309 "), stdout);
310       fputs (_("\
311       --strip-trailing-slashes  remove any trailing slashes from each SOURCE\n\
312                                  argument\n\
313   -S, --suffix=SUFFIX          override the usual backup suffix\n\
314 "), stdout);
315       fputs (_("\
316   -t, --target-directory=DIRECTORY  move all SOURCE arguments into DIRECTORY\n\
317   -T, --no-target-directory    treat DEST as a normal file\n\
318   -u, --update                 move only when the SOURCE file is newer\n\
319                                  than the destination file or when the\n\
320                                  destination file is missing\n\
321   -v, --verbose                explain what is being done\n\
322 "), stdout);
323       fputs (HELP_OPTION_DESCRIPTION, stdout);
324       fputs (VERSION_OPTION_DESCRIPTION, stdout);
325       fputs (_("\
326 \n\
327 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
328 The version control method may be selected via the --backup option or through\n\
329 the VERSION_CONTROL environment variable.  Here are the values:\n\
330 \n\
331 "), stdout);
332       fputs (_("\
333   none, off       never make backups (even if --backup is given)\n\
334   numbered, t     make numbered backups\n\
335   existing, nil   numbered if numbered backups exist, simple otherwise\n\
336   simple, never   always make simple backups\n\
337 "), stdout);
338       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
339     }
340   exit (status);
341 }
342
343 int
344 main (int argc, char **argv)
345 {
346   int c;
347   bool ok;
348   bool make_backups = false;
349   char *backup_suffix_string;
350   char *version_control_string = NULL;
351   struct cp_options x;
352   char *target_directory = NULL;
353   bool no_target_directory = false;
354   int n_files;
355   char **file;
356
357   initialize_main (&argc, &argv);
358   program_name = argv[0];
359   setlocale (LC_ALL, "");
360   bindtextdomain (PACKAGE, LOCALEDIR);
361   textdomain (PACKAGE);
362
363   atexit (close_stdout);
364
365   cp_option_init (&x);
366
367   /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
368      we'll actually use backup_suffix_string.  */
369   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
370
371   while ((c = getopt_long (argc, argv, "bfit:uvS:T", long_options, NULL))
372          != -1)
373     {
374       switch (c)
375         {
376         case 'b':
377           make_backups = true;
378           if (optarg)
379             version_control_string = optarg;
380           break;
381         case 'f':
382           x.interactive = I_ALWAYS_YES;
383           break;
384         case 'i':
385           x.interactive = I_ASK_USER;
386           break;
387         case REPLY_OPTION: /* Deprecated */
388           x.interactive = XARGMATCH ("--reply", optarg,
389                                      reply_args, reply_vals);
390           error (0, 0,
391                  _("the --reply option is deprecated; use -i or -f instead"));
392           break;
393         case STRIP_TRAILING_SLASHES_OPTION:
394           remove_trailing_slashes = true;
395           break;
396         case 't':
397           if (target_directory)
398             error (EXIT_FAILURE, 0, _("multiple target directories specified"));
399           else
400             {
401               struct stat st;
402               if (stat (optarg, &st) != 0)
403                 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
404               if (! S_ISDIR (st.st_mode))
405                 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
406                        quote (optarg));
407             }
408           target_directory = optarg;
409           break;
410         case 'T':
411           no_target_directory = true;
412           break;
413         case 'u':
414           x.update = true;
415           break;
416         case 'v':
417           x.verbose = true;
418           break;
419         case 'S':
420           make_backups = true;
421           backup_suffix_string = optarg;
422           break;
423         case_GETOPT_HELP_CHAR;
424         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
425         default:
426           usage (EXIT_FAILURE);
427         }
428     }
429
430   n_files = argc - optind;
431   file = argv + optind;
432
433   if (n_files <= !target_directory)
434     {
435       if (n_files <= 0)
436         error (0, 0, _("missing file operand"));
437       else
438         error (0, 0, _("missing destination file operand after %s"),
439                quote (file[0]));
440       usage (EXIT_FAILURE);
441     }
442
443   if (no_target_directory)
444     {
445       if (target_directory)
446         error (EXIT_FAILURE, 0,
447                _("Cannot combine --target-directory (-t) "
448                  "and --no-target-directory (-T)"));
449       if (2 < n_files)
450         {
451           error (0, 0, _("extra operand %s"), quote (file[2]));
452           usage (EXIT_FAILURE);
453         }
454     }
455   else if (!target_directory)
456     {
457       if (2 <= n_files && target_directory_operand (file[n_files - 1]))
458         target_directory = file[--n_files];
459       else if (2 < n_files)
460         error (EXIT_FAILURE, 0, _("target %s is not a directory"),
461                quote (file[n_files - 1]));
462     }
463
464   if (backup_suffix_string)
465     simple_backup_suffix = xstrdup (backup_suffix_string);
466
467   x.backup_type = (make_backups
468                    ? xget_version (_("backup type"),
469                                    version_control_string)
470                    : no_backups);
471
472   hash_init ();
473
474   if (target_directory)
475     {
476       int i;
477
478       /* Initialize the hash table only if we'll need it.
479          The problem it is used to detect can arise only if there are
480          two or more files to move.  */
481       if (2 <= n_files)
482         dest_info_init (&x);
483
484       ok = true;
485       for (i = 0; i < n_files; ++i)
486         ok &= movefile (file[i], target_directory, true, &x);
487     }
488   else
489     ok = movefile (file[0], file[1], false, &x);
490
491   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
492 }