(IF_READDIR_NEEDS_REWINDDIR): Remove.
(remove_cwd_entries): Rewrite to avoid IF_READDIR_NEEDS_REWINDDIR,
which was a bit weird because it couldn't be emulated by a function.
(IF_READDIR_NEEDS_REWINDDIR): Define.
[! HAVE_WORKING_READDIR] (remove_cwd_entries): If readdir has just
returned NULL and there has been at least one successful unlink or
rmdir call since the opendir or previous rewinddir, then call
rewinddir and reiterate the loop.
accurate diagnostic when failing to remove a file owned by some other
user. Reported by Ivo Timmermans via Michael Stone.
This fixes Debian bug# 178471.
has d_type == DT_UNKNOWN it may still be a directory -- or not (e.g., with
FreeBSD on an NFS-mounted file system), so resort to calling lstat to find out.
* src/remove.c: [cycle_check_state]: New global.
(remove_cwd_entries): Adapt to new semantics of cycle_check.
(rm): Call cycle_check_init and cycle_check_free for each file.
When rm detects a cycle, don't abort the entire command,
but rather just the affected command line argument.
* src/remove.c: Include <setjmp.h>
(struct dirstack_state) [current_arg_jumpbuf]: New member.
(remove_cwd_entries): Call longjmp if we detect a cycle.
(rm): Call setjmp here.
* src/remove.c (cycle_check, is_power_of_two): Remove functions.
Instead, include cycle-check.h and use it.
To be used in place of these file-scoped globals ...
(dir_stack, len_stack, Active_dir): Remove globals.
(ds_init, ds_free): New functions.
(full_filename): Define.
(full_filename_): Rename from full_filename.
Begin to make AD_* functions more generic.
(AD_push_initial): Don't set status to RM_OK here.
(AD_push): Likewise.
(AD_INIT_OTHER_MEMBERS): Define.
(remove_dir): Define the `status' member manually after each
call to AD_push or AD_push_initial.
permissions, but give a misleading diagnostic like this:
rm: cannot chdir from `.' to `foo': Not a directory
(remove_dir): Detect the case in which unlinking a
non-directory fails with EPERM, and give an appropriate diagnostic.
around the problem of making the translations of the adjective
`write-protected' and the corresponding run-time-variable noun
(e.g., file, directory, symlink, etc.) consistent. From Paul Eggert.
* src/remove.c (enum Ternary): Define type.
(prompt): Add a parameter. Adjust callers.
(remove_entry): Attempt rmdir here, only if a directory is
`known' to be empty. Significant rework.
(remove_dir): Propagate failure `up' also when rmdir fails.
In interactive mode, prompt only once about an empty directory.
* src/remove.c (enum Prompt_action): Define.
(prompt): Two new parameters. Adjust all callers.
Performance.
* src/remove.c (remove_entry) [!ROOT_CAN_UNLINK_DIRS]:
Don't call rmdir here.
* src/remove.c (AD_pop_and_chdir): Don't use errno (it's not valid)
in diagnostic for changed dev/ino.
(remove_entry): Tweak diagnostic.
* src/remove.c (ROOT_CAN_UNLINK_DIRS): Define.
(AD_pop_and_chdir): Propagate status as we traverse back `up' the tree.
(DO_UNLINK, DO_RMDIR): Define.
(remove_entry) [ROOT_CAN_UNLINK_DIRS]: Add code so this works also on
systems where root can use `unlink' to remove directories.
* src/remove.c: Include file-type.h.
Include file type in prompt when asking whether to remove file.
Based on a patch from Paul Eggert.
* src/remove.c (prompt): Add comment.
* src/remove.c (remove_dir): Fix another (known) leak.
* src/remove.c (hash_freer): New function.
(AD_mark_helper): Use it.
(AD_mark_as_unremovable): xstrdup the filename argument.
(remove_dir): Free directory name.
* src/remove.c (remove_entry): Fail also when trying to remove a
directory without the --recursive option.
Change a diagnostic, s/unlink/remove/, now that it can apply also
to a directory.
* src/remove.c (is_empty_dir): New function.
(prompt): New function, factored out of...
(remove_entry): ...here. Call it.
(remove_dir): Call prompt before rmdir.
* src/remove.c (remove_entry): Add support for prompting (e.g., -i).
* src/remove.h (UPDATE_STATUS): New macro.
* src/remove.c [AD_ent] (status): New member. This lets us propagate
the status from a subdirectory to its parent via AD_pop_and_chdir.
(AD_push_initial): Set it.
(AD_push): Likewise.
(remove_cwd_entries): Change return type to enum RM_status, and
adjust all callers.
(rm): Use UPDATE_STATUS rather than open-coding it.
* src/remove.c (remove_entry): New function, factored out of...
(remove_cwd_entries): ...here, and...
(rm_1): ...here.
* src/remove.c (remove_cwd_entries): Add support for --verbose.
(remove_dir): Likewise.
(rm_1): Likewise.
* src/remove.c (rm): Free cwd_state, if necessary.
* src/remove.c (rm_1): Remove now useless (always true)
user_specified_name parameter. Adjust sole caller.
* src/remove.c (rm): New function. This interface allows
one to remove multiple arguments at a time. This is important in
that it allows us to hide the remove_init/remove_fini functions and
the cwd_state parameter.
(rm_1): Renamed from rm.
(remove_init, remove_fini): Remove functions. Each body is now
part of `rm'.
out of remove_dir. The sole difference is that upon detecting a
cycle, rm now dies unconditionally. Before, in interactive mode,
it would ask the user whether to continue.
(remove_dir): Call cycle_check.
Instead, detect them lazily with just O(1) memory.
Suggestion from Andi Kleen.
(is_power_of_two): New function.
(print_nth_dir, make_active_dir_ent): Remove functions.
(hash_active_dir_ent, hash_compare_active_dir_ents): Likewise.
(remove_dir): Check for cycles here, ...
(rm): ... and don't check for cycles here.
(rm): Call fspec_get_full_mode here, rather than
fspec_get_filetype_mode. We want to get the dev/ino earlier, and
at the same time as when we get the file type, to avoid the risk
that an attacker would change e.g. a directory to a symlink before
we record its dev/ino.
removing unintended files. In one scenario, if root is removing a
hierarchy that is writable by the malicious user, that user may trick
root into removing all of `/'. Reported by Wojciech Purczynski.
(remove_dir): After chdir `..', call lstat to get the
dev/inode of "." and fail if they aren't the same as the old numbers.
(remove_cwd_entries): New parameter, `cwd_dev_ino'.
(remove_dir): Likewise.
(rm): Likewise.
Adjust all callers.