1 /* remove.c -- core functions for removing files and directories
2 Copyright (C) 1988-2024 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. */
21 #include <sys/types.h>
25 #include "file-type.h"
26 #include "filenamecat.h"
27 #include "ignore-value.h"
29 #include "root-dev-ino.h"
30 #include "stat-time.h"
31 #include "write-any-file.h"
35 /* The prompt function may be called twice for a given directory.
36 The first time, we ask whether to descend into it, and the
37 second time, we ask whether to remove it. */
40 PA_DESCEND_INTO_DIR
= 2,
44 /* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN
46 #if ! HAVE_STRUCT_DIRENT_D_TYPE
47 /* Any int values will do here, so long as they're distinct.
48 Undef any existing macros out of the way. */
57 /* Like fstatat, but cache on POSIX-compatible systems. */
59 cache_fstatat (int fd
, char const *file
, struct stat
*st
, int flag
)
61 #if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
62 /* If ST->st_atim.tv_nsec is -1, the status has not been gotten yet.
63 If less than -1, fstatat failed with errno == ST->st_ino.
64 Otherwise, the status has already been gotten, so return 0. */
65 if (0 <= st
->st_atim
.tv_nsec
)
67 if (st
->st_atim
.tv_nsec
== -1)
69 if (fstatat (fd
, file
, st
, flag
) == 0)
71 st
->st_atim
.tv_nsec
= -2;
77 return fstatat (fd
, file
, st
, flag
);
81 /* Initialize a fstatat cache *ST. Return ST for convenience. */
82 static inline struct stat
*
83 cache_stat_init (struct stat
*st
)
85 #if HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
86 st
->st_atim
.tv_nsec
= -1;
91 /* Return 1 if FILE is an unwritable non-symlink,
92 0 if it is writable or some other type of file,
93 -1 and set errno if there is some problem in determining the answer.
94 Set *BUF to the file status. */
96 write_protected_non_symlink (int fd_cwd
,
100 if (can_write_any_file ())
102 if (cache_fstatat (fd_cwd
, file
, buf
, AT_SYMLINK_NOFOLLOW
) != 0)
104 if (S_ISLNK (buf
->st_mode
))
106 /* Here, we know FILE is not a symbolic link. */
108 /* In order to be reentrant -- i.e., to avoid changing the working
109 directory, and at the same time to be able to deal with alternate
110 access control mechanisms (ACLs, xattr-style attributes) and
111 arbitrarily deep trees -- we need a function like eaccessat, i.e.,
112 like Solaris' eaccess, but fd-relative, in the spirit of openat. */
114 /* In the absence of a native eaccessat function, here are some of
115 the implementation choices [#4 and #5 were suggested by Paul Eggert]:
116 1) call openat with O_WRONLY|O_NOCTTY
117 Disadvantage: may create the file and doesn't work for directory,
118 may mistakenly report 'unwritable' for EROFS or ACLs even though
119 perm bits say the file is writable.
121 2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
122 Disadvantage: changes working directory (not reentrant) and can't
123 work if save_cwd fails.
125 3) if (euidaccess (full_name, W_OK) == 0)
126 Disadvantage: doesn't work if full_name is too long.
127 Inefficient for very deep trees (O(Depth^2)).
129 4) If the full pathname is sufficiently short (say, less than
130 PATH_MAX or 8192 bytes, whichever is shorter):
131 use method (3) (i.e., euidaccess (full_name, W_OK));
132 Otherwise: vfork, fchdir in the child, run euidaccess in the
133 child, then the child exits with a status that tells the parent
134 whether euidaccess succeeded.
136 This avoids the O(N**2) algorithm of method (3), and it also avoids
137 the failure-due-to-too-long-file-names of method (3), but it's fast
138 in the normal shallow case. It also avoids the lack-of-reentrancy
139 and the save_cwd problems.
140 Disadvantage; it uses a process slot for very-long file names,
141 and would be very slow for hierarchies with many such files.
143 5) If the full file name 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: look just at the file bits. Perhaps issue a warning
147 the first time this occurs.
149 This is like (4), except for the "Otherwise" case where it isn't as
150 "perfect" as (4) but is considerably faster. It conforms to current
151 POSIX, and is uniformly better than what Solaris and FreeBSD do (they
152 mess up with long file names). */
155 if (faccessat (fd_cwd
, file
, W_OK
, AT_EACCESS
) == 0)
158 return errno
== EACCES
? 1 : -1;
162 /* Return the status of the directory identified by FTS and ENT.
163 This is -1 if the directory is empty, 0 if it is nonempty,
164 and a positive error number if there was trouble determining the status,
165 e.g., it is not a directory, or permissions problems, or I/O errors.
166 Use *DIR_STATUS as a cache for the status. */
168 get_dir_status (FTS
const *fts
, FTSENT
const *ent
, int *dir_status
)
170 if (*dir_status
== DS_UNKNOWN
)
171 *dir_status
= directory_status (fts
->fts_cwd_fd
, ent
->fts_accpath
);
175 /* Prompt whether to remove FILENAME, if required via a combination of
176 the options specified by X and/or file attributes. If the file may
177 be removed, return RM_OK or RM_USER_ACCEPTED, the latter if the user
178 was prompted and accepted. 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 Use and update *DIR_STATUS as needed, via the conventions of
188 static enum RM_status
189 prompt (FTS
const *fts
, FTSENT
const *ent
, bool is_dir
,
190 struct rm_options
const *x
, enum Prompt_action mode
,
193 int fd_cwd
= fts
->fts_cwd_fd
;
194 char const *full_name
= ent
->fts_path
;
195 char const *filename
= ent
->fts_accpath
;
197 struct stat
*sbuf
= &st
;
198 cache_stat_init (sbuf
);
200 int dirent_type
= is_dir
? DT_DIR
: DT_UNKNOWN
;
201 int write_protected
= 0;
203 /* When nonzero, this indicates that we failed to remove a child entry,
204 either because the user declined an interactive prompt, or due to
205 some other failure, like permissions. */
207 return RM_USER_DECLINED
;
209 if (x
->interactive
== RMI_NEVER
)
213 if (!x
->ignore_missing_files
214 && (x
->interactive
== RMI_ALWAYS
|| x
->stdin_tty
)
215 && dirent_type
!= DT_LNK
)
217 write_protected
= write_protected_non_symlink (fd_cwd
, filename
, sbuf
);
221 if (write_protected
|| x
->interactive
== RMI_ALWAYS
)
223 if (0 <= write_protected
&& dirent_type
== DT_UNKNOWN
)
225 if (cache_fstatat (fd_cwd
, filename
, sbuf
, AT_SYMLINK_NOFOLLOW
) == 0)
227 if (S_ISLNK (sbuf
->st_mode
))
228 dirent_type
= DT_LNK
;
229 else if (S_ISDIR (sbuf
->st_mode
))
230 dirent_type
= DT_DIR
;
231 /* Otherwise it doesn't matter, so leave it DT_UNKNOWN. */
235 /* This happens, e.g., with 'rm '''. */
236 write_protected
= -1;
241 if (0 <= write_protected
)
245 /* Using permissions doesn't make sense for symlinks. */
246 if (x
->interactive
!= RMI_ALWAYS
)
251 /* Unless we're either deleting directories or deleting
252 recursively, we want to raise an EISDIR error rather than
253 prompting the user */
255 || (x
->remove_empty_directories
256 && get_dir_status (fts
, ent
, dir_status
) != 0)))
258 write_protected
= -1;
259 wp_errno
= *dir_status
<= 0 ? EISDIR
: *dir_status
;
264 char const *quoted_name
= quoteaf (full_name
);
266 if (write_protected
< 0)
268 error (0, wp_errno
, _("cannot remove %s"), quoted_name
);
272 /* Issue the prompt. */
273 if (dirent_type
== DT_DIR
274 && mode
== PA_DESCEND_INTO_DIR
275 && get_dir_status (fts
, ent
, dir_status
) == DS_NONEMPTY
)
278 ? _("%s: descend into write-protected directory %s? ")
279 : _("%s: descend into directory %s? ")),
280 program_name
, quoted_name
);
281 else if (0 < *dir_status
)
283 if ( ! (x
->remove_empty_directories
&& *dir_status
== EACCES
))
285 error (0, *dir_status
, _("cannot remove %s"), quoted_name
);
289 /* The following code can lead to a successful deletion only with
290 the --dir (-d) option (remove_empty_directories) and an empty
291 inaccessible directory. In the first prompt call for a directory,
292 we'd normally ask whether to descend into it, but in this case
293 (it's inaccessible), that is not possible, so don't prompt. */
294 if (mode
== PA_DESCEND_INTO_DIR
)
298 _("%s: attempt removal of inaccessible directory %s? "),
299 program_name
, quoted_name
);
303 if (cache_fstatat (fd_cwd
, filename
, sbuf
, AT_SYMLINK_NOFOLLOW
) != 0)
305 error (0, errno
, _("cannot remove %s"), quoted_name
);
311 /* TRANSLATORS: In the next two strings the second %s is
312 replaced by the type of the file. To avoid grammatical
313 problems, it may be more convenient to translate these
314 strings instead as: "%1$s: %3$s is write-protected and
315 is of type '%2$s' -- remove it? ". */
316 ? _("%s: remove write-protected %s %s? ")
317 : _("%s: remove %s %s? ")),
318 program_name
, file_type (sbuf
), quoted_name
);
321 return yesno () ? RM_USER_ACCEPTED
: RM_USER_DECLINED
;
326 /* When a function like unlink, rmdir, or fstatat fails with an errno
327 value of ERRNUM, return true if the specified file system object
328 is guaranteed not to exist; otherwise, return false. */
330 nonexistent_file_errno (int errnum
)
332 /* Do not include ELOOP here, since the specified file may indeed
333 exist, but be (in)accessible only via too long a symlink chain.
334 Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail
335 if the "..." part expands to a long enough sequence of "./"s,
336 even though ./foo does indeed exist.
338 Another case to consider is when a particular name is invalid for
339 a given file system. In 2011, smbfs returns EINVAL, but the next
340 revision of POSIX will require EILSEQ for that situation:
341 https://austingroupbugs.net/view.php?id=293
356 /* Encapsulate the test for whether the errno value, ERRNUM, is ignorable. */
358 ignorable_missing (struct rm_options
const *x
, int errnum
)
360 return x
->ignore_missing_files
&& nonexistent_file_errno (errnum
);
363 /* Tell fts not to traverse into the hierarchy at ENT. */
365 fts_skip_tree (FTS
*fts
, FTSENT
*ent
)
367 fts_set (fts
, ent
, FTS_SKIP
);
368 /* Ensure that we do not process ENT a second time. */
369 ignore_value (fts_read (fts
));
372 /* Upon unlink failure, or when the user declines to remove ENT, mark
373 each of its ancestor directories, so that we know not to prompt for
376 mark_ancestor_dirs (FTSENT
*ent
)
379 for (p
= ent
->fts_parent
; FTS_ROOTLEVEL
<= p
->fts_level
; p
= p
->fts_parent
)
387 /* Remove the file system object specified by ENT. IS_DIR specifies
388 whether it is expected to be a directory or non-directory.
389 Return RM_OK upon success, else RM_ERROR. */
390 static enum RM_status
391 excise (FTS
*fts
, FTSENT
*ent
, struct rm_options
const *x
, bool is_dir
)
393 int flag
= is_dir
? AT_REMOVEDIR
: 0;
394 if (unlinkat (fts
->fts_cwd_fd
, ent
->fts_accpath
, flag
) == 0)
399 ? _("removed directory %s\n")
400 : _("removed %s\n")), quoteaf (ent
->fts_path
));
405 /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
406 nonexistent files. When the file is indeed missing, map that to ENOENT,
407 so that rm -f ignores it, as required. Even without -f, this is useful
408 because it makes rm print the more precise diagnostic. */
412 if ( ! (fstatat (fts
->fts_cwd_fd
, ent
->fts_accpath
, &st
,
418 if (ignorable_missing (x
, errno
))
421 /* When failing to rmdir an unreadable directory, we see errno values
422 like EISDIR or ENOTDIR (or, on Solaris 10, EEXIST), but they would be
423 meaningless in a diagnostic. When that happens, use the earlier, more
424 descriptive errno value. */
425 if (ent
->fts_info
== FTS_DNR
426 && (errno
== ENOTEMPTY
|| errno
== EISDIR
|| errno
== ENOTDIR
428 && ent
->fts_errno
!= 0)
429 errno
= ent
->fts_errno
;
430 error (0, errno
, _("cannot remove %s"), quoteaf (ent
->fts_path
));
431 mark_ancestor_dirs (ent
);
435 /* This function is called once for every file system object that fts
436 encounters. fts performs a depth-first traversal.
437 A directory is usually processed twice, first with fts_info == FTS_D,
438 and later, after all of its entries have been processed, with FTS_DP.
439 Return RM_ERROR upon error, RM_USER_DECLINED for a negative response
440 to an interactive prompt, and otherwise, RM_OK. */
441 static enum RM_status
442 rm_fts (FTS
*fts
, FTSENT
*ent
, struct rm_options
const *x
)
444 int dir_status
= DS_UNKNOWN
;
446 switch (ent
->fts_info
)
448 case FTS_D
: /* preorder directory */
450 && !(x
->remove_empty_directories
451 && get_dir_status (fts
, ent
, &dir_status
) != 0))
453 /* This is the first (pre-order) encounter with a directory
454 that we cannot delete.
455 Not recursive, and it's not an empty directory (if we're removing
456 them) so arrange to skip contents. */
457 int err
= x
->remove_empty_directories
? ENOTEMPTY
: EISDIR
;
458 error (0, err
, _("cannot remove %s"), quoteaf (ent
->fts_path
));
459 mark_ancestor_dirs (ent
);
460 fts_skip_tree (fts
, ent
);
464 /* Perform checks that can apply only for command-line arguments. */
465 if (ent
->fts_level
== FTS_ROOTLEVEL
)
468 If the basename of a command line argument is "." or "..",
469 diagnose it and do nothing more with that argument. */
470 if (dot_or_dotdot (last_component (ent
->fts_accpath
)))
473 _("refusing to remove %s or %s directory: skipping %s"),
474 quoteaf_n (0, "."), quoteaf_n (1, ".."),
475 quoteaf_n (2, ent
->fts_path
));
476 fts_skip_tree (fts
, ent
);
481 If a command line argument resolves to "/" (and --preserve-root
482 is in effect -- default) diagnose and skip it. */
483 if (ROOT_DEV_INO_CHECK (x
->root_dev_ino
, ent
->fts_statp
))
485 ROOT_DEV_INO_WARN (ent
->fts_path
);
486 fts_skip_tree (fts
, ent
);
490 /* If a command line argument is a mount point and
491 --preserve-root=all is in effect, diagnose and skip it.
492 This doesn't handle "/", but that's handled above. */
493 if (x
->preserve_all_root
)
496 char *parent
= file_name_concat (ent
->fts_accpath
, "..", nullptr);
499 if (!parent
|| lstat (parent
, &statbuf
))
502 _("failed to stat %s: skipping %s"),
503 quoteaf_n (0, parent
),
504 quoteaf_n (1, ent
->fts_accpath
));
510 if (failed
|| fts
->fts_dev
!= statbuf
.st_dev
)
515 _("skipping %s, since it's on a different device"),
516 quoteaf (ent
->fts_path
));
517 error (0, 0, _("and --preserve-root=all is in effect"));
519 fts_skip_tree (fts
, ent
);
526 enum RM_status s
= prompt (fts
, ent
, true /*is_dir*/, x
,
527 PA_DESCEND_INTO_DIR
, &dir_status
);
529 if (s
== RM_USER_ACCEPTED
&& dir_status
== DS_EMPTY
)
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);
535 fts_skip_tree (fts
, ent
);
538 if (! (s
== RM_OK
|| s
== RM_USER_ACCEPTED
))
540 mark_ancestor_dirs (ent
);
541 fts_skip_tree (fts
, ent
);
547 case FTS_F
: /* regular file */
548 case FTS_NS
: /* stat(2) failed */
549 case FTS_SL
: /* symbolic link */
550 case FTS_SLNONE
: /* symbolic link without target */
551 case FTS_DP
: /* postorder directory */
552 case FTS_DNR
: /* unreadable directory */
553 case FTS_NSOK
: /* e.g., dangling symlink */
554 case FTS_DEFAULT
: /* none of the above */
556 /* With --one-file-system, do not attempt to remove a mount point.
557 fts' FTS_XDEV ensures that we don't process any entries under
559 if (ent
->fts_info
== FTS_DP
560 && x
->one_file_system
561 && FTS_ROOTLEVEL
< ent
->fts_level
562 && ent
->fts_statp
->st_dev
!= fts
->fts_dev
)
564 mark_ancestor_dirs (ent
);
565 error (0, 0, _("skipping %s, since it's on a different device"),
566 quoteaf (ent
->fts_path
));
570 bool is_dir
= ent
->fts_info
== FTS_DP
|| ent
->fts_info
== FTS_DNR
;
571 enum RM_status s
= prompt (fts
, ent
, is_dir
, x
, PA_REMOVE_DIR
,
573 if (! (s
== RM_OK
|| s
== RM_USER_ACCEPTED
))
575 return excise (fts
, ent
, x
, is_dir
);
578 case FTS_DC
: /* directory that causes cycles */
579 emit_cycle_warning (ent
->fts_path
);
580 fts_skip_tree (fts
, ent
);
584 /* Various failures, from opendir to ENOMEM, to failure to "return"
585 to preceding directory, can provoke this. */
586 error (0, ent
->fts_errno
, _("traversal failed: %s"),
587 quotef (ent
->fts_path
));
588 fts_skip_tree (fts
, ent
);
592 error (0, 0, _("unexpected failure: fts_info=%d: %s\n"
593 "please report to %s"),
595 quotef (ent
->fts_path
),
601 /* Remove FILEs, honoring options specified via X.
602 Return RM_OK if successful. */
604 rm (char *const *file
, struct rm_options
const *x
)
606 enum RM_status rm_status
= RM_OK
;
610 int bit_flags
= (FTS_CWDFD
614 if (x
->one_file_system
)
615 bit_flags
|= FTS_XDEV
;
617 FTS
*fts
= xfts_open (file
, bit_flags
, nullptr);
623 ent
= fts_read (fts
);
628 error (0, errno
, _("fts_read failed"));
629 rm_status
= RM_ERROR
;
634 enum RM_status s
= rm_fts (fts
, ent
, x
);
636 affirm (VALID_STATUS (s
));
637 UPDATE_STATUS (rm_status
, s
);
640 if (fts_close (fts
) != 0)
642 error (0, errno
, _("fts_close failed"));
643 rm_status
= RM_ERROR
;