maint: revert "build: update gnulib submodule to latest"
[coreutils/ericb.git] / src / remove.c
blobc650543060a3a90510ee00f6d4d29533fe48911e
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. */
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 "ignore-value.h"
28 #include "quote.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 true if *ST has been statted. */
92 static inline bool
93 cache_statted (struct stat *st)
95 return (st->st_size != -1);
98 /* Return true if *ST has been statted successfully. */
99 static inline bool
100 cache_stat_ok (struct stat *st)
102 return (0 <= st->st_size);
105 /* Return 1 if FILE is an unwritable non-symlink,
106 0 if it is writable or some other type of file,
107 -1 and set errno if there is some problem in determining the answer.
108 Set *BUF to the file status. */
109 static int
110 write_protected_non_symlink (int fd_cwd,
111 char const *file,
112 struct stat *buf)
114 if (can_write_any_file ())
115 return 0;
116 if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
117 return -1;
118 if (S_ISLNK (buf->st_mode))
119 return 0;
120 /* Here, we know FILE is not a symbolic link. */
122 /* In order to be reentrant -- i.e., to avoid changing the working
123 directory, and at the same time to be able to deal with alternate
124 access control mechanisms (ACLs, xattr-style attributes) and
125 arbitrarily deep trees -- we need a function like eaccessat, i.e.,
126 like Solaris' eaccess, but fd-relative, in the spirit of openat. */
128 /* In the absence of a native eaccessat function, here are some of
129 the implementation choices [#4 and #5 were suggested by Paul Eggert]:
130 1) call openat with O_WRONLY|O_NOCTTY
131 Disadvantage: may create the file and doesn't work for directory,
132 may mistakenly report `unwritable' for EROFS or ACLs even though
133 perm bits say the file is writable.
135 2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
136 Disadvantage: changes working directory (not reentrant) and can't
137 work if save_cwd fails.
139 3) if (euidaccess (full_name, W_OK) == 0)
140 Disadvantage: doesn't work if full_name is too long.
141 Inefficient for very deep trees (O(Depth^2)).
143 4) If the full pathname 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: vfork, fchdir in the child, run euidaccess in the
147 child, then the child exits with a status that tells the parent
148 whether euidaccess succeeded.
150 This avoids the O(N**2) algorithm of method (3), and it also avoids
151 the failure-due-to-too-long-file-names of method (3), but it's fast
152 in the normal shallow case. It also avoids the lack-of-reentrancy
153 and the save_cwd problems.
154 Disadvantage; it uses a process slot for very-long file names,
155 and would be very slow for hierarchies with many such files.
157 5) If the full file name is sufficiently short (say, less than
158 PATH_MAX or 8192 bytes, whichever is shorter):
159 use method (3) (i.e., euidaccess (full_name, W_OK));
160 Otherwise: look just at the file bits. Perhaps issue a warning
161 the first time this occurs.
163 This is like (4), except for the "Otherwise" case where it isn't as
164 "perfect" as (4) but is considerably faster. It conforms to current
165 POSIX, and is uniformly better than what Solaris and FreeBSD do (they
166 mess up with long file names). */
169 if (faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0)
170 return 0;
172 return errno == EACCES ? 1 : -1;
176 /* Prompt whether to remove FILENAME (ent->, 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. If the user declines to remove the file,
179 return RM_USER_DECLINED. If not ignoring missing files and we
180 cannot lstat FILENAME, then return RM_ERROR.
182 IS_DIR is true if ENT designates a directory, false otherwise.
184 Depending on MODE, ask whether to `descend into' or to `remove' the
185 directory FILENAME. MODE is ignored when FILENAME is not a directory.
186 Set *IS_EMPTY_P to T_YES if FILENAME is an empty directory, and it is
187 appropriate to try to remove it with rmdir (e.g. recursive mode).
188 Don't even try to set *IS_EMPTY_P when MODE == PA_REMOVE_DIR. */
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 Ternary *is_empty_p)
194 int fd_cwd = fts->fts_cwd_fd;
195 char const *full_name = ent->fts_path;
196 char const *filename = ent->fts_accpath;
197 if (is_empty_p)
198 *is_empty_p = T_UNKNOWN;
200 struct stat st;
201 struct stat *sbuf = &st;
202 cache_stat_init (sbuf);
204 int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN;
205 int write_protected = 0;
207 /* When nonzero, this indicates that we failed to remove a child entry,
208 either because the user declined an interactive prompt, or due to
209 some other failure, like permissions. */
210 if (ent->fts_number)
211 return RM_USER_DECLINED;
213 if (x->interactive == RMI_NEVER)
214 return RM_OK;
216 int wp_errno = 0;
217 if (!x->ignore_missing_files
218 && ((x->interactive == RMI_ALWAYS) || x->stdin_tty)
219 && dirent_type != DT_LNK)
221 write_protected = write_protected_non_symlink (fd_cwd, filename, sbuf);
222 wp_errno = errno;
225 if (write_protected || x->interactive == RMI_ALWAYS)
227 if (0 <= write_protected && dirent_type == DT_UNKNOWN)
229 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0)
231 if (S_ISLNK (sbuf->st_mode))
232 dirent_type = DT_LNK;
233 else if (S_ISDIR (sbuf->st_mode))
234 dirent_type = DT_DIR;
235 /* Otherwise it doesn't matter, so leave it DT_UNKNOWN. */
237 else
239 /* This happens, e.g., with `rm '''. */
240 write_protected = -1;
241 wp_errno = errno;
245 if (0 <= write_protected)
246 switch (dirent_type)
248 case DT_LNK:
249 /* Using permissions doesn't make sense for symlinks. */
250 if (x->interactive != RMI_ALWAYS)
251 return RM_OK;
252 break;
254 case DT_DIR:
255 if (!x->recursive)
257 write_protected = -1;
258 wp_errno = EISDIR;
260 break;
263 char const *quoted_name = quote (full_name);
265 if (write_protected < 0)
267 error (0, wp_errno, _("cannot remove %s"), quoted_name);
268 return RM_ERROR;
271 bool is_empty;
272 if (is_empty_p)
274 is_empty = is_empty_dir (fd_cwd, filename);
275 *is_empty_p = is_empty ? T_YES : T_NO;
277 else
278 is_empty = false;
280 /* Issue the prompt. */
281 if (dirent_type == DT_DIR
282 && mode == PA_DESCEND_INTO_DIR
283 && !is_empty)
284 fprintf (stderr,
285 (write_protected
286 ? _("%s: descend into write-protected directory %s? ")
287 : _("%s: descend into directory %s? ")),
288 program_name, quoted_name);
289 else
291 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
293 error (0, errno, _("cannot remove %s"), quoted_name);
294 return RM_ERROR;
297 fprintf (stderr,
298 (write_protected
299 /* TRANSLATORS: You may find it more convenient to
300 translate "%s: remove %s (write-protected) %s? "
301 instead. It should avoid grammatical problems
302 with the output of file_type. */
303 ? _("%s: remove write-protected %s %s? ")
304 : _("%s: remove %s %s? ")),
305 program_name, file_type (sbuf), quoted_name);
308 if (!yesno ())
309 return RM_USER_DECLINED;
311 return RM_OK;
314 /* Return true if FILENAME is a directory (and not a symlink to a directory).
315 Otherwise, including the case in which lstat fails, return false.
316 *ST is FILENAME's tstatus.
317 Do not modify errno. */
318 static inline bool
319 is_dir_lstat (int fd_cwd, char const *filename, struct stat *st)
321 int saved_errno = errno;
322 bool is_dir =
323 (cache_fstatat (fd_cwd, filename, st, AT_SYMLINK_NOFOLLOW) == 0
324 && S_ISDIR (st->st_mode));
325 errno = saved_errno;
326 return is_dir;
329 /* Return true if FILENAME is a non-directory.
330 Otherwise, including the case in which lstat fails, return false.
331 *ST is FILENAME's tstatus.
332 Do not modify errno. */
333 static inline bool
334 is_nondir_lstat (int fd_cwd, char const *filename, struct stat *st)
336 int saved_errno = errno;
337 bool is_non_dir =
338 (cache_fstatat (fd_cwd, filename, st, AT_SYMLINK_NOFOLLOW) == 0
339 && !S_ISDIR (st->st_mode));
340 errno = saved_errno;
341 return is_non_dir;
344 /* When a function like unlink, rmdir, or fstatat fails with an errno
345 value of ERRNUM, return true if the specified file system object
346 is guaranteed not to exist; otherwise, return false. */
347 static inline bool
348 nonexistent_file_errno (int errnum)
350 /* Do not include ELOOP here, since the specified file may indeed
351 exist, but be (in)accessible only via too long a symlink chain.
352 Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail
353 if the "..." part expands to a long enough sequence of "./"s,
354 even though ./foo does indeed exist.
356 Another case to consider is when a particular name is invalid for
357 a given file system. In 2011, smbfs returns EINVAL, but the next
358 revision of POSIX will require EILSEQ for that situation:
359 http://austingroupbugs.net/view.php?id=293
362 switch (errnum)
364 case EILSEQ:
365 case EINVAL:
366 case ENOENT:
367 case ENOTDIR:
368 return true;
369 default:
370 return false;
374 /* Encapsulate the test for whether the errno value, ERRNUM, is ignorable. */
375 static inline bool
376 ignorable_missing (struct rm_options const *x, int errnum)
378 return x->ignore_missing_files && nonexistent_file_errno (errnum);
381 /* Tell fts not to traverse into the hierarchy at ENT. */
382 static void
383 fts_skip_tree (FTS *fts, FTSENT *ent)
385 fts_set (fts, ent, FTS_SKIP);
386 /* Ensure that we do not process ENT a second time. */
387 ignore_value (fts_read (fts));
390 /* Upon unlink failure, or when the user declines to remove ENT, mark
391 each of its ancestor directories, so that we know not to prompt for
392 its removal. */
393 static void
394 mark_ancestor_dirs (FTSENT *ent)
396 FTSENT *p;
397 for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent)
399 if (p->fts_number)
400 break;
401 p->fts_number = 1;
405 /* Remove the file system object specified by ENT. IS_DIR specifies
406 whether it is expected to be a directory or non-directory.
407 Return RM_OK upon success, else RM_ERROR. */
408 static enum RM_status
409 excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
411 int flag = is_dir ? AT_REMOVEDIR : 0;
412 if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
414 if (x->verbose)
416 printf ((is_dir
417 ? _("removed directory: %s\n")
418 : _("removed %s\n")), quote (ent->fts_path));
420 return RM_OK;
423 /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
424 nonexistent files. When the file is indeed missing, map that to ENOENT,
425 so that rm -f ignores it, as required. Even without -f, this is useful
426 because it makes rm print the more precise diagnostic. */
427 if (errno == EROFS)
429 struct stat st;
430 if ( ! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st)
431 && errno == ENOENT))
432 errno = EROFS;
435 if (ignorable_missing (x, errno))
436 return RM_OK;
438 /* When failing to rmdir an unreadable directory, the typical
439 errno value is EISDIR, but that is not as useful to the user
440 as the errno value from the failed open (probably EPERM).
441 Use the earlier, more descriptive errno value. */
442 if (ent->fts_info == FTS_DNR)
443 errno = ent->fts_errno;
444 error (0, errno, _("cannot remove %s"), quote (ent->fts_path));
445 mark_ancestor_dirs (ent);
446 return RM_ERROR;
449 /* This function is called once for every file system object that fts
450 encounters. fts performs a depth-first traversal.
451 A directory is usually processed twice, first with fts_info == FTS_D,
452 and later, after all of its entries have been processed, with FTS_DP.
453 Return RM_ERROR upon error, RM_USER_DECLINED for a negative response
454 to an interactive prompt, and otherwise, RM_OK. */
455 static enum RM_status
456 rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
458 switch (ent->fts_info)
460 case FTS_D: /* preorder directory */
461 if (! x->recursive)
463 /* This is the first (pre-order) encounter with a directory.
464 Not recursive, so arrange to skip contents. */
465 error (0, EISDIR, _("cannot remove %s"), quote (ent->fts_path));
466 mark_ancestor_dirs (ent);
467 fts_skip_tree (fts, ent);
468 return RM_ERROR;
471 /* Perform checks that can apply only for command-line arguments. */
472 if (ent->fts_level == FTS_ROOTLEVEL)
474 if (strip_trailing_slashes (ent->fts_path))
475 ent->fts_pathlen = strlen (ent->fts_path);
477 /* If the basename of a command line argument is "." or "..",
478 diagnose it and do nothing more with that argument. */
479 if (dot_or_dotdot (last_component (ent->fts_accpath)))
481 error (0, 0, _("cannot remove directory: %s"),
482 quote (ent->fts_path));
483 fts_skip_tree (fts, ent);
484 return RM_ERROR;
487 /* If a command line argument resolves to "/" (and --preserve-root
488 is in effect -- default) diagnose and skip it. */
489 if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp))
491 ROOT_DEV_INO_WARN (ent->fts_path);
492 fts_skip_tree (fts, ent);
493 return RM_ERROR;
498 Ternary is_empty_directory;
499 enum RM_status s = prompt (fts, ent, true /*is_dir*/, x,
500 PA_DESCEND_INTO_DIR, &is_empty_directory);
502 if (s == RM_OK && is_empty_directory == T_YES)
504 /* When we know (from prompt when in interactive mode)
505 that this is an empty directory, don't prompt twice. */
506 s = excise (fts, ent, x, true);
507 fts_skip_tree (fts, ent);
510 if (s != RM_OK)
512 mark_ancestor_dirs (ent);
513 fts_skip_tree (fts, ent);
516 return s;
519 case FTS_F: /* regular file */
520 case FTS_NS: /* stat(2) failed */
521 case FTS_SL: /* symbolic link */
522 case FTS_SLNONE: /* symbolic link without target */
523 case FTS_DP: /* postorder directory */
524 case FTS_DNR: /* unreadable directory */
525 case FTS_NSOK: /* e.g., dangling symlink */
526 case FTS_DEFAULT: /* none of the above */
528 /* With --one-file-system, do not attempt to remove a mount point.
529 fts' FTS_XDEV ensures that we don't process any entries under
530 the mount point. */
531 if (ent->fts_info == FTS_DP
532 && x->one_file_system
533 && FTS_ROOTLEVEL < ent->fts_level
534 && ent->fts_statp->st_dev != fts->fts_dev)
536 mark_ancestor_dirs (ent);
537 error (0, 0, _("skipping %s, since it's on a different device"),
538 quote (ent->fts_path));
539 return RM_ERROR;
542 bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR;
543 enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR, NULL);
544 if (s != RM_OK)
545 return s;
546 return excise (fts, ent, x, is_dir);
549 case FTS_DC: /* directory that causes cycles */
550 emit_cycle_warning (ent->fts_path);
551 fts_skip_tree (fts, ent);
552 return RM_ERROR;
554 case FTS_ERR:
555 /* Various failures, from opendir to ENOMEM, to failure to "return"
556 to preceding directory, can provoke this. */
557 error (0, ent->fts_errno, _("traversal failed: %s"),
558 quote (ent->fts_path));
559 fts_skip_tree (fts, ent);
560 return RM_ERROR;
562 default:
563 error (0, 0, _("unexpected failure: fts_info=%d: %s\n"
564 "please report to %s"),
565 ent->fts_info,
566 quote (ent->fts_path),
567 PACKAGE_BUGREPORT);
568 abort ();
572 /* Remove FILEs, honoring options specified via X.
573 Return RM_OK if successful. */
574 enum RM_status
575 rm (char *const *file, struct rm_options const *x)
577 enum RM_status rm_status = RM_OK;
579 if (*file)
581 int bit_flags = (FTS_CWDFD
582 | FTS_NOSTAT
583 | FTS_PHYSICAL);
585 if (x->one_file_system)
586 bit_flags |= FTS_XDEV;
588 FTS *fts = xfts_open (file, bit_flags, NULL);
590 while (1)
592 FTSENT *ent;
594 ent = fts_read (fts);
595 if (ent == NULL)
597 if (errno != 0)
599 error (0, errno, _("fts_read failed"));
600 rm_status = RM_ERROR;
602 break;
605 enum RM_status s = rm_fts (fts, ent, x);
607 assert (VALID_STATUS (s));
608 UPDATE_STATUS (rm_status, s);
611 if (fts_close (fts) != 0)
613 error (0, errno, _("fts_close failed"));
614 rm_status = RM_ERROR;
618 return rm_status;