ptx: fix an invalid heap reference with short --width
[coreutils.git] / src / remove.c
blob7309f03b0c06e4e7f80582394aa6077a11a167a0
1 /* remove.c -- core functions for removing files and directories
2 Copyright (C) 1988-2016 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 "remove.h"
29 #include "root-dev-ino.h"
30 #include "write-any-file.h"
31 #include "xfts.h"
32 #include "yesno.h"
34 enum Ternary
36 T_UNKNOWN = 2,
37 T_NO,
38 T_YES
40 typedef enum Ternary Ternary;
42 /* The prompt function may be called twice for a given directory.
43 The first time, we ask whether to descend into it, and the
44 second time, we ask whether to remove it. */
45 enum Prompt_action
47 PA_DESCEND_INTO_DIR = 2,
48 PA_REMOVE_DIR
51 /* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN
52 otherwise. */
53 #if ! HAVE_STRUCT_DIRENT_D_TYPE
54 /* Any int values will do here, so long as they're distinct.
55 Undef any existing macros out of the way. */
56 # undef DT_UNKNOWN
57 # undef DT_DIR
58 # undef DT_LNK
59 # define DT_UNKNOWN 0
60 # define DT_DIR 1
61 # define DT_LNK 2
62 #endif
64 /* Like fstatat, but cache the result. If ST->st_size is -1, the
65 status has not been gotten yet. If less than -1, fstatat failed
66 with errno == ST->st_ino. Otherwise, the status has already
67 been gotten, so return 0. */
68 static int
69 cache_fstatat (int fd, char const *file, struct stat *st, int flag)
71 if (st->st_size == -1 && fstatat (fd, file, st, flag) != 0)
73 st->st_size = -2;
74 st->st_ino = errno;
76 if (0 <= st->st_size)
77 return 0;
78 errno = (int) st->st_ino;
79 return -1;
82 /* Initialize a fstatat cache *ST. Return ST for convenience. */
83 static inline struct stat *
84 cache_stat_init (struct stat *st)
86 st->st_size = -1;
87 return st;
90 /* Return 1 if FILE is an unwritable non-symlink,
91 0 if it is writable or some other type of file,
92 -1 and set errno if there is some problem in determining the answer.
93 Set *BUF to the file status. */
94 static int
95 write_protected_non_symlink (int fd_cwd,
96 char const *file,
97 struct stat *buf)
99 if (can_write_any_file ())
100 return 0;
101 if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
102 return -1;
103 if (S_ISLNK (buf->st_mode))
104 return 0;
105 /* Here, we know FILE is not a symbolic link. */
107 /* In order to be reentrant -- i.e., to avoid changing the working
108 directory, and at the same time to be able to deal with alternate
109 access control mechanisms (ACLs, xattr-style attributes) and
110 arbitrarily deep trees -- we need a function like eaccessat, i.e.,
111 like Solaris' eaccess, but fd-relative, in the spirit of openat. */
113 /* In the absence of a native eaccessat function, here are some of
114 the implementation choices [#4 and #5 were suggested by Paul Eggert]:
115 1) call openat with O_WRONLY|O_NOCTTY
116 Disadvantage: may create the file and doesn't work for directory,
117 may mistakenly report 'unwritable' for EROFS or ACLs even though
118 perm bits say the file is writable.
120 2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
121 Disadvantage: changes working directory (not reentrant) and can't
122 work if save_cwd fails.
124 3) if (euidaccess (full_name, W_OK) == 0)
125 Disadvantage: doesn't work if full_name is too long.
126 Inefficient for very deep trees (O(Depth^2)).
128 4) If the full pathname is sufficiently short (say, less than
129 PATH_MAX or 8192 bytes, whichever is shorter):
130 use method (3) (i.e., euidaccess (full_name, W_OK));
131 Otherwise: vfork, fchdir in the child, run euidaccess in the
132 child, then the child exits with a status that tells the parent
133 whether euidaccess succeeded.
135 This avoids the O(N**2) algorithm of method (3), and it also avoids
136 the failure-due-to-too-long-file-names of method (3), but it's fast
137 in the normal shallow case. It also avoids the lack-of-reentrancy
138 and the save_cwd problems.
139 Disadvantage; it uses a process slot for very-long file names,
140 and would be very slow for hierarchies with many such files.
142 5) If the full file name is sufficiently short (say, less than
143 PATH_MAX or 8192 bytes, whichever is shorter):
144 use method (3) (i.e., euidaccess (full_name, W_OK));
145 Otherwise: look just at the file bits. Perhaps issue a warning
146 the first time this occurs.
148 This is like (4), except for the "Otherwise" case where it isn't as
149 "perfect" as (4) but is considerably faster. It conforms to current
150 POSIX, and is uniformly better than what Solaris and FreeBSD do (they
151 mess up with long file names). */
154 if (faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0)
155 return 0;
157 return errno == EACCES ? 1 : -1;
161 /* Prompt whether to remove FILENAME (ent->, if required via a combination of
162 the options specified by X and/or file attributes. If the file may
163 be removed, return RM_OK. If the user declines to remove the file,
164 return RM_USER_DECLINED. If not ignoring missing files and we
165 cannot lstat FILENAME, then return RM_ERROR.
167 IS_DIR is true if ENT designates a directory, false otherwise.
169 Depending on MODE, ask whether to 'descend into' or to 'remove' the
170 directory FILENAME. MODE is ignored when FILENAME is not a directory.
171 Set *IS_EMPTY_P to T_YES if FILENAME is an empty directory, and it is
172 appropriate to try to remove it with rmdir (e.g. recursive mode).
173 Don't even try to set *IS_EMPTY_P when MODE == PA_REMOVE_DIR. */
174 static enum RM_status
175 prompt (FTS const *fts, FTSENT const *ent, bool is_dir,
176 struct rm_options const *x, enum Prompt_action mode,
177 Ternary *is_empty_p)
179 int fd_cwd = fts->fts_cwd_fd;
180 char const *full_name = ent->fts_path;
181 char const *filename = ent->fts_accpath;
182 if (is_empty_p)
183 *is_empty_p = T_UNKNOWN;
185 struct stat st;
186 struct stat *sbuf = &st;
187 cache_stat_init (sbuf);
189 int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN;
190 int write_protected = 0;
192 bool is_empty = false;
193 if (is_empty_p)
195 is_empty = is_empty_dir (fd_cwd, filename);
196 *is_empty_p = is_empty ? T_YES : T_NO;
199 /* When nonzero, this indicates that we failed to remove a child entry,
200 either because the user declined an interactive prompt, or due to
201 some other failure, like permissions. */
202 if (ent->fts_number)
203 return RM_USER_DECLINED;
205 if (x->interactive == RMI_NEVER)
206 return RM_OK;
208 int wp_errno = 0;
209 if (!x->ignore_missing_files
210 && ((x->interactive == RMI_ALWAYS) || x->stdin_tty)
211 && dirent_type != DT_LNK)
213 write_protected = write_protected_non_symlink (fd_cwd, filename, sbuf);
214 wp_errno = errno;
217 if (write_protected || x->interactive == RMI_ALWAYS)
219 if (0 <= write_protected && dirent_type == DT_UNKNOWN)
221 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0)
223 if (S_ISLNK (sbuf->st_mode))
224 dirent_type = DT_LNK;
225 else if (S_ISDIR (sbuf->st_mode))
226 dirent_type = DT_DIR;
227 /* Otherwise it doesn't matter, so leave it DT_UNKNOWN. */
229 else
231 /* This happens, e.g., with 'rm '''. */
232 write_protected = -1;
233 wp_errno = errno;
237 if (0 <= write_protected)
238 switch (dirent_type)
240 case DT_LNK:
241 /* Using permissions doesn't make sense for symlinks. */
242 if (x->interactive != RMI_ALWAYS)
243 return RM_OK;
244 break;
246 case DT_DIR:
247 /* Unless we're either deleting directories or deleting
248 recursively, we want to raise an EISDIR error rather than
249 prompting the user */
250 if ( ! (x->recursive || (x->remove_empty_directories && is_empty)))
252 write_protected = -1;
253 wp_errno = EISDIR;
255 break;
258 char const *quoted_name = quoteaf (full_name);
260 if (write_protected < 0)
262 error (0, wp_errno, _("cannot remove %s"), quoted_name);
263 return RM_ERROR;
266 /* Issue the prompt. */
267 if (dirent_type == DT_DIR
268 && mode == PA_DESCEND_INTO_DIR
269 && !is_empty)
270 fprintf (stderr,
271 (write_protected
272 ? _("%s: descend into write-protected directory %s? ")
273 : _("%s: descend into directory %s? ")),
274 program_name, quoted_name);
275 else
277 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
279 error (0, errno, _("cannot remove %s"), quoted_name);
280 return RM_ERROR;
283 fprintf (stderr,
284 (write_protected
285 /* TRANSLATORS: In the next two strings the second %s is
286 replaced by the type of the file. To avoid grammatical
287 problems, it may be more convenient to translate these
288 strings instead as: "%1$s: %3$s is write-protected and
289 is of type '%2$s' -- remove it? ". */
290 ? _("%s: remove write-protected %s %s? ")
291 : _("%s: remove %s %s? ")),
292 program_name, file_type (sbuf), quoted_name);
295 if (!yesno ())
296 return RM_USER_DECLINED;
298 return RM_OK;
301 /* When a function like unlink, rmdir, or fstatat fails with an errno
302 value of ERRNUM, return true if the specified file system object
303 is guaranteed not to exist; otherwise, return false. */
304 static inline bool
305 nonexistent_file_errno (int errnum)
307 /* Do not include ELOOP here, since the specified file may indeed
308 exist, but be (in)accessible only via too long a symlink chain.
309 Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail
310 if the "..." part expands to a long enough sequence of "./"s,
311 even though ./foo does indeed exist.
313 Another case to consider is when a particular name is invalid for
314 a given file system. In 2011, smbfs returns EINVAL, but the next
315 revision of POSIX will require EILSEQ for that situation:
316 http://austingroupbugs.net/view.php?id=293
319 switch (errnum)
321 case EILSEQ:
322 case EINVAL:
323 case ENOENT:
324 case ENOTDIR:
325 return true;
326 default:
327 return false;
331 /* Encapsulate the test for whether the errno value, ERRNUM, is ignorable. */
332 static inline bool
333 ignorable_missing (struct rm_options const *x, int errnum)
335 return x->ignore_missing_files && nonexistent_file_errno (errnum);
338 /* Tell fts not to traverse into the hierarchy at ENT. */
339 static void
340 fts_skip_tree (FTS *fts, FTSENT *ent)
342 fts_set (fts, ent, FTS_SKIP);
343 /* Ensure that we do not process ENT a second time. */
344 ignore_value (fts_read (fts));
347 /* Upon unlink failure, or when the user declines to remove ENT, mark
348 each of its ancestor directories, so that we know not to prompt for
349 its removal. */
350 static void
351 mark_ancestor_dirs (FTSENT *ent)
353 FTSENT *p;
354 for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent)
356 if (p->fts_number)
357 break;
358 p->fts_number = 1;
362 /* Remove the file system object specified by ENT. IS_DIR specifies
363 whether it is expected to be a directory or non-directory.
364 Return RM_OK upon success, else RM_ERROR. */
365 static enum RM_status
366 excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
368 int flag = is_dir ? AT_REMOVEDIR : 0;
369 if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
371 if (x->verbose)
373 printf ((is_dir
374 ? _("removed directory %s\n")
375 : _("removed %s\n")), quoteaf (ent->fts_path));
377 return RM_OK;
380 /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
381 nonexistent files. When the file is indeed missing, map that to ENOENT,
382 so that rm -f ignores it, as required. Even without -f, this is useful
383 because it makes rm print the more precise diagnostic. */
384 if (errno == EROFS)
386 struct stat st;
387 if ( ! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st)
388 && errno == ENOENT))
389 errno = EROFS;
392 if (ignorable_missing (x, errno))
393 return RM_OK;
395 /* When failing to rmdir an unreadable directory, we see errno values
396 like EISDIR or ENOTDIR (or, on Solaris 10, EEXIST), but they would be
397 meaningless in a diagnostic. When that happens and the errno value
398 from the failed open is EPERM or EACCES, use the earlier, more
399 descriptive errno value. */
400 if (ent->fts_info == FTS_DNR
401 && (errno == ENOTEMPTY || errno == EISDIR || errno == ENOTDIR
402 || errno == EEXIST)
403 && (ent->fts_errno == EPERM || ent->fts_errno == EACCES))
404 errno = ent->fts_errno;
405 error (0, errno, _("cannot remove %s"), quoteaf (ent->fts_path));
406 mark_ancestor_dirs (ent);
407 return RM_ERROR;
410 /* This function is called once for every file system object that fts
411 encounters. fts performs a depth-first traversal.
412 A directory is usually processed twice, first with fts_info == FTS_D,
413 and later, after all of its entries have been processed, with FTS_DP.
414 Return RM_ERROR upon error, RM_USER_DECLINED for a negative response
415 to an interactive prompt, and otherwise, RM_OK. */
416 static enum RM_status
417 rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
419 switch (ent->fts_info)
421 case FTS_D: /* preorder directory */
422 if (! x->recursive
423 && !(x->remove_empty_directories
424 && is_empty_dir (fts->fts_cwd_fd, ent->fts_accpath)))
426 /* This is the first (pre-order) encounter with a directory
427 that we cannot delete.
428 Not recursive, and it's not an empty directory (if we're removing
429 them) so arrange to skip contents. */
430 int err = x->remove_empty_directories ? ENOTEMPTY : EISDIR;
431 error (0, err, _("cannot remove %s"), quoteaf (ent->fts_path));
432 mark_ancestor_dirs (ent);
433 fts_skip_tree (fts, ent);
434 return RM_ERROR;
437 /* Perform checks that can apply only for command-line arguments. */
438 if (ent->fts_level == FTS_ROOTLEVEL)
440 /* POSIX says:
441 If the basename of a command line argument is "." or "..",
442 diagnose it and do nothing more with that argument. */
443 if (dot_or_dotdot (last_component (ent->fts_accpath)))
445 error (0, 0,
446 _("refusing to remove %s or %s directory: skipping %s"),
447 quoteaf_n (0, "."), quoteaf_n (1, ".."),
448 quoteaf_n (2, ent->fts_path));
449 fts_skip_tree (fts, ent);
450 return RM_ERROR;
453 /* POSIX also says:
454 If a command line argument resolves to "/" (and --preserve-root
455 is in effect -- default) diagnose and skip it. */
456 if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp))
458 ROOT_DEV_INO_WARN (ent->fts_path);
459 fts_skip_tree (fts, ent);
460 return RM_ERROR;
465 Ternary is_empty_directory;
466 enum RM_status s = prompt (fts, ent, true /*is_dir*/, x,
467 PA_DESCEND_INTO_DIR, &is_empty_directory);
469 if (s == RM_OK && is_empty_directory == T_YES)
471 /* When we know (from prompt when in interactive mode)
472 that this is an empty directory, don't prompt twice. */
473 s = excise (fts, ent, x, true);
474 fts_skip_tree (fts, ent);
477 if (s != RM_OK)
479 mark_ancestor_dirs (ent);
480 fts_skip_tree (fts, ent);
483 return s;
486 case FTS_F: /* regular file */
487 case FTS_NS: /* stat(2) failed */
488 case FTS_SL: /* symbolic link */
489 case FTS_SLNONE: /* symbolic link without target */
490 case FTS_DP: /* postorder directory */
491 case FTS_DNR: /* unreadable directory */
492 case FTS_NSOK: /* e.g., dangling symlink */
493 case FTS_DEFAULT: /* none of the above */
495 /* With --one-file-system, do not attempt to remove a mount point.
496 fts' FTS_XDEV ensures that we don't process any entries under
497 the mount point. */
498 if (ent->fts_info == FTS_DP
499 && x->one_file_system
500 && FTS_ROOTLEVEL < ent->fts_level
501 && ent->fts_statp->st_dev != fts->fts_dev)
503 mark_ancestor_dirs (ent);
504 error (0, 0, _("skipping %s, since it's on a different device"),
505 quoteaf (ent->fts_path));
506 return RM_ERROR;
509 bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR;
510 enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR, NULL);
511 if (s != RM_OK)
512 return s;
513 return excise (fts, ent, x, is_dir);
516 case FTS_DC: /* directory that causes cycles */
517 emit_cycle_warning (ent->fts_path);
518 fts_skip_tree (fts, ent);
519 return RM_ERROR;
521 case FTS_ERR:
522 /* Various failures, from opendir to ENOMEM, to failure to "return"
523 to preceding directory, can provoke this. */
524 error (0, ent->fts_errno, _("traversal failed: %s"),
525 quotef (ent->fts_path));
526 fts_skip_tree (fts, ent);
527 return RM_ERROR;
529 default:
530 error (0, 0, _("unexpected failure: fts_info=%d: %s\n"
531 "please report to %s"),
532 ent->fts_info,
533 quotef (ent->fts_path),
534 PACKAGE_BUGREPORT);
535 abort ();
539 /* Remove FILEs, honoring options specified via X.
540 Return RM_OK if successful. */
541 enum RM_status
542 rm (char *const *file, struct rm_options const *x)
544 enum RM_status rm_status = RM_OK;
546 if (*file)
548 int bit_flags = (FTS_CWDFD
549 | FTS_NOSTAT
550 | FTS_PHYSICAL);
552 if (x->one_file_system)
553 bit_flags |= FTS_XDEV;
555 FTS *fts = xfts_open (file, bit_flags, NULL);
557 while (1)
559 FTSENT *ent;
561 ent = fts_read (fts);
562 if (ent == NULL)
564 if (errno != 0)
566 error (0, errno, _("fts_read failed"));
567 rm_status = RM_ERROR;
569 break;
572 enum RM_status s = rm_fts (fts, ent, x);
574 assert (VALID_STATUS (s));
575 UPDATE_STATUS (rm_status, s);
578 if (fts_close (fts) != 0)
580 error (0, errno, _("fts_close failed"));
581 rm_status = RM_ERROR;
585 return rm_status;