doc: od --strings: clarify operation
[coreutils.git] / src / mv.c
blobfc2bf77da77f4886e511d30fbddc998baed26469
1 /* mv -- move or rename files
2 Copyright (C) 1986-2023 Free Software Foundation, Inc.
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.
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.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Mike Parker, David MacKenzie, and Jim Meyering */
19 #include <config.h>
20 #include <stdio.h>
21 #include <getopt.h>
22 #include <sys/types.h>
23 #include <assert.h>
24 #include <selinux/label.h>
26 #include "system.h"
27 #include "argmatch.h"
28 #include "backupfile.h"
29 #include "copy.h"
30 #include "cp-hash.h"
31 #include "die.h"
32 #include "error.h"
33 #include "filenamecat.h"
34 #include "remove.h"
35 #include "renameatu.h"
36 #include "root-dev-ino.h"
37 #include "targetdir.h"
38 #include "priv-set.h"
40 /* The official name of this program (e.g., no 'g' prefix). */
41 #define PROGRAM_NAME "mv"
43 #define AUTHORS \
44 proper_name ("Mike Parker"), \
45 proper_name ("David MacKenzie"), \
46 proper_name ("Jim Meyering")
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
52 DEBUG_OPTION = CHAR_MAX + 1,
53 NO_COPY_OPTION,
54 STRIP_TRAILING_SLASHES_OPTION
57 static char const *const update_type_string[] =
59 "all", "none", "older", NULL
61 static enum Update_type const update_type[] =
63 UPDATE_ALL, UPDATE_NONE, UPDATE_OLDER,
65 ARGMATCH_VERIFY (update_type_string, update_type);
67 static struct option const long_options[] =
69 {"backup", optional_argument, NULL, 'b'},
70 {"context", no_argument, NULL, 'Z'},
71 {"debug", no_argument, NULL, DEBUG_OPTION},
72 {"force", no_argument, NULL, 'f'},
73 {"interactive", no_argument, NULL, 'i'},
74 {"no-clobber", no_argument, NULL, 'n'},
75 {"no-copy", no_argument, NULL, NO_COPY_OPTION},
76 {"no-target-directory", no_argument, NULL, 'T'},
77 {"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION},
78 {"suffix", required_argument, NULL, 'S'},
79 {"target-directory", required_argument, NULL, 't'},
80 {"update", optional_argument, NULL, 'u'},
81 {"verbose", no_argument, NULL, 'v'},
82 {GETOPT_HELP_OPTION_DECL},
83 {GETOPT_VERSION_OPTION_DECL},
84 {NULL, 0, NULL, 0}
87 static void
88 rm_option_init (struct rm_options *x)
90 x->ignore_missing_files = false;
91 x->remove_empty_directories = true;
92 x->recursive = true;
93 x->one_file_system = false;
95 /* Should we prompt for removal, too? No. Prompting for the 'move'
96 part is enough. It implies removal. */
97 x->interactive = RMI_NEVER;
98 x->stdin_tty = false;
100 x->verbose = false;
102 /* Since this program may well have to process additional command
103 line arguments after any call to 'rm', that function must preserve
104 the initial working directory, in case one of those is a
105 '.'-relative name. */
106 x->require_restore_cwd = true;
109 static struct dev_ino dev_ino_buf;
110 x->root_dev_ino = get_root_dev_ino (&dev_ino_buf);
111 if (x->root_dev_ino == NULL)
112 die (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
113 quoteaf ("/"));
116 x->preserve_all_root = false;
119 static void
120 cp_option_init (struct cp_options *x)
122 bool selinux_enabled = (0 < is_selinux_enabled ());
124 cp_options_default (x);
125 x->copy_as_regular = false; /* FIXME: maybe make this an option */
126 x->reflink_mode = REFLINK_AUTO;
127 x->dereference = DEREF_NEVER;
128 x->unlink_dest_before_opening = false;
129 x->unlink_dest_after_failed_open = false;
130 x->hard_link = false;
131 x->interactive = I_UNSPECIFIED;
132 x->move_mode = true;
133 x->install_mode = false;
134 x->one_file_system = false;
135 x->preserve_ownership = true;
136 x->preserve_links = true;
137 x->preserve_mode = true;
138 x->preserve_timestamps = true;
139 x->explicit_no_preserve_mode= false;
140 x->preserve_security_context = selinux_enabled;
141 x->set_security_context = NULL;
142 x->reduce_diagnostics = false;
143 x->data_copy_required = true;
144 x->require_preserve = false; /* FIXME: maybe make this an option */
145 x->require_preserve_context = false;
146 x->preserve_xattr = true;
147 x->require_preserve_xattr = false;
148 x->recursive = true;
149 x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */
150 x->symbolic_link = false;
151 x->set_mode = false;
152 x->mode = 0;
153 x->stdin_tty = isatty (STDIN_FILENO);
155 x->open_dangling_dest_symlink = false;
156 x->update = false;
157 x->verbose = false;
158 x->dest_info = NULL;
159 x->src_info = NULL;
162 /* Move SOURCE onto DEST aka DEST_DIRFD+DEST_RELNAME.
163 Handle cross-file-system moves.
164 If SOURCE is a directory, DEST must not exist.
165 Return true if successful. */
167 static bool
168 do_move (char const *source, char const *dest,
169 int dest_dirfd, char const *dest_relname, const struct cp_options *x)
171 bool copy_into_self;
172 bool rename_succeeded;
173 bool ok = copy (source, dest, dest_dirfd, dest_relname, 0, x,
174 &copy_into_self, &rename_succeeded);
176 if (ok)
178 char const *dir_to_remove;
179 if (copy_into_self)
181 /* In general, when copy returns with copy_into_self set, SOURCE is
182 the same as, or a parent of DEST. In this case we know it's a
183 parent. It doesn't make sense to move a directory into itself, and
184 besides in some situations doing so would give highly nonintuitive
185 results. Run this 'mkdir b; touch a c; mv * b' in an empty
186 directory. Here's the result of running echo $(find b -print):
187 b b/a b/b b/b/a b/c. Notice that only file 'a' was copied
188 into b/b. Handle this by giving a diagnostic, removing the
189 copied-into-self directory, DEST ('b/b' in the example),
190 and failing. */
192 dir_to_remove = NULL;
193 ok = false;
195 else if (rename_succeeded)
197 /* No need to remove anything. SOURCE was successfully
198 renamed to DEST. Or the user declined to rename a file. */
199 dir_to_remove = NULL;
201 else
203 /* This may mean SOURCE and DEST referred to different devices.
204 It may also conceivably mean that even though they referred
205 to the same device, rename wasn't implemented for that device.
207 E.g., (from Joel N. Weber),
208 [...] there might someday be cases where you can't rename
209 but you can copy where the device name is the same, especially
210 on Hurd. Consider an ftpfs with a primitive ftp server that
211 supports uploading, downloading and deleting, but not renaming.
213 Also, note that comparing device numbers is not a reliable
214 check for 'can-rename'. Some systems can be set up so that
215 files from many different physical devices all have the same
216 st_dev field. This is a feature of some NFS mounting
217 configurations.
219 We reach this point if SOURCE has been successfully copied
220 to DEST. Now we have to remove SOURCE.
222 This function used to resort to copying only when rename
223 failed and set errno to EXDEV. */
225 dir_to_remove = source;
228 if (dir_to_remove != NULL)
230 struct rm_options rm_options;
231 enum RM_status status;
232 char const *dir[2];
234 rm_option_init (&rm_options);
235 rm_options.verbose = x->verbose;
236 dir[0] = dir_to_remove;
237 dir[1] = NULL;
239 status = rm ((void *) dir, &rm_options);
240 assert (VALID_STATUS (status));
241 if (status == RM_ERROR)
242 ok = false;
246 return ok;
249 void
250 usage (int status)
252 if (status != EXIT_SUCCESS)
253 emit_try_help ();
254 else
256 printf (_("\
257 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
258 or: %s [OPTION]... SOURCE... DIRECTORY\n\
259 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
261 program_name, program_name, program_name);
262 fputs (_("\
263 Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\
264 "), stdout);
266 emit_mandatory_arg_note ();
268 fputs (_("\
269 --backup[=CONTROL] make a backup of each existing destination file\
271 -b like --backup but does not accept an argument\n\
272 "), stdout);
273 fputs (_("\
274 --debug explain how a file is copied. Implies -v\n\
275 "), stdout);
276 fputs (_("\
277 -f, --force do not prompt before overwriting\n\
278 -i, --interactive prompt before overwrite\n\
279 -n, --no-clobber do not overwrite an existing file\n\
280 If you specify more than one of -i, -f, -n, only the final one takes effect.\n\
281 "), stdout);
282 fputs (_("\
283 --no-copy do not copy if renaming fails\n\
284 --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\
285 argument\n\
286 -S, --suffix=SUFFIX override the usual backup suffix\n\
287 "), stdout);
288 fputs (_("\
289 -t, --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY\n\
290 -T, --no-target-directory treat DEST as a normal file\n\
291 "), stdout);
292 fputs (_("\
293 --update[=UPDATE] control which existing files are updated;\n\
294 UPDATE={all,none,older(default)}. See below\n\
295 -u equivalent to --update[=older]\n\
296 "), stdout);
297 fputs (_("\
298 -v, --verbose explain what is being done\n\
299 -Z, --context set SELinux security context of destination\n\
300 file to default type\n\
301 "), stdout);
302 fputs (HELP_OPTION_DESCRIPTION, stdout);
303 fputs (VERSION_OPTION_DESCRIPTION, stdout);
304 emit_update_parameters_note ();
305 emit_backup_suffix_note ();
306 emit_ancillary_info (PROGRAM_NAME);
308 exit (status);
312 main (int argc, char **argv)
314 int c;
315 bool ok;
316 bool make_backups = false;
317 char const *backup_suffix = NULL;
318 char *version_control_string = NULL;
319 struct cp_options x;
320 bool remove_trailing_slashes = false;
321 char const *target_directory = NULL;
322 bool no_target_directory = false;
323 int n_files;
324 char **file;
325 bool selinux_enabled = (0 < is_selinux_enabled ());
327 initialize_main (&argc, &argv);
328 set_program_name (argv[0]);
329 setlocale (LC_ALL, "");
330 bindtextdomain (PACKAGE, LOCALEDIR);
331 textdomain (PACKAGE);
333 atexit (close_stdin);
335 cp_option_init (&x);
337 /* Try to disable the ability to unlink a directory. */
338 priv_set_remove_linkdir ();
340 while ((c = getopt_long (argc, argv, "bfint:uvS:TZ", long_options, NULL))
341 != -1)
343 switch (c)
345 case 'b':
346 make_backups = true;
347 if (optarg)
348 version_control_string = optarg;
349 break;
350 case 'f':
351 x.interactive = I_ALWAYS_YES;
352 break;
353 case 'i':
354 x.interactive = I_ASK_USER;
355 break;
356 case 'n':
357 x.interactive = I_ALWAYS_NO;
358 break;
359 case DEBUG_OPTION:
360 x.debug = x.verbose = true;
361 break;
362 case NO_COPY_OPTION:
363 x.no_copy = true;
364 break;
365 case STRIP_TRAILING_SLASHES_OPTION:
366 remove_trailing_slashes = true;
367 break;
368 case 't':
369 if (target_directory)
370 die (EXIT_FAILURE, 0, _("multiple target directories specified"));
371 target_directory = optarg;
372 break;
373 case 'T':
374 no_target_directory = true;
375 break;
376 case 'u':
377 if (optarg == NULL)
378 x.update = true;
379 else if (x.interactive != I_ALWAYS_NO) /* -n takes precedence. */
381 enum Update_type update_opt;
382 update_opt = XARGMATCH ("--update", optarg,
383 update_type_string, update_type);
384 if (update_opt == UPDATE_ALL)
386 /* Default mv operation. */
387 x.update = false;
388 x.interactive = I_UNSPECIFIED;
390 else if (update_opt == UPDATE_NONE)
392 x.update = false;
393 x.interactive = I_ALWAYS_SKIP;
395 else if (update_opt == UPDATE_OLDER)
397 x.update = true;
398 x.interactive = I_UNSPECIFIED;
401 break;
402 case 'v':
403 x.verbose = true;
404 break;
405 case 'S':
406 make_backups = true;
407 backup_suffix = optarg;
408 break;
409 case 'Z':
410 /* As a performance enhancement, don't even bother trying
411 to "restorecon" when not on an selinux-enabled kernel. */
412 if (selinux_enabled)
414 x.preserve_security_context = false;
415 x.set_security_context = selabel_open (SELABEL_CTX_FILE, NULL, 0);
416 if (! x.set_security_context)
417 error (0, errno, _("warning: ignoring --context"));
419 break;
420 case_GETOPT_HELP_CHAR;
421 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
422 default:
423 usage (EXIT_FAILURE);
427 n_files = argc - optind;
428 file = argv + optind;
430 if (n_files <= !target_directory)
432 if (n_files <= 0)
433 error (0, 0, _("missing file operand"));
434 else
435 error (0, 0, _("missing destination file operand after %s"),
436 quoteaf (file[0]));
437 usage (EXIT_FAILURE);
440 struct stat sb;
441 sb.st_mode = 0;
442 int target_dirfd = AT_FDCWD;
443 if (no_target_directory)
445 if (target_directory)
446 die (EXIT_FAILURE, 0,
447 _("cannot combine --target-directory (-t) "
448 "and --no-target-directory (-T)"));
449 if (2 < n_files)
451 error (0, 0, _("extra operand %s"), quoteaf (file[2]));
452 usage (EXIT_FAILURE);
455 else if (target_directory)
457 target_dirfd = target_directory_operand (target_directory, &sb);
458 if (! target_dirfd_valid (target_dirfd))
459 die (EXIT_FAILURE, errno, _("target directory %s"),
460 quoteaf (target_directory));
462 else
464 char const *lastfile = file[n_files - 1];
465 if (n_files == 2)
466 x.rename_errno = (renameatu (AT_FDCWD, file[0], AT_FDCWD, lastfile,
467 RENAME_NOREPLACE)
468 ? errno : 0);
469 if (x.rename_errno != 0)
471 int fd = target_directory_operand (lastfile, &sb);
472 if (target_dirfd_valid (fd))
474 x.rename_errno = -1;
475 target_dirfd = fd;
476 target_directory = lastfile;
477 n_files--;
479 else
481 /* The last operand LASTFILE cannot be opened as a directory.
482 If there are more than two operands, report an error.
484 Also, report an error if LASTFILE is known to be a directory
485 even though it could not be opened, which can happen if
486 opening failed with EACCES on a platform lacking O_PATH.
487 In this case use stat to test whether LASTFILE is a
488 directory, in case opening a non-directory with (O_SEARCH
489 | O_DIRECTORY) failed with EACCES not ENOTDIR. */
490 int err = errno;
491 if (2 < n_files
492 || (O_PATHSEARCH == O_SEARCH && err == EACCES
493 && (sb.st_mode != 0 || stat (lastfile, &sb) == 0)
494 && S_ISDIR (sb.st_mode)))
495 die (EXIT_FAILURE, err, _("target %s"), quoteaf (lastfile));
500 /* Handle the ambiguity in the semantics of mv induced by the
501 varying semantics of the rename function. POSIX-compatible
502 systems (e.g., GNU/Linux) have a rename function that honors a
503 trailing slash in the source, while others (Solaris 9, FreeBSD
504 7.2) have a rename function that ignores it. */
505 if (remove_trailing_slashes)
506 for (int i = 0; i < n_files; i++)
507 strip_trailing_slashes (file[i]);
509 if (x.interactive == I_ALWAYS_NO)
510 x.update = false;
512 if (make_backups && x.interactive == I_ALWAYS_NO)
514 error (0, 0,
515 _("options --backup and --no-clobber are mutually exclusive"));
516 usage (EXIT_FAILURE);
519 x.backup_type = (make_backups
520 ? xget_version (_("backup type"),
521 version_control_string)
522 : no_backups);
523 set_simple_backup_suffix (backup_suffix);
525 hash_init ();
527 if (target_directory)
529 /* Initialize the hash table only if we'll need it.
530 The problem it is used to detect can arise only if there are
531 two or more files to move. */
532 if (2 <= n_files)
533 dest_info_init (&x);
535 ok = true;
536 for (int i = 0; i < n_files; ++i)
538 x.last_file = i + 1 == n_files;
539 char const *source = file[i];
540 char const *source_basename = last_component (source);
541 char *dest_relname;
542 char *dest = file_name_concat (target_directory, source_basename,
543 &dest_relname);
544 strip_trailing_slashes (dest_relname);
545 ok &= do_move (source, dest, target_dirfd, dest_relname, &x);
546 free (dest);
549 else
551 x.last_file = true;
552 ok = do_move (file[0], file[1], AT_FDCWD, file[1], &x);
555 main_exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);