Tizen 2.0 Release
[external/tizen-coreutils.git] / src / mv.c
1 /* mv -- move or rename files
2    Copyright (C) 86, 89, 90, 91, 1995-2007 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 "error.h"
32 #include "filenamecat.h"
33 #include "quote.h"
34 #include "remove.h"
35
36 /* The official name of this program (e.g., no `g' prefix).  */
37 #define PROGRAM_NAME "mv"
38
39 #define AUTHORS "Mike Parker", "David MacKenzie", "Jim Meyering"
40
41 /* Initial number of entries in each hash table entry's table of inodes.  */
42 #define INITIAL_HASH_MODULE 100
43
44 /* Initial number of entries in the inode hash table.  */
45 #define INITIAL_ENTRY_TAB_SIZE 70
46
47 /* For long options that have no equivalent short option, use a
48    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
49 enum
50 {
51   REPLY_OPTION = CHAR_MAX + 1,
52   STRIP_TRAILING_SLASHES_OPTION
53 };
54
55 /* The name this program was run with. */
56 char *program_name;
57
58 /* Remove any trailing slashes from each SOURCE argument.  */
59 static bool remove_trailing_slashes;
60
61 /* Valid arguments to the `--reply' option. */
62 static char const* const reply_args[] =
63 {
64   "yes", "no", "query", NULL
65 };
66
67 /* The values that correspond to the above strings. */
68 static int const reply_vals[] =
69 {
70   I_ALWAYS_YES, I_ALWAYS_NO, I_ASK_USER
71 };
72
73 static struct option const long_options[] =
74 {
75   {"backup", optional_argument, NULL, 'b'},
76   {"force", no_argument, NULL, 'f'},
77   {"interactive", no_argument, NULL, 'i'},
78   {"no-target-directory", no_argument, NULL, 'T'},
79   {"reply", required_argument, NULL, REPLY_OPTION}, /* Deprecated 2005-07-03,
80                                                        remove in 2008. */
81   {"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION},
82   {"suffix", required_argument, NULL, 'S'},
83   {"target-directory", required_argument, NULL, 't'},
84   {"update", no_argument, NULL, 'u'},
85   {"verbose", no_argument, NULL, 'v'},
86   {GETOPT_HELP_OPTION_DECL},
87   {GETOPT_VERSION_OPTION_DECL},
88   {NULL, 0, NULL, 0}
89 };
90
91 static void
92 rm_option_init (struct rm_options *x)
93 {
94   x->ignore_missing_files = false;
95   x->root_dev_ino = NULL;
96   x->recursive = true;
97   x->one_file_system = false;
98
99   /* Should we prompt for removal, too?  No.  Prompting for the `move'
100      part is enough.  It implies removal.  */
101   x->interactive = RMI_NEVER;
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 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
226           rm_option_init (&rm_options);
227           rm_options.verbose = x->verbose;
228
229           status = rm (1, &dir_to_remove, &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., 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 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 "), stdout);
303       fputs (_("\
304       --strip-trailing-slashes  remove any trailing slashes from each SOURCE\n\
305                                  argument\n\
306   -S, --suffix=SUFFIX          override the usual backup suffix\n\
307 "), stdout);
308       fputs (_("\
309   -t, --target-directory=DIRECTORY  move all SOURCE arguments into DIRECTORY\n\
310   -T, --no-target-directory    treat DEST as a normal file\n\
311   -u, --update                 move only when the SOURCE file is newer\n\
312                                  than the destination file or when the\n\
313                                  destination file is missing\n\
314   -v, --verbose                explain what is being done\n\
315 "), stdout);
316       fputs (HELP_OPTION_DESCRIPTION, stdout);
317       fputs (VERSION_OPTION_DESCRIPTION, stdout);
318       fputs (_("\
319 \n\
320 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
321 The version control method may be selected via the --backup option or through\n\
322 the VERSION_CONTROL environment variable.  Here are the values:\n\
323 \n\
324 "), stdout);
325       fputs (_("\
326   none, off       never make backups (even if --backup is given)\n\
327   numbered, t     make numbered backups\n\
328   existing, nil   numbered if numbered backups exist, simple otherwise\n\
329   simple, never   always make simple backups\n\
330 "), stdout);
331       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
332     }
333   exit (status);
334 }
335
336 int
337 main (int argc, char **argv)
338 {
339   int c;
340   bool ok;
341   bool make_backups = false;
342   char *backup_suffix_string;
343   char *version_control_string = NULL;
344   struct cp_options x;
345   char *target_directory = NULL;
346   bool no_target_directory = false;
347   int n_files;
348   char **file;
349
350   initialize_main (&argc, &argv);
351   program_name = argv[0];
352   setlocale (LC_ALL, "");
353   bindtextdomain (PACKAGE, LOCALEDIR);
354   textdomain (PACKAGE);
355
356   atexit (close_stdout);
357
358   cp_option_init (&x);
359
360   /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
361      we'll actually use backup_suffix_string.  */
362   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
363
364   while ((c = getopt_long (argc, argv, "bfit:uvS:T", long_options, NULL))
365          != -1)
366     {
367       switch (c)
368         {
369         case 'b':
370           make_backups = true;
371           if (optarg)
372             version_control_string = optarg;
373           break;
374         case 'f':
375           x.interactive = I_ALWAYS_YES;
376           break;
377         case 'i':
378           x.interactive = I_ASK_USER;
379           break;
380         case REPLY_OPTION: /* Deprecated */
381           x.interactive = XARGMATCH ("--reply", optarg,
382                                      reply_args, reply_vals);
383           error (0, 0,
384                  _("the --reply option is deprecated; use -i or -f instead"));
385           break;
386         case STRIP_TRAILING_SLASHES_OPTION:
387           remove_trailing_slashes = true;
388           break;
389         case 't':
390           if (target_directory)
391             error (EXIT_FAILURE, 0, _("multiple target directories specified"));
392           else
393             {
394               struct stat st;
395               if (stat (optarg, &st) != 0)
396                 error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
397               if (! S_ISDIR (st.st_mode))
398                 error (EXIT_FAILURE, 0, _("target %s is not a directory"),
399                        quote (optarg));
400             }
401           target_directory = optarg;
402           break;
403         case 'T':
404           no_target_directory = true;
405           break;
406         case 'u':
407           x.update = true;
408           break;
409         case 'v':
410           x.verbose = true;
411           break;
412         case 'S':
413           make_backups = true;
414           backup_suffix_string = optarg;
415           break;
416         case_GETOPT_HELP_CHAR;
417         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
418         default:
419           usage (EXIT_FAILURE);
420         }
421     }
422
423   n_files = argc - optind;
424   file = argv + optind;
425
426   if (n_files <= !target_directory)
427     {
428       if (n_files <= 0)
429         error (0, 0, _("missing file operand"));
430       else
431         error (0, 0, _("missing destination file operand after %s"),
432                quote (file[0]));
433       usage (EXIT_FAILURE);
434     }
435
436   if (no_target_directory)
437     {
438       if (target_directory)
439         error (EXIT_FAILURE, 0,
440                _("Cannot combine --target-directory (-t) "
441                  "and --no-target-directory (-T)"));
442       if (2 < n_files)
443         {
444           error (0, 0, _("extra operand %s"), quote (file[2]));
445           usage (EXIT_FAILURE);
446         }
447     }
448   else if (!target_directory)
449     {
450       assert (2 <= n_files);
451       if (target_directory_operand (file[n_files - 1]))
452         target_directory = file[--n_files];
453       else if (2 < n_files)
454         error (EXIT_FAILURE, 0, _("target %s is not a directory"),
455                quote (file[n_files - 1]));
456     }
457
458   if (backup_suffix_string)
459     simple_backup_suffix = xstrdup (backup_suffix_string);
460
461   x.backup_type = (make_backups
462                    ? xget_version (_("backup type"),
463                                    version_control_string)
464                    : no_backups);
465
466   hash_init ();
467
468   if (target_directory)
469     {
470       int i;
471
472       /* Initialize the hash table only if we'll need it.
473          The problem it is used to detect can arise only if there are
474          two or more files to move.  */
475       if (2 <= n_files)
476         dest_info_init (&x);
477
478       ok = true;
479       for (i = 0; i < n_files; ++i)
480         ok &= movefile (file[i], target_directory, true, &x);
481     }
482   else
483     ok = movefile (file[0], file[1], false, &x);
484
485   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
486 }