Since commit 5454df9c31 ("rename: check source file access early")
rename fails early for symlinks with non-existing target (regression),
because access() dereferences the link.
From access(2):
"access() checks whether the calling process can access the file pathname.
If pathname is a symbolic link, it is dereferenced."
Thus replace access() with faccessat() and lstat() as fallback,
(as in do_symlink()), that is equivalent for symlink and files.
From fsaccess(2) and stat(2):
"The faccessat() system call operates in exactly the same way as access(),
except for the differences described here.
[...]
If pathname is relative and dirfd is the special value AT_FDCWD, then pathname
is interpreted relative to the current working directory of the calling process
(like access()).
[...]
AT_SYMLINK_NOFOLLOW
If pathname is a symbolic link, do not dereference it:
instead return information about the link itself."
"lstat() is identical to stat(), except that if pathname is a symbolic link, then
it returns information about the link itself, not the file that it refers to."
Testing
-------
1) symlink with existing target
2) symlink with non-existing target
3) non-existing symlink
4) existing file
5) non-existing file
Before:
$ touch file-found
$ ln -s file-found symlink-1
$ ./rename sym symbolic- symlink-1 # XPASS.
$ echo $?
0
$ ln -s file-not-found symlink-2
$ ./rename sym symbolic- symlink-2 # FAIL! REGRESSION.
rename: symlink-2: not accessible: No such file or directory
$ echo $?
1
$ ./rename sym symbolic- symlink-3 # XFAIL.
rename: symlink-3: not accessible: No such file or directory
$ echo $?
1
$ touch file-found
$ ./rename found existing file-found # XPASS.
$ echo $?
0
$ ./rename found existing file-not-found # XFAIL.
rename: file-not-found: not accessible: No such file or directory
$ echo $?
1
After:
$ touch file-found
$ ln -s file-found symlink-1
$ ./rename sym symbolic- symlink-1 # XPASS.
$ echo $?
0
$ ln -s file-not-found symlink-2
$ ./rename sym symbolic- symlink-2 # PASS! REGRESSION FIXED.
$ echo $?
0
$ ./rename sym symbolic- symlink-3 # XFAIL.
rename: symlink-3: not accessible: No such file or directory
$ echo $?
1
$ touch file-found
$ ./rename found existing file-found # XPASS.
$ echo $?
0
$ ./rename found existing file-not-found # XFAIL.
rename: file-not-found: not accessible: No such file or directory
$ echo $?
1
And to test/simulate faccessat()'s EINVAL for AT_SYMLINK_NOFOLLOW
for Mac OS X, per commit 826538bf64 ("rename: skip faccessat()
failure if AT_SYMLINK_NOFOLLOW is not a valid flag"), forced 'if'
to evaluate to false so that lstat() is taken.
It still fails early; the error messages are slightly different
('not accessible' vs. 'stat of ... failed') but still tell same
'No such file or directory'; exit code is the same as well.
$ ./rename sym symbolic- symlink-3 # XFAIL. DIFF MSG/SAME RC.
rename: stat of symlink-3 failed: No such file or directory
$ echo $?
1
$ ./rename found existing file-not-found # XFAIL. DIFF MSG/SAME RC.
rename: stat of file-not-found failed: No such file or directory
$ echo $?
1
Tested on commit 2b41c409e ("Merge branch 'blkd-err' of ...")
Signed-off-by: Mauricio Faria de Oliveira <mfo@canonical.com>
In case where the non-standard `fpurge` function is available, we
redefine `__fpurge` to `fpurge`. We can do so because the only
difference between both functions is that one returns an error code
while the other does not. But as we do not check the error code either
way, we do not care about which one of them we use.
The above redefinition happens unconditionally if we know that `fpurge`
exists. Most notably, we also redefine it if we already do have an
`__fpurge` function available that could be used. This causes problems
on musl-based platforms, where we detect availability of `fpurge` in
libc, but where no function declaration for it exists in "stdio_ext.h".
The compiler thus prints a warning due to an unknown function, even
though it will link just fine.
Avoid this warning by only redefining `__fpurge` to `fpurge` when
HAVE___FPURGE is not defined.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Making a purge in cbreak mode also makes the code compatible with
canonical mode. This can be useful in the case a shell, like bash, does
not restore the tty state of stopped jobs before restarting them. An
alternative fix to this minor shortcoming would be to retest the tty
state each time inside ask().
Set tty_cbreak only when tty has a VMIN of 1 to avoid having to purge at
all in cbreak mode.
The prompt is still compatible with a non interactive input from a pipe.
This change makes rename detect inexisting files given on the command
line and consider them faliures. This is particularly useful with
--no-act (to detect extraneous arguments).
It also prevents skipping non existing files (when the modified name
happens to exist). This makes --verbose not print skipping messages of
false positives (the access error is printed instead).
This fixes a bug introduced by commit fabb90676 ("Added --no-override
option to rename.", 2017-05-27) where the fallthrough meant to let
--no-act set --verbose was changed to set --no-override (the previous
code was too smart).
Do not let --no-act set --verbose anymore but update the manual to
recommend adding option --verbose. This is to be able to make --no-act
detect only non existing file arguments (in a future commit).
The previous behaviour was to overwrite a symlink only when the new
destination did not exist, i.e. to avoid creating a symlink to an
existing file! It had not been documented and it seems
counter-intuitive to me. So the new behavior protects symlinks pointing
to existing targets from being changed.
Also update manpage to document this mode.
This is more lightweight than calling stat(3). In same go add a regression
test to ensure changes like this will not break --no-overwrite option.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
changed in include/c.h and applied via sed:
sed -i 's/fprintf.*\(USAGE_MAN_TAIL.*\)/printf(\1/' $(git ls-files -- "*.c")
sed -i 's/print_usage_help_options\(.*\);/printf(USAGE_HELP_OPTIONS\1);/' $(git ls-files -- "*.c")
Signed-off-by: Ruediger Meier <ruediger.meier@ga-group.nl>
Consolidate --help and --version descriptions. We are
now able to align them to the other options.
We changed include/c.h. The rest of this patch was
generated by sed, plus manually setting the right
alignment numbers. We do not change anything but
white spaces in the --help output.
Signed-off-by: Ruediger Meier <ruediger.meier@ga-group.nl>
The rename(1) can exit early when replace expression and replacement are
identical string. It is also appropriate to change return value in this
case to 'nothing was renamed'.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
(Original patch and commit message edited by Rudi.)
gcc-7 adds -Wimplicit-fallthrough=3 to our default flag -Wextra.
This warning can be silenced by using comment /* fallthrough */
which is also recognized by other tools like coverity. There are
also other valid comments (see man gcc-7) but we consolidate this
style now.
We could have also used __attribute__((fallthrough)) but the comment
looks nice and does not need to be ifdef'ed for compatibility.
Reference: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=7652
Reference: https://developers.redhat.com/blog/2017/03/10/wimplicit-fallthrough-in-gcc-7/
Reviewed-by: Ruediger Meier <ruediger.meier@ga-group.nl>
Suggested-by: Karel Zak <kzak@redhat.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
It is reasonable to assume use of --no-act means one wants to always see
what would have happen if rename is done. To say same slightly differently,
if there is sn use case for silent rename --no-act run I cannot think one.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
[kzak@redhat.com: - rename --dry-run to --no-act]
Signed-off-by: Alexander F Rødseth <xyproto@archlinux.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
The command "touch b0;rename.ul -v ./b0 ./b1 ./b0" used to work
before "allow renaming in subdirectories" change.
(regression in commit bd9ced628b)
Addresses: https://bugs.debian.org/789240
Reported-by: gregrwm <bug-grub@whitleymott.net>
Reviewed-by: Sami Kerola <kerolasa@iki.fi>
Signed-off-by: Andreas Henriksson <andreas@fatal.se>
The rindex() is marked legacy in POSIX.1-2001, and apparently Androids
bionic libc does not even have it so it is best not to use the legacy
interface.
Reference: https://lists.gnu.org/archive/html/weechat-dev/2014-02/msg00004.html
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
The message "stat failed %s" seems to say that stat() failed to
do something, or failed to pass a test, but of course it means
that the statting of something failed. So say so. Also make
two very similar messages equal to this one.
Signed-off-by: Benno Schulenberg <bensberg@justemail.net>
This adds a concise description of a tool to its usage text.
A first form of this patch was proposed by Steven Honeyman
(see http://www.spinics.net/lists/util-linux-ng/msg09994.html).
Signed-off-by: Benno Schulenberg <bensberg@justemail.net>
Fixing plain typos, miswordings, inconsistent periods, some missing
angular brackets, and a proper pluralization (even when it involves
a constant, because for some languages the precise value matters).
Signed-off-by: Benno Schulenberg <bensberg@justemail.net>
Add separate functions to different functionality, and add a function for
the stuff that is in common for both.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Try to do all file operations even when one or some of them fail, and
use exit value to inform what happen.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Earlier the rename(1) considered path as possible string to be renamed,
could lead to an issue with none existing destination. See below for
demonstration of this issue. After this change all directory elements
are ignored when the match finding happens.
$ cd $(mktemp -d)
$ mkdir aa ab
$ touch a{a,b}/aa
$ rename -v a x */aa
rename: aa/aa: rename to xa/aa failed: No such file or directory
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
The rename has new verbose option which will print which files
where renamed. Maintenance fixes includes long options, coding
style and freeing memory after usage.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
The number of files successfully renamed is calculated and stored in variable
ct, > but actually the variable is not used afterwards.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>