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