Go to file
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
.github/workflows travis: turn on CIFuzz 2020-07-03 11:19:14 +02:00
Documentation docs: remove drone.io, add lgtm.com 2020-07-01 09:33:27 +02:00
bash-completion bash-completion: release preparations 2020-06-15 11:35:40 +02:00
config build-sys: gtkdoc-fixxref v1.27 requires module option 2018-02-01 13:23:40 +01:00
disk-utils disk-utils: Add reference to ufiformat(8) 2020-06-27 21:15:10 +02:00
include dmesg: adjust timestamps according to suspended time 2020-06-04 10:57:36 +02:00
lib lib/sysfs: fix prefix use in sysfs_devname_is_hidden() 2020-06-19 10:06:25 +02:00
libblkid libblkid: remove blkid_llseek() 2020-07-01 15:47:20 +02:00
libfdisk libfdisk: (gpt) fix compiler warning [-Wmaybe-uninitialized] 2020-07-03 12:30:59 +02:00
libmount libmount: (parser) fix memory leak on error before end-of-file 2020-06-26 12:59:32 +02:00
libsmartcols libsmartcols: don't calculate with encoding on scols_table_enable_noencoding() 2020-04-22 12:24:33 +02:00
libuuid doc: libuuid/man/*: Fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
login-utils chfn: Make readline prompt for each field on a separate line 2020-06-29 11:57:26 +02:00
m4 build-sys: add missing NR underscore to UL_CHECK_SYSCALL() 2019-11-25 20:33:05 +00:00
misc-utils rename: fix regression for symlink with non-existing target 2020-07-07 16:19:15 -03:00
po po: merge changes 2020-06-09 11:49:28 +02:00
schedutils doc: schedutils/*: Fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
sys-utils unshare: (man) add note about signals on --fork 2020-07-03 13:03:58 +02:00
term-utils doc: term-utils/*: fix some warnings from "mandoc -T lint" 2020-06-15 11:28:01 +02:00
tests tests: turn off detect_leaks on s390x, use more asan options 2020-07-03 13:26:08 +00:00
text-utils col: fix output when first line does not have newline character 2020-06-20 22:17:30 +01:00
tools build-sys: add --with-cryptsetup to config-gen.d/all.conf 2019-12-05 14:57:50 +01:00
.editorconfig add .editorconfig 2016-01-25 00:12:14 +01:00
.gitignore lsirq: add new command 2020-03-06 16:21:10 +01:00
.travis-functions.sh Merge branch 'werror' of https://github.com/evverx/util-linux 2020-07-03 11:34:12 +02:00
.travis.yml travis: build util-linux on arm64, ppc64le and s390x 2020-07-02 08:08:41 +00:00
AUTHORS docs: update AUTHORS file 2020-06-09 11:51:51 +02:00
COPYING docs: corrections to FSF license files, and postal address 2012-02-24 14:13:35 +01:00
ChangeLog docs: Correct ChangeLog URL to history log. 2020-05-11 09:48:43 +02:00
Makefile.am build-sys: add --enable-ubsan to make it possible to build util-linux with UBSan 2020-07-03 11:17:53 +02:00
NEWS build-sys: release++ (v2.36-rc1) 2020-06-09 15:13:48 +02:00
README docs: add link to mail list archive 2018-12-17 10:16:22 +01:00
README.licensing docs: add GPLv3 text 2019-11-08 11:10:54 +01:00
autogen.sh build-sys: improve bison version detection 2018-04-30 09:43:32 +02:00
configure.ac build-sys: add --enable-ubsan to make it possible to build util-linux with UBSan 2020-07-03 11:17:53 +02:00
util-linux.doap docs: replace FTP by HTTPS in kernel.org URLs 2016-12-19 11:22:26 +01:00

README

				  util-linux

		util-linux is a random collection of Linux utilities

     Note: for the years 2006-2010 this project was named "util-linux-ng".

MAILING LIST:

      E-MAIL:  util-linux@vger.kernel.org
      URL:     http://vger.kernel.org/vger-lists.html#util-linux
      ARCHIVE: https://lore.kernel.org/util-linux/

      The mailing list will reject email messages that contain:
       - more than 100K characters
       - html
       - spam phrases/keywords
      See: http://vger.kernel.org/majordomo-info.html#taboo

IRC CHANNEL:

      #util-linux at freenode.net:

      irc://chat.freenode.net/util-linux

      The IRC channel and Mailing list are for developers and project
      maintainers. For end users it is recommended to utilize the
      distribution's support system.

BUG REPORTING:

      E-MAIL: util-linux@vger.kernel.org
      Web:    https://github.com/karelzak/util-linux/issues

      This project has no resources to provide support for distribution specific
      issues. For end users it is recommended to utilize the distribution's
      support system.

NLS (PO TRANSLATIONS):

      PO files are maintained by:
	  http://translationproject.org/domain/util-linux.html

VERSION SCHEMA:

      Standard releases:
	  <major>.<minor>[.<maint>]
	     major = fatal and deep changes
	     minor = typical release with new features
	     maint = maintenance releases; bug fixes only

      Development releases:
	 <major>.<minor>-rc<N>

SOURCE CODE:

 Download archive:
	  https://www.kernel.org/pub/linux/utils/util-linux/

 SCM (Source Code Management) Repository:

    Primary repository:
	  git clone git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git

    Backup repository:
	  git clone git://github.com/karelzak/util-linux.git

    Web interfaces:
	  http://git.kernel.org/cgit/utils/util-linux/util-linux.git
	  https://github.com/karelzak/util-linux

      Note: the GitHub repository may contain temporary development branches too.

      The kernel.org repository contains master (current development) and stable/*
      (maintenance) branches only. All master or stable/* changes are always pushed
      to both repositories at the same time.

    Repository Branches: 'git branch -a'
	  master branch
	   - current development
	   - the source for stable releases when deemed ready.
	   - day-to-day status is: 'it works for me'. This means that its
	     normal state is useful but not well tested.
	   - long-term development or invasive changes in active development are
	     forked into separate 'topic' branches from the tip of 'master'.

	  stable/ branches
	   - public releases
	   - branch name: stable/v<major>.<minor>.
	   - created from the 'master' branch after two or more release
	     candidates and the final public release. This means that the stable
	     releases are committed, tagged, and reachable in 'master'.
	   - these branches then become forked development branches. This means
	     that any changes made to them diverge from the 'master' branch.
	   - maintenance releases are part of, and belong to, their respective
	     stable branch. As such, they are tags(<major>.<minor>.<maint>) and
	     not branches of their own. They are not part of, visible in, or
	     have anything to do with the 'master' development branch. In git
	     terminology: maintenance releases are not reachable from 'master'.
	   - when initially cloned (as with the 'git clone' command given above)
	     these branches are created as 'remote tracking branches' and are
	     only visible by using the -a or -r options to 'git branch'. To
	     create a local branch use the desired tag with this command:
	     'git checkout -b v2.29.2 v2.29.2'

    Tags: 'git tag'
	   - a new tag object is created for every release.
	   - tag name: v<version>.
	   - all tags are signed by the maintainer's PGP key.

    Known Bugs:
	- don't use tag v2.13.1 (created and published by mistake),
	  use v2.13.1-REAL instead.

WORKFLOW EXAMPLE:

 1) development (branch: <master>)

 2) master release (tags: v2.29-rc1, v2.29-rc2, v2.29, branch: <master>)

 3) development (work on v2.30, branch: <master>)

 4) fork -- create a new branch <stable/v2.29> based on tag v2.29

     4a) new patches or cherry-pick patches from <master> (branch: <stable/v2.29>)

     4b) stable release (tag: v2.29.1, branch: <stable/v2.29>)

     4c) more patches; another release (tag: v2.29.2, branch: <stable/v2.29>)

 5) master release v2.30 (branch: <master>)
    ...

where 3) and 4) happen simultaneously.