1 /* remove.c -- core functions for removing files and directories
2 Copyright (C) 1988, 1990-1991, 1994-2011 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 <http://www.gnu.org/licenses/>. */
17 /* Extracted from rm.c, librarified, then rewritten twice by Jim Meyering. */
21 #include <sys/types.h>
26 #include "euidaccess-stat.h"
27 #include "file-type.h"
28 #include "ignore-value.h"
31 #include "root-dev-ino.h"
32 #include "write-any-file.h"
42 typedef enum Ternary Ternary;
44 /* The prompt function may be called twice for a given directory.
45 The first time, we ask whether to descend into it, and the
46 second time, we ask whether to remove it. */
49 PA_DESCEND_INTO_DIR = 2,
53 /* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN
55 #if ! HAVE_STRUCT_DIRENT_D_TYPE
56 /* Any int values will do here, so long as they're distinct.
57 Undef any existing macros out of the way. */
66 /* Like fstatat, but cache the result. If ST->st_size is -1, the
67 status has not been gotten yet. If less than -1, fstatat failed
68 with errno == ST->st_ino. Otherwise, the status has already
69 been gotten, so return 0. */
71 cache_fstatat (int fd, char const *file, struct stat *st, int flag)
73 if (st->st_size == -1 && fstatat (fd, file, st, flag) != 0)
80 errno = (int) st->st_ino;
84 /* Initialize a fstatat cache *ST. Return ST for convenience. */
85 static inline struct stat *
86 cache_stat_init (struct stat *st)
92 /* Return true if *ST has been statted. */
94 cache_statted (struct stat *st)
96 return (st->st_size != -1);
99 /* Return true if *ST has been statted successfully. */
101 cache_stat_ok (struct stat *st)
103 return (0 <= st->st_size);
106 /* Return 1 if FILE is an unwritable non-symlink,
107 0 if it is writable or some other type of file,
108 -1 and set errno if there is some problem in determining the answer.
109 Use FULL_NAME only if necessary.
110 Set *BUF to the file status.
111 This is to avoid calling euidaccess when FILE is a symlink. */
113 write_protected_non_symlink (int fd_cwd,
115 char const *full_name,
118 if (can_write_any_file ())
120 if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
122 if (S_ISLNK (buf->st_mode))
124 /* Here, we know FILE is not a symbolic link. */
126 /* In order to be reentrant -- i.e., to avoid changing the working
127 directory, and at the same time to be able to deal with alternate
128 access control mechanisms (ACLs, xattr-style attributes) and
129 arbitrarily deep trees -- we need a function like eaccessat, i.e.,
130 like Solaris' eaccess, but fd-relative, in the spirit of openat. */
132 /* In the absence of a native eaccessat function, here are some of
133 the implementation choices [#4 and #5 were suggested by Paul Eggert]:
134 1) call openat with O_WRONLY|O_NOCTTY
135 Disadvantage: may create the file and doesn't work for directory,
136 may mistakenly report `unwritable' for EROFS or ACLs even though
137 perm bits say the file is writable.
139 2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
140 Disadvantage: changes working directory (not reentrant) and can't
141 work if save_cwd fails.
143 3) if (euidaccess (full_name, W_OK) == 0)
144 Disadvantage: doesn't work if full_name is too long.
145 Inefficient for very deep trees (O(Depth^2)).
147 4) If the full pathname is sufficiently short (say, less than
148 PATH_MAX or 8192 bytes, whichever is shorter):
149 use method (3) (i.e., euidaccess (full_name, W_OK));
150 Otherwise: vfork, fchdir in the child, run euidaccess in the
151 child, then the child exits with a status that tells the parent
152 whether euidaccess succeeded.
154 This avoids the O(N**2) algorithm of method (3), and it also avoids
155 the failure-due-to-too-long-file-names of method (3), but it's fast
156 in the normal shallow case. It also avoids the lack-of-reentrancy
157 and the save_cwd problems.
158 Disadvantage; it uses a process slot for very-long file names,
159 and would be very slow for hierarchies with many such files.
161 5) If the full file name is sufficiently short (say, less than
162 PATH_MAX or 8192 bytes, whichever is shorter):
163 use method (3) (i.e., euidaccess (full_name, W_OK));
164 Otherwise: look just at the file bits. Perhaps issue a warning
165 the first time this occurs.
167 This is like (4), except for the "Otherwise" case where it isn't as
168 "perfect" as (4) but is considerably faster. It conforms to current
169 POSIX, and is uniformly better than what Solaris and FreeBSD do (they
170 mess up with long file names). */
173 /* This implements #1: on decent systems, either faccessat is
174 native or /proc/self/fd allows us to skip a chdir. */
175 if (!openat_needs_fchdir ())
177 if (faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0)
180 return errno == EACCES ? 1 : -1;
183 /* This implements #5: */
184 size_t file_name_len = strlen (full_name);
186 if (MIN (PATH_MAX, 8192) <= file_name_len)
187 return ! euidaccess_stat (buf, W_OK);
188 if (euidaccess (full_name, W_OK) == 0)
196 /* Perhaps some other process has removed the file, or perhaps this
197 is a buggy NFS client. */
202 /* Prompt whether to remove FILENAME (ent->, if required via a combination of
203 the options specified by X and/or file attributes. If the file may
204 be removed, return RM_OK. If the user declines to remove the file,
205 return RM_USER_DECLINED. If not ignoring missing files and we
206 cannot lstat FILENAME, then return RM_ERROR.
208 IS_DIR is true if ENT designates a directory, false otherwise.
210 Depending on MODE, ask whether to `descend into' or to `remove' the
211 directory FILENAME. MODE is ignored when FILENAME is not a directory.
212 Set *IS_EMPTY_P to T_YES if FILENAME is an empty directory, and it is
213 appropriate to try to remove it with rmdir (e.g. recursive mode).
214 Don't even try to set *IS_EMPTY_P when MODE == PA_REMOVE_DIR. */
215 static enum RM_status
216 prompt (FTS const *fts, FTSENT const *ent, bool is_dir,
217 struct rm_options const *x, enum Prompt_action mode,
220 int fd_cwd = fts->fts_cwd_fd;
221 char const *full_name = ent->fts_path;
222 char const *filename = ent->fts_accpath;
224 *is_empty_p = T_UNKNOWN;
227 struct stat *sbuf = &st;
228 cache_stat_init (sbuf);
230 int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN;
231 int write_protected = 0;
233 /* When nonzero, this indicates that we failed to remove a child entry,
234 either because the user declined an interactive prompt, or due to
235 some other failure, like permissions. */
237 return RM_USER_DECLINED;
239 if (x->interactive == RMI_NEVER)
243 if (!x->ignore_missing_files
244 && ((x->interactive == RMI_ALWAYS) || x->stdin_tty)
245 && dirent_type != DT_LNK)
247 write_protected = write_protected_non_symlink (fd_cwd, filename,
252 if (write_protected || x->interactive == RMI_ALWAYS)
254 if (0 <= write_protected && dirent_type == DT_UNKNOWN)
256 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0)
258 if (S_ISLNK (sbuf->st_mode))
259 dirent_type = DT_LNK;
260 else if (S_ISDIR (sbuf->st_mode))
261 dirent_type = DT_DIR;
262 /* Otherwise it doesn't matter, so leave it DT_UNKNOWN. */
266 /* This happens, e.g., with `rm '''. */
267 write_protected = -1;
272 if (0 <= write_protected)
276 /* Using permissions doesn't make sense for symlinks. */
277 if (x->interactive != RMI_ALWAYS)
284 write_protected = -1;
290 char const *quoted_name = quote (full_name);
292 if (write_protected < 0)
294 error (0, wp_errno, _("cannot remove %s"), quoted_name);
301 is_empty = is_empty_dir (fd_cwd, filename);
302 *is_empty_p = is_empty ? T_YES : T_NO;
307 /* Issue the prompt. */
308 if (dirent_type == DT_DIR
309 && mode == PA_DESCEND_INTO_DIR
313 ? _("%s: descend into write-protected directory %s? ")
314 : _("%s: descend into directory %s? ")),
315 program_name, quoted_name);
318 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
320 error (0, errno, _("cannot remove %s"), quoted_name);
326 /* TRANSLATORS: You may find it more convenient to
327 translate "%s: remove %s (write-protected) %s? "
328 instead. It should avoid grammatical problems
329 with the output of file_type. */
330 ? _("%s: remove write-protected %s %s? ")
331 : _("%s: remove %s %s? ")),
332 program_name, file_type (sbuf), quoted_name);
336 return RM_USER_DECLINED;
341 /* Return true if FILENAME is a directory (and not a symlink to a directory).
342 Otherwise, including the case in which lstat fails, return false.
343 *ST is FILENAME's tstatus.
344 Do not modify errno. */
346 is_dir_lstat (int fd_cwd, char const *filename, struct stat *st)
348 int saved_errno = errno;
350 (cache_fstatat (fd_cwd, filename, st, AT_SYMLINK_NOFOLLOW) == 0
351 && S_ISDIR (st->st_mode));
356 /* Return true if FILENAME is a non-directory.
357 Otherwise, including the case in which lstat fails, return false.
358 *ST is FILENAME's tstatus.
359 Do not modify errno. */
361 is_nondir_lstat (int fd_cwd, char const *filename, struct stat *st)
363 int saved_errno = errno;
365 (cache_fstatat (fd_cwd, filename, st, AT_SYMLINK_NOFOLLOW) == 0
366 && !S_ISDIR (st->st_mode));
371 /* When a function like unlink, rmdir, or fstatat fails with an errno
372 value of ERRNUM, return true if the specified file system object
373 is guaranteed not to exist; otherwise, return false. */
375 nonexistent_file_errno (int errnum)
377 /* Do not include ELOOP here, since the specified file may indeed
378 exist, but be (in)accessible only via too long a symlink chain.
379 Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail
380 if the "..." part expands to a long enough sequence of "./"s,
381 even though ./foo does indeed exist.
383 Another case to consider is when a particular name is invalid for
384 a given file system. In 2011, smbfs returns EINVAL, but the next
385 revision of POSIX will require EILSEQ for that situation:
386 http://austingroupbugs.net/view.php?id=293
401 /* Encapsulate the test for whether the errno value, ERRNUM, is ignorable. */
403 ignorable_missing (struct rm_options const *x, int errnum)
405 return x->ignore_missing_files && nonexistent_file_errno (errnum);
408 /* Tell fts not to traverse into the hierarchy at ENT. */
410 fts_skip_tree (FTS *fts, FTSENT *ent)
412 fts_set (fts, ent, FTS_SKIP);
413 /* Ensure that we do not process ENT a second time. */
414 ignore_value (fts_read (fts));
417 /* Upon unlink failure, or when the user declines to remove ENT, mark
418 each of its ancestor directories, so that we know not to prompt for
421 mark_ancestor_dirs (FTSENT *ent)
424 for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent)
432 /* Remove the file system object specified by ENT. IS_DIR specifies
433 whether it is expected to be a directory or non-directory.
434 Return RM_OK upon success, else RM_ERROR. */
435 static enum RM_status
436 excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
438 int flag = is_dir ? AT_REMOVEDIR : 0;
439 if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
444 ? _("removed directory: %s\n")
445 : _("removed %s\n")), quote (ent->fts_path));
450 /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
451 nonexistent files. When the file is indeed missing, map that to ENOENT,
452 so that rm -f ignores it, as required. Even without -f, this is useful
453 because it makes rm print the more precise diagnostic. */
457 if ( ! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st)
462 if (ignorable_missing (x, errno))
465 /* When failing to rmdir an unreadable directory, the typical
466 errno value is EISDIR, but that is not as useful to the user
467 as the errno value from the failed open (probably EPERM).
468 Use the earlier, more descriptive errno value. */
469 if (ent->fts_info == FTS_DNR)
470 errno = ent->fts_errno;
471 error (0, errno, _("cannot remove %s"), quote (ent->fts_path));
472 mark_ancestor_dirs (ent);
476 /* This function is called once for every file system object that fts
477 encounters. fts performs a depth-first traversal.
478 A directory is usually processed twice, first with fts_info == FTS_D,
479 and later, after all of its entries have been processed, with FTS_DP.
480 Return RM_ERROR upon error, RM_USER_DECLINED for a negative response
481 to an interactive prompt, and otherwise, RM_OK. */
482 static enum RM_status
483 rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
485 switch (ent->fts_info)
487 case FTS_D: /* preorder directory */
490 /* This is the first (pre-order) encounter with a directory.
491 Not recursive, so arrange to skip contents. */
492 error (0, EISDIR, _("cannot remove %s"), quote (ent->fts_path));
493 mark_ancestor_dirs (ent);
494 fts_skip_tree (fts, ent);
498 /* Perform checks that can apply only for command-line arguments. */
499 if (ent->fts_level == FTS_ROOTLEVEL)
501 if (strip_trailing_slashes (ent->fts_path))
502 ent->fts_pathlen = strlen (ent->fts_path);
504 /* If the basename of a command line argument is "." or "..",
505 diagnose it and do nothing more with that argument. */
506 if (dot_or_dotdot (last_component (ent->fts_accpath)))
508 error (0, 0, _("cannot remove directory: %s"),
509 quote (ent->fts_path));
510 fts_skip_tree (fts, ent);
514 /* If a command line argument resolves to "/" (and --preserve-root
515 is in effect -- default) diagnose and skip it. */
516 if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp))
518 ROOT_DEV_INO_WARN (ent->fts_path);
519 fts_skip_tree (fts, ent);
525 Ternary is_empty_directory;
526 enum RM_status s = prompt (fts, ent, true /*is_dir*/, x,
527 PA_DESCEND_INTO_DIR, &is_empty_directory);
529 if (s == RM_OK && is_empty_directory == T_YES)
531 /* When we know (from prompt when in interactive mode)
532 that this is an empty directory, don't prompt twice. */
533 s = excise (fts, ent, x, true);
534 fts_skip_tree (fts, ent);
539 mark_ancestor_dirs (ent);
540 fts_skip_tree (fts, ent);
546 case FTS_F: /* regular file */
547 case FTS_NS: /* stat(2) failed */
548 case FTS_SL: /* symbolic link */
549 case FTS_SLNONE: /* symbolic link without target */
550 case FTS_DP: /* postorder directory */
551 case FTS_DNR: /* unreadable directory */
552 case FTS_NSOK: /* e.g., dangling symlink */
553 case FTS_DEFAULT: /* none of the above */
555 /* With --one-file-system, do not attempt to remove a mount point.
556 fts' FTS_XDEV ensures that we don't process any entries under
558 if (ent->fts_info == FTS_DP
559 && x->one_file_system
560 && FTS_ROOTLEVEL < ent->fts_level
561 && ent->fts_statp->st_dev != fts->fts_dev)
563 mark_ancestor_dirs (ent);
564 error (0, 0, _("skipping %s, since it's on a different device"),
565 quote (ent->fts_path));
569 bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR;
570 enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR, NULL);
573 return excise (fts, ent, x, is_dir);
576 case FTS_DC: /* directory that causes cycles */
577 emit_cycle_warning (ent->fts_path);
578 fts_skip_tree (fts, ent);
582 /* Various failures, from opendir to ENOMEM, to failure to "return"
583 to preceding directory, can provoke this. */
584 error (0, ent->fts_errno, _("traversal failed: %s"),
585 quote (ent->fts_path));
586 fts_skip_tree (fts, ent);
590 error (0, 0, _("unexpected failure: fts_info=%d: %s\n"
591 "please report to %s"),
593 quote (ent->fts_path),
599 /* Remove FILEs, honoring options specified via X.
600 Return RM_OK if successful. */
602 rm (char *const *file, struct rm_options const *x)
604 enum RM_status rm_status = RM_OK;
608 int bit_flags = (FTS_CWDFD
612 if (x->one_file_system)
613 bit_flags |= FTS_XDEV;
615 FTS *fts = xfts_open (file, bit_flags, NULL);
621 ent = fts_read (fts);
626 error (0, errno, _("fts_read failed"));
627 rm_status = RM_ERROR;
632 enum RM_status s = rm_fts (fts, ent, x);
634 assert (VALID_STATUS (s));
635 UPDATE_STATUS (rm_status, s);
638 if (fts_close (fts) != 0)
640 error (0, errno, _("fts_close failed"));
641 rm_status = RM_ERROR;