du: --apparent counts only symlinks and regular
[coreutils.git] / src / remove.c
blobe1da19e38b86e5b516fc62fcb6d6705fc3b2d293
1 /* remove.c -- core functions for removing files and directories
2 Copyright (C) 1988-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 /* 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 "stat-time.h"
32 #include "write-any-file.h"
33 #include "xfts.h"
34 #include "yesno.h"
36 /* The prompt function may be called twice for a given directory.
37 The first time, we ask whether to descend into it, and the
38 second time, we ask whether to remove it. */
39 enum Prompt_action
41 PA_DESCEND_INTO_DIR = 2,
42 PA_REMOVE_DIR
45 /* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN
46 otherwise. */
47 #if ! HAVE_STRUCT_DIRENT_D_TYPE
48 /* Any int values will do here, so long as they're distinct.
49 Undef any existing macros out of the way. */
50 # undef DT_UNKNOWN
51 # undef DT_DIR
52 # undef DT_LNK
53 # define DT_UNKNOWN 0
54 # define DT_DIR 1
55 # define DT_LNK 2
56 #endif
58 /* Like fstatat, but cache on POSIX-compatible systems. */
59 static int
60 cache_fstatat (int fd, char const *file, struct stat *st, int flag)
62 #if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
63 /* If ST->st_atim.tv_nsec is -1, the status has not been gotten yet.
64 If less than -1, fstatat failed with errno == ST->st_ino.
65 Otherwise, the status has already been gotten, so return 0. */
66 if (0 <= st->st_atim.tv_nsec)
67 return 0;
68 if (st->st_atim.tv_nsec == -1)
70 if (fstatat (fd, file, st, flag) == 0)
71 return 0;
72 st->st_atim.tv_nsec = -2;
73 st->st_ino = errno;
75 errno = st->st_ino;
76 return -1;
77 #else
78 return fstatat (fd, file, st, flag);
79 #endif
82 /* Initialize a fstatat cache *ST. Return ST for convenience. */
83 static inline struct stat *
84 cache_stat_init (struct stat *st)
86 #if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
87 st->st_atim.tv_nsec = -1;
88 #endif
89 return st;
92 /* Return 1 if FILE is an unwritable non-symlink,
93 0 if it is writable or some other type of file,
94 -1 and set errno if there is some problem in determining the answer.
95 Set *BUF to the file status. */
96 static int
97 write_protected_non_symlink (int fd_cwd,
98 char const *file,
99 struct stat *buf)
101 if (can_write_any_file ())
102 return 0;
103 if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
104 return -1;
105 if (S_ISLNK (buf->st_mode))
106 return 0;
107 /* Here, we know FILE is not a symbolic link. */
109 /* In order to be reentrant -- i.e., to avoid changing the working
110 directory, and at the same time to be able to deal with alternate
111 access control mechanisms (ACLs, xattr-style attributes) and
112 arbitrarily deep trees -- we need a function like eaccessat, i.e.,
113 like Solaris' eaccess, but fd-relative, in the spirit of openat. */
115 /* In the absence of a native eaccessat function, here are some of
116 the implementation choices [#4 and #5 were suggested by Paul Eggert]:
117 1) call openat with O_WRONLY|O_NOCTTY
118 Disadvantage: may create the file and doesn't work for directory,
119 may mistakenly report 'unwritable' for EROFS or ACLs even though
120 perm bits say the file is writable.
122 2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
123 Disadvantage: changes working directory (not reentrant) and can't
124 work if save_cwd fails.
126 3) if (euidaccess (full_name, W_OK) == 0)
127 Disadvantage: doesn't work if full_name is too long.
128 Inefficient for very deep trees (O(Depth^2)).
130 4) If the full pathname is sufficiently short (say, less than
131 PATH_MAX or 8192 bytes, whichever is shorter):
132 use method (3) (i.e., euidaccess (full_name, W_OK));
133 Otherwise: vfork, fchdir in the child, run euidaccess in the
134 child, then the child exits with a status that tells the parent
135 whether euidaccess succeeded.
137 This avoids the O(N**2) algorithm of method (3), and it also avoids
138 the failure-due-to-too-long-file-names of method (3), but it's fast
139 in the normal shallow case. It also avoids the lack-of-reentrancy
140 and the save_cwd problems.
141 Disadvantage; it uses a process slot for very-long file names,
142 and would be very slow for hierarchies with many such files.
144 5) If the full file name is sufficiently short (say, less than
145 PATH_MAX or 8192 bytes, whichever is shorter):
146 use method (3) (i.e., euidaccess (full_name, W_OK));
147 Otherwise: look just at the file bits. Perhaps issue a warning
148 the first time this occurs.
150 This is like (4), except for the "Otherwise" case where it isn't as
151 "perfect" as (4) but is considerably faster. It conforms to current
152 POSIX, and is uniformly better than what Solaris and FreeBSD do (they
153 mess up with long file names). */
156 if (faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0)
157 return 0;
159 return errno == EACCES ? 1 : -1;
163 /* Return the status of the directory identified by FTS and ENT.
164 This is -1 if the directory is empty, 0 if it is nonempty,
165 and a positive error number if there was trouble determining the status,
166 e.g., it is not a directory, or permissions problems, or I/O errors.
167 Use *DIR_STATUS as a cache for the status. */
168 static int
169 get_dir_status (FTS const *fts, FTSENT const *ent, int *dir_status)
171 if (*dir_status == DS_UNKNOWN)
172 *dir_status = directory_status (fts->fts_cwd_fd, ent->fts_accpath);
173 return *dir_status;
176 /* Prompt whether to remove FILENAME, if required via a combination of
177 the options specified by X and/or file attributes. If the file may
178 be removed, return RM_OK or RM_USER_ACCEPTED, the latter if the user
179 was prompted and accepted. If the user declines to remove the file,
180 return RM_USER_DECLINED. If not ignoring missing files and we
181 cannot lstat FILENAME, then return RM_ERROR.
183 IS_DIR is true if ENT designates a directory, false otherwise.
185 Depending on MODE, ask whether to 'descend into' or to 'remove' the
186 directory FILENAME. MODE is ignored when FILENAME is not a directory.
187 Use and update *DIR_STATUS as needed, via the conventions of
188 get_dir_status. */
189 static enum RM_status
190 prompt (FTS const *fts, FTSENT const *ent, bool is_dir,
191 struct rm_options const *x, enum Prompt_action mode,
192 int *dir_status)
194 int fd_cwd = fts->fts_cwd_fd;
195 char const *full_name = ent->fts_path;
196 char const *filename = ent->fts_accpath;
197 struct stat st;
198 struct stat *sbuf = &st;
199 cache_stat_init (sbuf);
201 int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN;
202 int write_protected = 0;
204 /* When nonzero, this indicates that we failed to remove a child entry,
205 either because the user declined an interactive prompt, or due to
206 some other failure, like permissions. */
207 if (ent->fts_number)
208 return RM_USER_DECLINED;
210 if (x->interactive == RMI_NEVER)
211 return RM_OK;
213 int wp_errno = 0;
214 if (!x->ignore_missing_files
215 && (x->interactive == RMI_ALWAYS || x->stdin_tty)
216 && dirent_type != DT_LNK)
218 write_protected = write_protected_non_symlink (fd_cwd, filename, sbuf);
219 wp_errno = errno;
222 if (write_protected || x->interactive == RMI_ALWAYS)
224 if (0 <= write_protected && dirent_type == DT_UNKNOWN)
226 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0)
228 if (S_ISLNK (sbuf->st_mode))
229 dirent_type = DT_LNK;
230 else if (S_ISDIR (sbuf->st_mode))
231 dirent_type = DT_DIR;
232 /* Otherwise it doesn't matter, so leave it DT_UNKNOWN. */
234 else
236 /* This happens, e.g., with 'rm '''. */
237 write_protected = -1;
238 wp_errno = errno;
242 if (0 <= write_protected)
243 switch (dirent_type)
245 case DT_LNK:
246 /* Using permissions doesn't make sense for symlinks. */
247 if (x->interactive != RMI_ALWAYS)
248 return RM_OK;
249 break;
251 case DT_DIR:
252 /* Unless we're either deleting directories or deleting
253 recursively, we want to raise an EISDIR error rather than
254 prompting the user */
255 if ( ! (x->recursive
256 || (x->remove_empty_directories
257 && get_dir_status (fts, ent, dir_status) != 0)))
259 write_protected = -1;
260 wp_errno = *dir_status <= 0 ? EISDIR : *dir_status;
262 break;
265 char const *quoted_name = quoteaf (full_name);
267 if (write_protected < 0)
269 error (0, wp_errno, _("cannot remove %s"), quoted_name);
270 return RM_ERROR;
273 /* Issue the prompt. */
274 if (dirent_type == DT_DIR
275 && mode == PA_DESCEND_INTO_DIR
276 && get_dir_status (fts, ent, dir_status) == DS_NONEMPTY)
277 fprintf (stderr,
278 (write_protected
279 ? _("%s: descend into write-protected directory %s? ")
280 : _("%s: descend into directory %s? ")),
281 program_name, quoted_name);
282 else if (0 < *dir_status)
284 if ( ! (x->remove_empty_directories && *dir_status == EACCES))
286 error (0, *dir_status, _("cannot remove %s"), quoted_name);
287 return RM_ERROR;
290 /* The following code can lead to a successful deletion only with
291 the --dir (-d) option (remove_empty_directories) and an empty
292 inaccessible directory. In the first prompt call for a directory,
293 we'd normally ask whether to descend into it, but in this case
294 (it's inaccessible), that is not possible, so don't prompt. */
295 if (mode == PA_DESCEND_INTO_DIR)
296 return RM_OK;
298 fprintf (stderr,
299 _("%s: attempt removal of inaccessible directory %s? "),
300 program_name, quoted_name);
302 else
304 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
306 error (0, errno, _("cannot remove %s"), quoted_name);
307 return RM_ERROR;
310 fprintf (stderr,
311 (write_protected
312 /* TRANSLATORS: In the next two strings the second %s is
313 replaced by the type of the file. To avoid grammatical
314 problems, it may be more convenient to translate these
315 strings instead as: "%1$s: %3$s is write-protected and
316 is of type '%2$s' -- remove it? ". */
317 ? _("%s: remove write-protected %s %s? ")
318 : _("%s: remove %s %s? ")),
319 program_name, file_type (sbuf), quoted_name);
322 return yesno () ? RM_USER_ACCEPTED : RM_USER_DECLINED;
324 return RM_OK;
327 /* When a function like unlink, rmdir, or fstatat fails with an errno
328 value of ERRNUM, return true if the specified file system object
329 is guaranteed not to exist; otherwise, return false. */
330 static inline bool
331 nonexistent_file_errno (int errnum)
333 /* Do not include ELOOP here, since the specified file may indeed
334 exist, but be (in)accessible only via too long a symlink chain.
335 Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail
336 if the "..." part expands to a long enough sequence of "./"s,
337 even though ./foo does indeed exist.
339 Another case to consider is when a particular name is invalid for
340 a given file system. In 2011, smbfs returns EINVAL, but the next
341 revision of POSIX will require EILSEQ for that situation:
342 https://austingroupbugs.net/view.php?id=293
345 switch (errnum)
347 case EILSEQ:
348 case EINVAL:
349 case ENOENT:
350 case ENOTDIR:
351 return true;
352 default:
353 return false;
357 /* Encapsulate the test for whether the errno value, ERRNUM, is ignorable. */
358 static inline bool
359 ignorable_missing (struct rm_options const *x, int errnum)
361 return x->ignore_missing_files && nonexistent_file_errno (errnum);
364 /* Tell fts not to traverse into the hierarchy at ENT. */
365 static void
366 fts_skip_tree (FTS *fts, FTSENT *ent)
368 fts_set (fts, ent, FTS_SKIP);
369 /* Ensure that we do not process ENT a second time. */
370 ignore_value (fts_read (fts));
373 /* Upon unlink failure, or when the user declines to remove ENT, mark
374 each of its ancestor directories, so that we know not to prompt for
375 its removal. */
376 static void
377 mark_ancestor_dirs (FTSENT *ent)
379 FTSENT *p;
380 for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent)
382 if (p->fts_number)
383 break;
384 p->fts_number = 1;
388 /* Remove the file system object specified by ENT. IS_DIR specifies
389 whether it is expected to be a directory or non-directory.
390 Return RM_OK upon success, else RM_ERROR. */
391 static enum RM_status
392 excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
394 int flag = is_dir ? AT_REMOVEDIR : 0;
395 if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
397 if (x->verbose)
399 printf ((is_dir
400 ? _("removed directory %s\n")
401 : _("removed %s\n")), quoteaf (ent->fts_path));
403 return RM_OK;
406 /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
407 nonexistent files. When the file is indeed missing, map that to ENOENT,
408 so that rm -f ignores it, as required. Even without -f, this is useful
409 because it makes rm print the more precise diagnostic. */
410 if (errno == EROFS)
412 struct stat st;
413 if ( ! (fstatat (fts->fts_cwd_fd, ent->fts_accpath, &st,
414 AT_SYMLINK_NOFOLLOW)
415 && errno == ENOENT))
416 errno = EROFS;
419 if (ignorable_missing (x, errno))
420 return RM_OK;
422 /* When failing to rmdir an unreadable directory, we see errno values
423 like EISDIR or ENOTDIR (or, on Solaris 10, EEXIST), but they would be
424 meaningless in a diagnostic. When that happens, use the earlier, more
425 descriptive errno value. */
426 if (ent->fts_info == FTS_DNR
427 && (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR
428 || errno == EEXIST)
429 && ent->fts_errno != 0)
430 errno = ent->fts_errno;
431 error (0, errno, _("cannot remove %s"), quoteaf (ent->fts_path));
432 mark_ancestor_dirs (ent);
433 return RM_ERROR;
436 /* This function is called once for every file system object that fts
437 encounters. fts performs a depth-first traversal.
438 A directory is usually processed twice, first with fts_info == FTS_D,
439 and later, after all of its entries have been processed, with FTS_DP.
440 Return RM_ERROR upon error, RM_USER_DECLINED for a negative response
441 to an interactive prompt, and otherwise, RM_OK. */
442 static enum RM_status
443 rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
445 int dir_status = DS_UNKNOWN;
447 switch (ent->fts_info)
449 case FTS_D: /* preorder directory */
450 if (! x->recursive
451 && !(x->remove_empty_directories
452 && get_dir_status (fts, ent, &dir_status) != 0))
454 /* This is the first (pre-order) encounter with a directory
455 that we cannot delete.
456 Not recursive, and it's not an empty directory (if we're removing
457 them) so arrange to skip contents. */
458 int err = x->remove_empty_directories ? ENOTEMPTY : EISDIR;
459 error (0, err, _("cannot remove %s"), quoteaf (ent->fts_path));
460 mark_ancestor_dirs (ent);
461 fts_skip_tree (fts, ent);
462 return RM_ERROR;
465 /* Perform checks that can apply only for command-line arguments. */
466 if (ent->fts_level == FTS_ROOTLEVEL)
468 /* POSIX says:
469 If the basename of a command line argument is "." or "..",
470 diagnose it and do nothing more with that argument. */
471 if (dot_or_dotdot (last_component (ent->fts_accpath)))
473 error (0, 0,
474 _("refusing to remove %s or %s directory: skipping %s"),
475 quoteaf_n (0, "."), quoteaf_n (1, ".."),
476 quoteaf_n (2, ent->fts_path));
477 fts_skip_tree (fts, ent);
478 return RM_ERROR;
481 /* POSIX also says:
482 If a command line argument resolves to "/" (and --preserve-root
483 is in effect -- default) diagnose and skip it. */
484 if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp))
486 ROOT_DEV_INO_WARN (ent->fts_path);
487 fts_skip_tree (fts, ent);
488 return RM_ERROR;
491 /* If a command line argument is a mount point and
492 --preserve-root=all is in effect, diagnose and skip it.
493 This doesn't handle "/", but that's handled above. */
494 if (x->preserve_all_root)
496 bool failed = false;
497 char *parent = file_name_concat (ent->fts_accpath, "..", NULL);
498 struct stat statbuf;
500 if (!parent || lstat (parent, &statbuf))
502 error (0, 0,
503 _("failed to stat %s: skipping %s"),
504 quoteaf_n (0, parent),
505 quoteaf_n (1, ent->fts_accpath));
506 failed = true;
509 free (parent);
511 if (failed || fts->fts_dev != statbuf.st_dev)
513 if (! failed)
515 error (0, 0,
516 _("skipping %s, since it's on a different device"),
517 quoteaf (ent->fts_path));
518 error (0, 0, _("and --preserve-root=all is in effect"));
520 fts_skip_tree (fts, ent);
521 return RM_ERROR;
527 enum RM_status s = prompt (fts, ent, true /*is_dir*/, x,
528 PA_DESCEND_INTO_DIR, &dir_status);
530 if (s == RM_USER_ACCEPTED && dir_status == DS_EMPTY)
532 /* When we know (from prompt when in interactive mode)
533 that this is an empty directory, don't prompt twice. */
534 s = excise (fts, ent, x, true);
535 if (s == RM_OK)
536 fts_skip_tree (fts, ent);
539 if (! (s == RM_OK || s == RM_USER_ACCEPTED))
541 mark_ancestor_dirs (ent);
542 fts_skip_tree (fts, ent);
545 return s;
548 case FTS_F: /* regular file */
549 case FTS_NS: /* stat(2) failed */
550 case FTS_SL: /* symbolic link */
551 case FTS_SLNONE: /* symbolic link without target */
552 case FTS_DP: /* postorder directory */
553 case FTS_DNR: /* unreadable directory */
554 case FTS_NSOK: /* e.g., dangling symlink */
555 case FTS_DEFAULT: /* none of the above */
557 /* With --one-file-system, do not attempt to remove a mount point.
558 fts' FTS_XDEV ensures that we don't process any entries under
559 the mount point. */
560 if (ent->fts_info == FTS_DP
561 && x->one_file_system
562 && FTS_ROOTLEVEL < ent->fts_level
563 && ent->fts_statp->st_dev != fts->fts_dev)
565 mark_ancestor_dirs (ent);
566 error (0, 0, _("skipping %s, since it's on a different device"),
567 quoteaf (ent->fts_path));
568 return RM_ERROR;
571 bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR;
572 enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR,
573 &dir_status);
574 if (! (s == RM_OK || s == RM_USER_ACCEPTED))
575 return s;
576 return excise (fts, ent, x, is_dir);
579 case FTS_DC: /* directory that causes cycles */
580 emit_cycle_warning (ent->fts_path);
581 fts_skip_tree (fts, ent);
582 return RM_ERROR;
584 case FTS_ERR:
585 /* Various failures, from opendir to ENOMEM, to failure to "return"
586 to preceding directory, can provoke this. */
587 error (0, ent->fts_errno, _("traversal failed: %s"),
588 quotef (ent->fts_path));
589 fts_skip_tree (fts, ent);
590 return RM_ERROR;
592 default:
593 error (0, 0, _("unexpected failure: fts_info=%d: %s\n"
594 "please report to %s"),
595 ent->fts_info,
596 quotef (ent->fts_path),
597 PACKAGE_BUGREPORT);
598 abort ();
602 /* Remove FILEs, honoring options specified via X.
603 Return RM_OK if successful. */
604 enum RM_status
605 rm (char *const *file, struct rm_options const *x)
607 enum RM_status rm_status = RM_OK;
609 if (*file)
611 int bit_flags = (FTS_CWDFD
612 | FTS_NOSTAT
613 | FTS_PHYSICAL);
615 if (x->one_file_system)
616 bit_flags |= FTS_XDEV;
618 FTS *fts = xfts_open (file, bit_flags, NULL);
620 while (true)
622 FTSENT *ent;
624 ent = fts_read (fts);
625 if (ent == NULL)
627 if (errno != 0)
629 error (0, errno, _("fts_read failed"));
630 rm_status = RM_ERROR;
632 break;
635 enum RM_status s = rm_fts (fts, ent, x);
637 assert (VALID_STATUS (s));
638 UPDATE_STATUS (rm_status, s);
641 if (fts_close (fts) != 0)
643 error (0, errno, _("fts_close failed"));
644 rm_status = RM_ERROR;
648 return rm_status;