dd: output final progress before syncing
[coreutils.git] / src / remove.c
blob28d55ff92d0a708005014b50dad9023ece47df86
1 /* remove.c -- core functions for removing files and directories
2 Copyright (C) 1988-2022 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 /* Extracted from rm.c, librarified, then rewritten twice by Jim Meyering. */
19 #include <config.h>
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <assert.h>
24 #include "system.h"
25 #include "error.h"
26 #include "file-type.h"
27 #include "filenamecat.h"
28 #include "ignore-value.h"
29 #include "remove.h"
30 #include "root-dev-ino.h"
31 #include "write-any-file.h"
32 #include "xfts.h"
33 #include "yesno.h"
35 enum Ternary
37 T_UNKNOWN = 2,
38 T_NO,
39 T_YES
41 typedef enum Ternary Ternary;
43 /* The prompt function may be called twice for a given directory.
44 The first time, we ask whether to descend into it, and the
45 second time, we ask whether to remove it. */
46 enum Prompt_action
48 PA_DESCEND_INTO_DIR = 2,
49 PA_REMOVE_DIR
52 /* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN
53 otherwise. */
54 #if ! HAVE_STRUCT_DIRENT_D_TYPE
55 /* Any int values will do here, so long as they're distinct.
56 Undef any existing macros out of the way. */
57 # undef DT_UNKNOWN
58 # undef DT_DIR
59 # undef DT_LNK
60 # define DT_UNKNOWN 0
61 # define DT_DIR 1
62 # define DT_LNK 2
63 #endif
65 /* Like fstatat, but cache the result. If ST->st_size is -1, the
66 status has not been gotten yet. If less than -1, fstatat failed
67 with errno == ST->st_ino. Otherwise, the status has already
68 been gotten, so return 0. */
69 static int
70 cache_fstatat (int fd, char const *file, struct stat *st, int flag)
72 if (st->st_size == -1 && fstatat (fd, file, st, flag) != 0)
74 st->st_size = -2;
75 st->st_ino = errno;
77 if (0 <= st->st_size)
78 return 0;
79 errno = (int) st->st_ino;
80 return -1;
83 /* Initialize a fstatat cache *ST. Return ST for convenience. */
84 static inline struct stat *
85 cache_stat_init (struct stat *st)
87 st->st_size = -1;
88 return st;
91 /* Return 1 if FILE is an unwritable non-symlink,
92 0 if it is writable or some other type of file,
93 -1 and set errno if there is some problem in determining the answer.
94 Set *BUF to the file status. */
95 static int
96 write_protected_non_symlink (int fd_cwd,
97 char const *file,
98 struct stat *buf)
100 if (can_write_any_file ())
101 return 0;
102 if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
103 return -1;
104 if (S_ISLNK (buf->st_mode))
105 return 0;
106 /* Here, we know FILE is not a symbolic link. */
108 /* In order to be reentrant -- i.e., to avoid changing the working
109 directory, and at the same time to be able to deal with alternate
110 access control mechanisms (ACLs, xattr-style attributes) and
111 arbitrarily deep trees -- we need a function like eaccessat, i.e.,
112 like Solaris' eaccess, but fd-relative, in the spirit of openat. */
114 /* In the absence of a native eaccessat function, here are some of
115 the implementation choices [#4 and #5 were suggested by Paul Eggert]:
116 1) call openat with O_WRONLY|O_NOCTTY
117 Disadvantage: may create the file and doesn't work for directory,
118 may mistakenly report 'unwritable' for EROFS or ACLs even though
119 perm bits say the file is writable.
121 2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
122 Disadvantage: changes working directory (not reentrant) and can't
123 work if save_cwd fails.
125 3) if (euidaccess (full_name, W_OK) == 0)
126 Disadvantage: doesn't work if full_name is too long.
127 Inefficient for very deep trees (O(Depth^2)).
129 4) If the full pathname is sufficiently short (say, less than
130 PATH_MAX or 8192 bytes, whichever is shorter):
131 use method (3) (i.e., euidaccess (full_name, W_OK));
132 Otherwise: vfork, fchdir in the child, run euidaccess in the
133 child, then the child exits with a status that tells the parent
134 whether euidaccess succeeded.
136 This avoids the O(N**2) algorithm of method (3), and it also avoids
137 the failure-due-to-too-long-file-names of method (3), but it's fast
138 in the normal shallow case. It also avoids the lack-of-reentrancy
139 and the save_cwd problems.
140 Disadvantage; it uses a process slot for very-long file names,
141 and would be very slow for hierarchies with many such files.
143 5) If the full file name is sufficiently short (say, less than
144 PATH_MAX or 8192 bytes, whichever is shorter):
145 use method (3) (i.e., euidaccess (full_name, W_OK));
146 Otherwise: look just at the file bits. Perhaps issue a warning
147 the first time this occurs.
149 This is like (4), except for the "Otherwise" case where it isn't as
150 "perfect" as (4) but is considerably faster. It conforms to current
151 POSIX, and is uniformly better than what Solaris and FreeBSD do (they
152 mess up with long file names). */
155 if (faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0)
156 return 0;
158 return errno == EACCES ? 1 : -1;
162 /* Prompt whether to remove FILENAME (ent->, if required via a combination of
163 the options specified by X and/or file attributes. If the file may
164 be removed, return RM_OK. If the user declines to remove the file,
165 return RM_USER_DECLINED. If not ignoring missing files and we
166 cannot lstat FILENAME, then return RM_ERROR.
168 IS_DIR is true if ENT designates a directory, false otherwise.
170 Depending on MODE, ask whether to 'descend into' or to 'remove' the
171 directory FILENAME. MODE is ignored when FILENAME is not a directory.
172 Set *IS_EMPTY_P to T_YES if FILENAME is an empty directory, and it is
173 appropriate to try to remove it with rmdir (e.g. recursive mode).
174 Don't even try to set *IS_EMPTY_P when MODE == PA_REMOVE_DIR. */
175 static enum RM_status
176 prompt (FTS const *fts, FTSENT const *ent, bool is_dir,
177 struct rm_options const *x, enum Prompt_action mode,
178 Ternary *is_empty_p)
180 int fd_cwd = fts->fts_cwd_fd;
181 char const *full_name = ent->fts_path;
182 char const *filename = ent->fts_accpath;
183 if (is_empty_p)
184 *is_empty_p = T_UNKNOWN;
186 struct stat st;
187 struct stat *sbuf = &st;
188 cache_stat_init (sbuf);
190 int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN;
191 int write_protected = 0;
193 bool is_empty = false;
194 if (is_empty_p)
196 is_empty = is_empty_dir (fd_cwd, filename);
197 *is_empty_p = is_empty ? T_YES : T_NO;
200 /* When nonzero, this indicates that we failed to remove a child entry,
201 either because the user declined an interactive prompt, or due to
202 some other failure, like permissions. */
203 if (ent->fts_number)
204 return RM_USER_DECLINED;
206 if (x->interactive == RMI_NEVER)
207 return RM_OK;
209 int wp_errno = 0;
210 if (!x->ignore_missing_files
211 && ((x->interactive == RMI_ALWAYS) || x->stdin_tty)
212 && dirent_type != DT_LNK)
214 write_protected = write_protected_non_symlink (fd_cwd, filename, sbuf);
215 wp_errno = errno;
218 if (write_protected || x->interactive == RMI_ALWAYS)
220 if (0 <= write_protected && dirent_type == DT_UNKNOWN)
222 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0)
224 if (S_ISLNK (sbuf->st_mode))
225 dirent_type = DT_LNK;
226 else if (S_ISDIR (sbuf->st_mode))
227 dirent_type = DT_DIR;
228 /* Otherwise it doesn't matter, so leave it DT_UNKNOWN. */
230 else
232 /* This happens, e.g., with 'rm '''. */
233 write_protected = -1;
234 wp_errno = errno;
238 if (0 <= write_protected)
239 switch (dirent_type)
241 case DT_LNK:
242 /* Using permissions doesn't make sense for symlinks. */
243 if (x->interactive != RMI_ALWAYS)
244 return RM_OK;
245 break;
247 case DT_DIR:
248 /* Unless we're either deleting directories or deleting
249 recursively, we want to raise an EISDIR error rather than
250 prompting the user */
251 if ( ! (x->recursive || (x->remove_empty_directories && is_empty)))
253 write_protected = -1;
254 wp_errno = EISDIR;
256 break;
259 char const *quoted_name = quoteaf (full_name);
261 if (write_protected < 0)
263 error (0, wp_errno, _("cannot remove %s"), quoted_name);
264 return RM_ERROR;
267 /* Issue the prompt. */
268 if (dirent_type == DT_DIR
269 && mode == PA_DESCEND_INTO_DIR
270 && !is_empty)
271 fprintf (stderr,
272 (write_protected
273 ? _("%s: descend into write-protected directory %s? ")
274 : _("%s: descend into directory %s? ")),
275 program_name, quoted_name);
276 else
278 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
280 error (0, errno, _("cannot remove %s"), quoted_name);
281 return RM_ERROR;
284 fprintf (stderr,
285 (write_protected
286 /* TRANSLATORS: In the next two strings the second %s is
287 replaced by the type of the file. To avoid grammatical
288 problems, it may be more convenient to translate these
289 strings instead as: "%1$s: %3$s is write-protected and
290 is of type '%2$s' -- remove it? ". */
291 ? _("%s: remove write-protected %s %s? ")
292 : _("%s: remove %s %s? ")),
293 program_name, file_type (sbuf), quoted_name);
296 if (!yesno ())
297 return RM_USER_DECLINED;
299 return RM_OK;
302 /* When a function like unlink, rmdir, or fstatat fails with an errno
303 value of ERRNUM, return true if the specified file system object
304 is guaranteed not to exist; otherwise, return false. */
305 static inline bool
306 nonexistent_file_errno (int errnum)
308 /* Do not include ELOOP here, since the specified file may indeed
309 exist, but be (in)accessible only via too long a symlink chain.
310 Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail
311 if the "..." part expands to a long enough sequence of "./"s,
312 even though ./foo does indeed exist.
314 Another case to consider is when a particular name is invalid for
315 a given file system. In 2011, smbfs returns EINVAL, but the next
316 revision of POSIX will require EILSEQ for that situation:
317 http://austingroupbugs.net/view.php?id=293
320 switch (errnum)
322 case EILSEQ:
323 case EINVAL:
324 case ENOENT:
325 case ENOTDIR:
326 return true;
327 default:
328 return false;
332 /* Encapsulate the test for whether the errno value, ERRNUM, is ignorable. */
333 static inline bool
334 ignorable_missing (struct rm_options const *x, int errnum)
336 return x->ignore_missing_files && nonexistent_file_errno (errnum);
339 /* Tell fts not to traverse into the hierarchy at ENT. */
340 static void
341 fts_skip_tree (FTS *fts, FTSENT *ent)
343 fts_set (fts, ent, FTS_SKIP);
344 /* Ensure that we do not process ENT a second time. */
345 ignore_value (fts_read (fts));
348 /* Upon unlink failure, or when the user declines to remove ENT, mark
349 each of its ancestor directories, so that we know not to prompt for
350 its removal. */
351 static void
352 mark_ancestor_dirs (FTSENT *ent)
354 FTSENT *p;
355 for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent)
357 if (p->fts_number)
358 break;
359 p->fts_number = 1;
363 /* Remove the file system object specified by ENT. IS_DIR specifies
364 whether it is expected to be a directory or non-directory.
365 Return RM_OK upon success, else RM_ERROR. */
366 static enum RM_status
367 excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
369 int flag = is_dir ? AT_REMOVEDIR : 0;
370 if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
372 if (x->verbose)
374 printf ((is_dir
375 ? _("removed directory %s\n")
376 : _("removed %s\n")), quoteaf (ent->fts_path));
378 return RM_OK;
381 /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
382 nonexistent files. When the file is indeed missing, map that to ENOENT,
383 so that rm -f ignores it, as required. Even without -f, this is useful
384 because it makes rm print the more precise diagnostic. */
385 if (errno == EROFS)
387 struct stat st;
388 if ( ! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st)
389 && errno == ENOENT))
390 errno = EROFS;
393 if (ignorable_missing (x, errno))
394 return RM_OK;
396 /* When failing to rmdir an unreadable directory, we see errno values
397 like EISDIR or ENOTDIR (or, on Solaris 10, EEXIST), but they would be
398 meaningless in a diagnostic. When that happens and the errno value
399 from the failed open is EPERM or EACCES, use the earlier, more
400 descriptive errno value. */
401 if (ent->fts_info == FTS_DNR
402 && (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR
403 || errno == EEXIST)
404 && (ent->fts_errno == EPERM || ent->fts_errno == EACCES))
405 errno = ent->fts_errno;
406 error (0, errno, _("cannot remove %s"), quoteaf (ent->fts_path));
407 mark_ancestor_dirs (ent);
408 return RM_ERROR;
411 /* This function is called once for every file system object that fts
412 encounters. fts performs a depth-first traversal.
413 A directory is usually processed twice, first with fts_info == FTS_D,
414 and later, after all of its entries have been processed, with FTS_DP.
415 Return RM_ERROR upon error, RM_USER_DECLINED for a negative response
416 to an interactive prompt, and otherwise, RM_OK. */
417 static enum RM_status
418 rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
420 switch (ent->fts_info)
422 case FTS_D: /* preorder directory */
423 if (! x->recursive
424 && !(x->remove_empty_directories
425 && is_empty_dir (fts->fts_cwd_fd, ent->fts_accpath)))
427 /* This is the first (pre-order) encounter with a directory
428 that we cannot delete.
429 Not recursive, and it's not an empty directory (if we're removing
430 them) so arrange to skip contents. */
431 int err = x->remove_empty_directories ? ENOTEMPTY : EISDIR;
432 error (0, err, _("cannot remove %s"), quoteaf (ent->fts_path));
433 mark_ancestor_dirs (ent);
434 fts_skip_tree (fts, ent);
435 return RM_ERROR;
438 /* Perform checks that can apply only for command-line arguments. */
439 if (ent->fts_level == FTS_ROOTLEVEL)
441 /* POSIX says:
442 If the basename of a command line argument is "." or "..",
443 diagnose it and do nothing more with that argument. */
444 if (dot_or_dotdot (last_component (ent->fts_accpath)))
446 error (0, 0,
447 _("refusing to remove %s or %s directory: skipping %s"),
448 quoteaf_n (0, "."), quoteaf_n (1, ".."),
449 quoteaf_n (2, ent->fts_path));
450 fts_skip_tree (fts, ent);
451 return RM_ERROR;
454 /* POSIX also says:
455 If a command line argument resolves to "/" (and --preserve-root
456 is in effect -- default) diagnose and skip it. */
457 if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp))
459 ROOT_DEV_INO_WARN (ent->fts_path);
460 fts_skip_tree (fts, ent);
461 return RM_ERROR;
464 /* If a command line argument is a mount point and
465 --preserve-root=all is in effect, diagnose and skip it.
466 This doesn't handle "/", but that's handled above. */
467 if (x->preserve_all_root)
469 bool failed = false;
470 char *parent = file_name_concat (ent->fts_accpath, "..", NULL);
471 struct stat statbuf;
473 if (!parent || lstat (parent, &statbuf))
475 error (0, 0,
476 _("failed to stat %s: skipping %s"),
477 quoteaf_n (0, parent),
478 quoteaf_n (1, ent->fts_accpath));
479 failed = true;
482 free (parent);
484 if (failed || fts->fts_dev != statbuf.st_dev)
486 if (! failed)
488 error (0, 0,
489 _("skipping %s, since it's on a different device"),
490 quoteaf (ent->fts_path));
491 error (0, 0, _("and --preserve-root=all is in effect"));
493 fts_skip_tree (fts, ent);
494 return RM_ERROR;
500 Ternary is_empty_directory;
501 enum RM_status s = prompt (fts, ent, true /*is_dir*/, x,
502 PA_DESCEND_INTO_DIR, &is_empty_directory);
504 if (s == RM_OK && is_empty_directory == T_YES)
506 /* When we know (from prompt when in interactive mode)
507 that this is an empty directory, don't prompt twice. */
508 s = excise (fts, ent, x, true);
509 if (s == RM_OK)
510 fts_skip_tree (fts, ent);
513 if (s != RM_OK)
515 mark_ancestor_dirs (ent);
516 fts_skip_tree (fts, ent);
519 return s;
522 case FTS_F: /* regular file */
523 case FTS_NS: /* stat(2) failed */
524 case FTS_SL: /* symbolic link */
525 case FTS_SLNONE: /* symbolic link without target */
526 case FTS_DP: /* postorder directory */
527 case FTS_DNR: /* unreadable directory */
528 case FTS_NSOK: /* e.g., dangling symlink */
529 case FTS_DEFAULT: /* none of the above */
531 /* With --one-file-system, do not attempt to remove a mount point.
532 fts' FTS_XDEV ensures that we don't process any entries under
533 the mount point. */
534 if (ent->fts_info == FTS_DP
535 && x->one_file_system
536 && FTS_ROOTLEVEL < ent->fts_level
537 && ent->fts_statp->st_dev != fts->fts_dev)
539 mark_ancestor_dirs (ent);
540 error (0, 0, _("skipping %s, since it's on a different device"),
541 quoteaf (ent->fts_path));
542 return RM_ERROR;
545 bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR;
546 enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR, NULL);
547 if (s != RM_OK)
548 return s;
549 return excise (fts, ent, x, is_dir);
552 case FTS_DC: /* directory that causes cycles */
553 emit_cycle_warning (ent->fts_path);
554 fts_skip_tree (fts, ent);
555 return RM_ERROR;
557 case FTS_ERR:
558 /* Various failures, from opendir to ENOMEM, to failure to "return"
559 to preceding directory, can provoke this. */
560 error (0, ent->fts_errno, _("traversal failed: %s"),
561 quotef (ent->fts_path));
562 fts_skip_tree (fts, ent);
563 return RM_ERROR;
565 default:
566 error (0, 0, _("unexpected failure: fts_info=%d: %s\n"
567 "please report to %s"),
568 ent->fts_info,
569 quotef (ent->fts_path),
570 PACKAGE_BUGREPORT);
571 abort ();
575 /* Remove FILEs, honoring options specified via X.
576 Return RM_OK if successful. */
577 enum RM_status
578 rm (char *const *file, struct rm_options const *x)
580 enum RM_status rm_status = RM_OK;
582 if (*file)
584 int bit_flags = (FTS_CWDFD
585 | FTS_NOSTAT
586 | FTS_PHYSICAL);
588 if (x->one_file_system)
589 bit_flags |= FTS_XDEV;
591 FTS *fts = xfts_open (file, bit_flags, NULL);
593 while (true)
595 FTSENT *ent;
597 ent = fts_read (fts);
598 if (ent == NULL)
600 if (errno != 0)
602 error (0, errno, _("fts_read failed"));
603 rm_status = RM_ERROR;
605 break;
608 enum RM_status s = rm_fts (fts, ent, x);
610 assert (VALID_STATUS (s));
611 UPDATE_STATUS (rm_status, s);
614 if (fts_close (fts) != 0)
616 error (0, errno, _("fts_close failed"));
617 rm_status = RM_ERROR;
621 return rm_status;