util-linux/misc-utils
Mauricio Faria de Oliveira 477239ce0d rename: fix regression for symlink with non-existing target
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>
2020-07-07 16:19:15 -03:00
..
.gitignore getopt: use examples installation directory in man page 2020-02-15 15:24:01 +00:00
Makemodule.am getopt: use examples installation directory in man page 2020-02-15 15:24:01 +00:00
blkid.8 Manual pages: wording fix: "another" ==> "other" 2020-05-29 14:31:47 +02:00
blkid.c docs: improve size arguments description in --help output 2020-02-05 11:01:36 +01:00
cal.1 doc: misc-utils/*: Fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
cal.c cal: use size_t to calculate width [lgtm scan] 2020-07-03 13:17:51 +02:00
fincore.1 docs: (man) remove double quotes (") in .SH lines 2020-05-19 12:15:34 +02:00
fincore.c cleanup: Remove some spurious spaces 2019-10-01 13:01:43 +02:00
findfs.8 doc: misc-utils/*: Fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
findfs.c misc: consolidate version printing and close_stdout() 2019-04-16 15:14:13 +02:00
findmnt-verify.c [clang-tidy] do not use else after return 2020-04-20 13:20:59 -07:00
findmnt.8 Manual pages: order NOTES / HISTORY / BUGS / EXAMPLE consistently 2020-05-22 10:25:50 +02:00
findmnt.c [clang-tidy] fix wrong *cmp usage 2020-04-20 13:21:00 -07:00
findmnt.h misc-tools/findmnt: add --pseudo, --real filters 2018-05-10 11:58:30 -05:00
getopt-parse.bash getops: make --a-long option work again 2017-05-16 14:54:41 +02:00
getopt-parse.tcsh getops: improve getopt-parse.bash example 2016-07-27 16:08:43 +01:00
getopt.1.in getopt: use examples installation directory in man page 2020-02-15 15:24:01 +00:00
getopt.c [clang-tidy] do not use else after return 2020-04-20 13:20:59 -07:00
hardlink.1 doc: misc-utils/*: Fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
hardlink.c [clang-tidy] fix wrong *cmp usage 2020-04-20 13:21:00 -07:00
kill.1 doc: Fix some warnings from "test-groff" for manuals 2020-06-10 10:22:58 +02:00
kill.c [clang-tidy] do not use else after return 2020-04-20 13:20:59 -07:00
logger.1 doc: misc-utils/*: Fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
logger.c various: fix more lgtm scan warnings 2020-02-20 20:18:46 +00:00
look.1 doc: misc-utils/*: Fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
look.c misc: consolidate version printing and close_stdout() 2019-04-16 15:14:13 +02:00
lsblk-devtree.c lsblk: fix -E segfault 2019-07-15 12:28:26 +02:00
lsblk-mnt.c lsblk: rename blkdev_cxt to lsblk_device 2018-12-07 12:32:57 +01:00
lsblk-properties.c lsblk: Fall back to ID_SERIAL 2020-05-04 11:21:01 +02:00
lsblk.8 Manual pages: order NOTES / HISTORY / BUGS / EXAMPLE consistently 2020-05-22 10:25:50 +02:00
lsblk.c lsblk: Ignore hidden devices 2020-05-14 15:48:26 +02:00
lsblk.h lsblk: add PARTTYPENAME column 2019-12-04 12:38:57 +01:00
lslocks.8 docs: (man) remove double quotes (") in .SH lines 2020-05-19 12:15:34 +02:00
lslocks.c misc: consolidate version printing and close_stdout() 2019-04-16 15:14:13 +02:00
mcookie.1 Manual pages: order NOTES / HISTORY / BUGS / EXAMPLE consistently 2020-05-22 10:25:50 +02:00
mcookie.c docs: improve size arguments description in --help output 2020-02-05 11:01:36 +01:00
namei.1 Manual pages: order AUTHORS / COPYRIGHT / SEE ALSO / AVAILABILITY consistently 2020-05-22 10:25:49 +02:00
namei.c misc: consolidate version printing and close_stdout() 2019-04-16 15:14:13 +02:00
rename.1 doc: misc-utils/*: Fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
rename.c rename: fix regression for symlink with non-existing target 2020-07-07 16:19:15 -03:00
test_uuidd.c misc: replace magic number 37 with UUID_STR_LEN 2017-09-05 11:49:21 +02:00
uuidd.8.in man pages: Change a HYPHEN-MINUS (-) to a minus (\-) for options and numbers 2019-12-17 12:32:43 +01:00
uuidd.c [clang-tidy] do not use else after return 2020-04-20 13:20:59 -07:00
uuidd.rc.in build: use --runstatedir instead of --localstatedir 2017-07-31 15:24:46 +02:00
uuidd.service.in uuidd: Add hardening settings to uuidd.service 2018-11-29 10:37:08 +01:00
uuidd.socket.in build: use --runstatedir instead of --localstatedir 2017-07-31 15:24:46 +02:00
uuidgen.1 Manual pages: rename EXAMPLE section to EXAMPLES 2020-05-28 14:51:54 +02:00
uuidgen.c misc: consolidate version printing and close_stdout() 2019-04-16 15:14:13 +02:00
uuidparse.1 docs: (man) remove double quotes (") in .SH lines 2020-05-19 12:15:34 +02:00
uuidparse.c misc: consolidate version printing and close_stdout() 2019-04-16 15:14:13 +02:00
whereis.1 doc: misc-utils/*: Fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
whereis.c [clang-tidy] do not return in void functions 2020-04-19 14:03:21 -07:00
wipefs.8 wipefs: add --lock and LOCK_BLOCK_DEVICE 2020-05-27 17:00:08 +02:00
wipefs.c wipefs: add --lock and LOCK_BLOCK_DEVICE 2020-05-27 17:00:08 +02:00