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