1/* remove.c -- core functions for removing files and directories 2 Copyright (C) 1988, 1990-1991, 1994-2010 Free Software Foundation, Inc. 3 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. 8 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. 13 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/>. */ 16 17/* Extracted from rm.c and librarified, then rewritten twice by Jim Meyering. */ 18 19#include <config.h> 20#include <stdio.h> 21#include <sys/types.h> 22#include <assert.h> 23 24#include "system.h" 25#include "error.h" 26#include "euidaccess-stat.h" 27#include "file-type.h" 28#include "hash.h" 29#include "hash-pjw.h" 30#include "obstack.h" 31#include "quote.h" 32#include "remove.h" 33#include "root-dev-ino.h" 34#include "write-any-file.h" 35#include "xfts.h" 36#include "yesno.h" 37 38enum Ternary 39 { 40 T_UNKNOWN = 2, 41 T_NO, 42 T_YES 43 }; 44typedef enum Ternary Ternary; 45 46/* The prompt function may be called twice for a given directory. 47 The first time, we ask whether to descend into it, and the 48 second time, we ask whether to remove it. */ 49enum Prompt_action 50 { 51 PA_DESCEND_INTO_DIR = 2, 52 PA_REMOVE_DIR 53 }; 54 55/* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN 56 otherwise. */ 57#if ! HAVE_STRUCT_DIRENT_D_TYPE 58/* Any int values will do here, so long as they're distinct. 59 Undef any existing macros out of the way. */ 60# undef DT_UNKNOWN 61# undef DT_DIR 62# undef DT_LNK 63# define DT_UNKNOWN 0 64# define DT_DIR 1 65# define DT_LNK 2 66#endif 67 68/* Like fstatat, but cache the result. If ST->st_size is -1, the 69 status has not been gotten yet. If less than -1, fstatat failed 70 with errno == ST->st_ino. Otherwise, the status has already 71 been gotten, so return 0. */ 72static int 73cache_fstatat (int fd, char const *file, struct stat *st, int flag) 74{ 75 if (st->st_size == -1 && fstatat (fd, file, st, flag) != 0) 76 { 77 st->st_size = -2; 78 st->st_ino = errno; 79 } 80 if (0 <= st->st_size) 81 return 0; 82 errno = (int) st->st_ino; 83 return -1; 84} 85 86/* Initialize a fstatat cache *ST. Return ST for convenience. */ 87static inline struct stat * 88cache_stat_init (struct stat *st) 89{ 90 st->st_size = -1; 91 return st; 92} 93 94/* Return true if *ST has been statted. */ 95static inline bool 96cache_statted (struct stat *st) 97{ 98 return (st->st_size != -1); 99} 100 101/* Return true if *ST has been statted successfully. */ 102static inline bool 103cache_stat_ok (struct stat *st) 104{ 105 return (0 <= st->st_size); 106} 107 108/* Return 1 if FILE is an unwritable non-symlink, 109 0 if it is writable or some other type of file, 110 -1 and set errno if there is some problem in determining the answer. 111 Use FULL_NAME only if necessary. 112 Set *BUF to the file status. 113 This is to avoid calling euidaccess when FILE is a symlink. */ 114static int 115write_protected_non_symlink (int fd_cwd, 116 char const *file, 117 char const *full_name, 118 struct stat *buf) 119{ 120 if (can_write_any_file ()) 121 return 0; 122 if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0) 123 return -1; 124 if (S_ISLNK (buf->st_mode)) 125 return 0; 126 /* Here, we know FILE is not a symbolic link. */ 127 128 /* In order to be reentrant -- i.e., to avoid changing the working 129 directory, and at the same time to be able to deal with alternate 130 access control mechanisms (ACLs, xattr-style attributes) and 131 arbitrarily deep trees -- we need a function like eaccessat, i.e., 132 like Solaris' eaccess, but fd-relative, in the spirit of openat. */ 133 134 /* In the absence of a native eaccessat function, here are some of 135 the implementation choices [#4 and #5 were suggested by Paul Eggert]: 136 1) call openat with O_WRONLY|O_NOCTTY 137 Disadvantage: may create the file and doesn't work for directory, 138 may mistakenly report `unwritable' for EROFS or ACLs even though 139 perm bits say the file is writable. 140 141 2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd) 142 Disadvantage: changes working directory (not reentrant) and can't 143 work if save_cwd fails. 144 145 3) if (euidaccess (full_name, W_OK) == 0) 146 Disadvantage: doesn't work if full_name is too long. 147 Inefficient for very deep trees (O(Depth^2)). 148 149 4) If the full pathname is sufficiently short (say, less than 150 PATH_MAX or 8192 bytes, whichever is shorter): 151 use method (3) (i.e., euidaccess (full_name, W_OK)); 152 Otherwise: vfork, fchdir in the child, run euidaccess in the 153 child, then the child exits with a status that tells the parent 154 whether euidaccess succeeded. 155 156 This avoids the O(N**2) algorithm of method (3), and it also avoids 157 the failure-due-to-too-long-file-names of method (3), but it's fast 158 in the normal shallow case. It also avoids the lack-of-reentrancy 159 and the save_cwd problems. 160 Disadvantage; it uses a process slot for very-long file names, 161 and would be very slow for hierarchies with many such files. 162 163 5) If the full file name is sufficiently short (say, less than 164 PATH_MAX or 8192 bytes, whichever is shorter): 165 use method (3) (i.e., euidaccess (full_name, W_OK)); 166 Otherwise: look just at the file bits. Perhaps issue a warning 167 the first time this occurs. 168 169 This is like (4), except for the "Otherwise" case where it isn't as 170 "perfect" as (4) but is considerably faster. It conforms to current 171 POSIX, and is uniformly better than what Solaris and FreeBSD do (they 172 mess up with long file names). */ 173 174 { 175 /* This implements #1: on decent systems, either faccessat is 176 native or /proc/self/fd allows us to skip a chdir. */ 177 if (!openat_needs_fchdir () 178 && faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0) 179 return 0; 180 181 { 182 /* This implements #5: */ 183 size_t file_name_len = strlen (full_name); 184 185 if (MIN (PATH_MAX, 8192) <= file_name_len) 186 return ! euidaccess_stat (buf, W_OK); 187 if (euidaccess (full_name, W_OK) == 0) 188 return 0; 189 if (errno == EACCES) 190 { 191 errno = 0; 192 return 1; 193 } 194 } 195 196 /* Perhaps some other process has removed the file, or perhaps this 197 is a buggy NFS client. */ 198 return -1; 199 } 200} 201 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. 207 208 IS_DIR is true if ENT designates a directory, false otherwise. 209 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. */ 215static enum RM_status 216prompt (FTS const *fts, FTSENT const *ent, bool is_dir, 217 struct rm_options const *x, enum Prompt_action mode, 218 Ternary *is_empty_p) 219{ 220 int wp_errno; 221 int fd_cwd = fts->fts_cwd_fd; 222 char const *full_name = ent->fts_path; 223 char const *filename = ent->fts_accpath; 224 struct stat st; 225 struct stat *sbuf = &st; 226 int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN; 227 int write_protected = 0; 228 if (is_empty_p) 229 *is_empty_p = T_UNKNOWN; 230 231 232 cache_stat_init (sbuf); 233 234 /* When nonzero, this indicates that we failed to remove a child entry, 235 either because the user declined an interactive prompt, or due to 236 some other failure, like permissions. */ 237 if (ent->fts_number) 238 return RM_USER_DECLINED; 239 240 if (x->interactive == RMI_NEVER) 241 return RM_OK; 242 243 wp_errno = 0; 244 if (!x->ignore_missing_files 245 && ((x->interactive == RMI_ALWAYS) || x->stdin_tty) 246 && dirent_type != DT_LNK) 247 { 248 write_protected = write_protected_non_symlink (fd_cwd, filename, 249 full_name, sbuf); 250 wp_errno = errno; 251 } 252 253 if (write_protected || errno || x->interactive == RMI_ALWAYS) 254 { 255 if (0 <= write_protected && dirent_type == DT_UNKNOWN) 256 { 257 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0) 258 { 259 if (S_ISLNK (sbuf->st_mode)) 260 dirent_type = DT_LNK; 261 else if (S_ISDIR (sbuf->st_mode)) 262 dirent_type = DT_DIR; 263 /* Otherwise it doesn't matter, so leave it DT_UNKNOWN. */ 264 } 265 else 266 { 267 /* This happens, e.g., with `rm '''. */ 268 write_protected = -1; 269 wp_errno = errno; 270 } 271 } 272 273 if (0 <= write_protected) 274 switch (dirent_type) 275 { 276 case DT_LNK: 277 /* Using permissions doesn't make sense for symlinks. */ 278 if (x->interactive != RMI_ALWAYS) 279 return RM_OK; 280 break; 281 282 case DT_DIR: 283 if (!x->recursive) 284 { 285 write_protected = -1; 286 wp_errno = EISDIR; 287 } 288 break; 289 } 290 { 291 char const *quoted_name = quote (full_name); 292 bool is_empty; 293 294 if (write_protected < 0) 295 { 296 error (0, wp_errno, _("cannot remove %s"), quoted_name); 297 return RM_ERROR; 298 } 299 300 301 if (is_empty_p) 302 { 303 is_empty = is_empty_dir (fd_cwd, filename); 304 *is_empty_p = is_empty ? T_YES : T_NO; 305 } 306 else 307 is_empty = false; 308 309 /* Issue the prompt. */ 310 if (dirent_type == DT_DIR 311 && mode == PA_DESCEND_INTO_DIR 312 && !is_empty) 313 fprintf (stderr, 314 (write_protected 315 ? _("%s: descend into write-protected directory %s? ") 316 : _("%s: descend into directory %s? ")), 317 program_name, quoted_name); 318 else 319 { 320 if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0) 321 { 322 error (0, errno, _("cannot remove %s"), quoted_name); 323 return RM_ERROR; 324 } 325 326 fprintf (stderr, 327 (write_protected 328 /* TRANSLATORS: You may find it more convenient to 329 translate "%s: remove %s (write-protected) %s? " 330 instead. It should avoid grammatical problems 331 with the output of file_type. */ 332 ? _("%s: remove write-protected %s %s? ") 333 : _("%s: remove %s %s? ")), 334 program_name, file_type (sbuf), quoted_name); 335 } 336 } 337 338 if (!yesno ()) 339 return RM_USER_DECLINED; 340 } 341 return RM_OK; 342} 343 344/* Return true if FILENAME is a directory (and not a symlink to a directory). 345 Otherwise, including the case in which lstat fails, return false. 346 *ST is FILENAME's tstatus. 347 Do not modify errno. */ 348static inline bool 349is_dir_lstat (int fd_cwd, char const *filename, struct stat *st) 350{ 351 int saved_errno = errno; 352 bool is_dir = 353 (cache_fstatat (fd_cwd, filename, st, AT_SYMLINK_NOFOLLOW) == 0 354 && S_ISDIR (st->st_mode)); 355 errno = saved_errno; 356 return is_dir; 357} 358 359/* Return true if FILENAME is a non-directory. 360 Otherwise, including the case in which lstat fails, return false. 361 *ST is FILENAME's tstatus. 362 Do not modify errno. */ 363static inline bool 364is_nondir_lstat (int fd_cwd, char const *filename, struct stat *st) 365{ 366 int saved_errno = errno; 367 bool is_non_dir = 368 (cache_fstatat (fd_cwd, filename, st, AT_SYMLINK_NOFOLLOW) == 0 369 && !S_ISDIR (st->st_mode)); 370 errno = saved_errno; 371 return is_non_dir; 372} 373 374/* When a function like unlink, rmdir, or fstatat fails with an errno 375 value of ERRNUM, return true if the specified file system object 376 is guaranteed not to exist; otherwise, return false. */ 377static inline bool 378nonexistent_file_errno (int errnum) 379{ 380 /* Do not include ELOOP here, since the specified file may indeed 381 exist, but be (in)accessible only via too long a symlink chain. 382 Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail 383 if the "..." part expands to a long enough sequence of "./"s, 384 even though ./foo does indeed exist. */ 385 386 switch (errnum) 387 { 388 case ENOENT: 389 case ENOTDIR: 390 return true; 391 default: 392 return false; 393 } 394} 395 396/* Encapsulate the test for whether the errno value, ERRNUM, is ignorable. */ 397static inline bool 398ignorable_missing (struct rm_options const *x, int errnum) 399{ 400 return x->ignore_missing_files && nonexistent_file_errno (errnum); 401} 402 403/* Tell fts not to traverse into the hierarchy at ENT. */ 404static void 405fts_skip_tree (FTS *fts, FTSENT *ent) 406{ 407 fts_set (fts, ent, FTS_SKIP); 408 /* Ensure that we do not process ENT a second time. */ 409 ent = fts_read (fts); 410} 411 412/* Upon unlink failure, or when the user declines to remove ENT, mark 413 each of its ancestor directories, so that we know not to prompt for 414 its removal. */ 415static void 416mark_ancestor_dirs (FTSENT *ent) 417{ 418 FTSENT *p; 419 for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent) 420 { 421 if (p->fts_number) 422 break; 423 p->fts_number = 1; 424 } 425} 426 427/* Remove the file system object specified by ENT. IS_DIR specifies 428 whether it is expected to be a directory or non-directory. 429 Return RM_OK upon success, else RM_ERROR. */ 430static enum RM_status 431excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir) 432{ 433 int flag = is_dir ? AT_REMOVEDIR : 0; 434 if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0) 435 { 436 if (x->verbose) 437 { 438 printf ((is_dir 439 ? _("removed directory: %s\n") 440 : _("removed %s\n")), quote (ent->fts_path)); 441 } 442 return RM_OK; 443 } 444 445 /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for 446 nonexistent files. When the file is indeed missing, map that to ENOENT, 447 so that rm -f ignores it, as required. Even without -f, this is useful 448 because it makes rm print the more precise diagnostic. */ 449 if (errno == EROFS) 450 { 451 struct stat st; 452 if ( ! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st) 453 && errno == ENOENT)) 454 errno = EROFS; 455 } 456 457 if (ignorable_missing (x, errno)) 458 return RM_OK; 459 460 /* When failing to rmdir an unreadable directory, the typical 461 errno value is EISDIR, but that is not as useful to the user 462 as the errno value from the failed open (probably EPERM). 463 Use the earlier, more descriptive errno value. */ 464 if (ent->fts_info == FTS_DNR) 465 errno = ent->fts_errno; 466 error (0, errno, _("cannot remove %s"), quote (ent->fts_path)); 467 mark_ancestor_dirs (ent); 468 return RM_ERROR; 469} 470 471/* This function is called once for every file system object that fts 472 encounters. fts performs a depth-first traversal. 473 A directory is usually processed twice, first with fts_info == FTS_D, 474 and later, after all of its entries have been processed, with FTS_DP. 475 Return RM_ERROR upon error, RM_USER_DECLINED for a negative response 476 to an interactive prompt, and otherwise, RM_OK. */ 477static enum RM_status 478rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x) 479{ 480 switch (ent->fts_info) 481 { 482 case FTS_D: /* preorder directory */ 483 if (! x->recursive) 484 { 485 /* This is the first (pre-order) encounter with a directory. 486 Not recursive, so arrange to skip contents. */ 487 error (0, EISDIR, _("cannot remove %s"), quote (ent->fts_path)); 488 mark_ancestor_dirs (ent); 489 fts_skip_tree (fts, ent); 490 return RM_ERROR; 491 } 492 493 /* Perform checks that can apply only for command-line arguments. */ 494 if (ent->fts_level == FTS_ROOTLEVEL) 495 { 496 if (strip_trailing_slashes (ent->fts_path)) 497 ent->fts_pathlen = strlen (ent->fts_path); 498 499 /* If the basename of a command line argument is "." or "..", 500 diagnose it and do nothing more with that argument. */ 501 if (dot_or_dotdot (last_component (ent->fts_accpath))) 502 { 503 error (0, 0, _("cannot remove directory: %s"), 504 quote (ent->fts_path)); 505 fts_skip_tree (fts, ent); 506 return RM_ERROR; 507 } 508 509 /* If a command line argument resolves to "/" (and --preserve-root 510 is in effect -- default) diagnose and skip it. */ 511 if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp)) 512 { 513 ROOT_DEV_INO_WARN (ent->fts_path); 514 fts_skip_tree (fts, ent); 515 return RM_ERROR; 516 } 517 } 518 519 { 520 Ternary is_empty_directory; 521 enum RM_status s = prompt (fts, ent, true /*is_dir*/, x, 522 PA_DESCEND_INTO_DIR, &is_empty_directory); 523 524 if (s == RM_OK && is_empty_directory == T_YES) 525 { 526 /* When we know (from prompt when in interactive mode) 527 that this is an empty directory, don't prompt twice. */ 528 s = excise (fts, ent, x, true); 529 fts_skip_tree (fts, ent); 530 } 531 532 if (s != RM_OK) 533 { 534 mark_ancestor_dirs (ent); 535 fts_skip_tree (fts, ent); 536 } 537 538 return s; 539 } 540 541 case FTS_F: /* regular file */ 542 case FTS_NS: /* stat(2) failed */ 543 case FTS_SL: /* symbolic link */ 544 case FTS_SLNONE: /* symbolic link without target */ 545 case FTS_DP: /* postorder directory */ 546 case FTS_DNR: /* unreadable directory */ 547 case FTS_NSOK: /* e.g., dangling symlink */ 548 case FTS_DEFAULT: /* none of the above */ 549 { 550 /* With --one-file-system, do not attempt to remove a mount point. 551 fts' FTS_XDEV ensures that we don't process any entries under 552 the mount point. */ 553 if (ent->fts_info == FTS_DP 554 && x->one_file_system 555 && FTS_ROOTLEVEL < ent->fts_level 556 && ent->fts_statp->st_dev != fts->fts_dev) 557 { 558 mark_ancestor_dirs (ent); 559 error (0, 0, _("skipping %s, since it's on a different device"), 560 quote (ent->fts_path)); 561 return RM_ERROR; 562 } 563 564 { 565 bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR; 566 enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR, NULL); 567 if (s != RM_OK) 568 return s; 569 return excise (fts, ent, x, is_dir); 570 } 571 } 572 573 case FTS_DC: /* directory that causes cycles */ 574 emit_cycle_warning (ent->fts_path); 575 fts_skip_tree (fts, ent); 576 return RM_ERROR; 577 578 case FTS_ERR: 579 /* Various failures, from opendir to ENOMEM, to failure to "return" 580 to preceding directory, can provoke this. */ 581 error (0, ent->fts_errno, _("traversal failed: %s"), 582 quote (ent->fts_path)); 583 fts_skip_tree (fts, ent); 584 return RM_ERROR; 585 586 default: 587 error (0, 0, _("unexpected failure: fts_info=%d: %s\n" 588 "please report to %s"), 589 ent->fts_info, 590 quote (ent->fts_path), 591 PACKAGE_BUGREPORT); 592 abort (); 593 } 594} 595 596/* Remove FILEs, honoring options specified via X. 597 Return RM_OK if successful. */ 598enum RM_status 599rm (char *const *file, struct rm_options const *x) 600{ 601 enum RM_status rm_status = RM_OK; 602 603 if (*file) 604 { 605 int bit_flags = (FTS_CWDFD 606 | FTS_NOSTAT 607 | FTS_PHYSICAL); 608 FTS *fts; 609 610 if (x->one_file_system) 611 bit_flags |= FTS_XDEV; 612 613 fts = xfts_open (file, bit_flags, NULL); 614 615 while (1) 616 { 617 FTSENT *ent; 618 enum RM_status s; 619 620 ent = fts_read (fts); 621 if (ent == NULL) 622 { 623 if (errno != 0) 624 { 625 error (0, errno, _("fts_read failed")); 626 rm_status = RM_ERROR; 627 } 628 break; 629 } 630 631 s = rm_fts (fts, ent, x); 632 633 assert (VALID_STATUS (s)); 634 UPDATE_STATUS (rm_status, s); 635 } 636 637 if (fts_close (fts) != 0) 638 { 639 error (0, errno, _("fts_close failed")); 640 rm_status = RM_ERROR; 641 } 642 } 643 644 return rm_status; 645} 646