From: Collin Funk Date: Sun, 10 Aug 2025 00:53:29 +0000 (-0700) Subject: realpath: support the -E option required by POSIX X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=HEAD;p=thirdparty%2Fcoreutils.git realpath: support the -E option required by POSIX * src/realpath.c (longopts): Add the option. (main): Likewise. (usage): Add the option to the --help message. * tests/misc/realpath.sh: Add a simple test. * doc/coreutils.texi (realpath invocation): Mention the new option. * NEWS: Likewise. --- diff --git a/NEWS b/NEWS index f80d0150e6..e4575d0db7 100644 --- a/NEWS +++ b/NEWS @@ -80,6 +80,10 @@ GNU coreutils NEWS -*- outline -*- basenc supports the --base58 option to encode and decode the visually unambiguous Base58 encoding. + realpath supports the -E option as required by POSIX. The behavior is + the same as realpath with no options. The corresponding long option + is --canonicalize. + ** Improvements 'factor' is now much faster at identifying large prime numbers, diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 596cdbf4fe..4f54770ec9 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -15006,8 +15006,7 @@ Exit status: @findex realpath @command{realpath} expands all symbolic links and resolves references to -@samp{/./}, @samp{/../} and extra @samp{/} characters. By default, -all but the last component of the specified files must exist. Synopsis: +@samp{/./}, @samp{/../} and extra @samp{/} characters. Synopsis: @example realpath [@var{option}]@dots{} @var{file}@dots{} @@ -15022,6 +15021,17 @@ The program accepts the following options. Also see @ref{Common options}. @table @samp +@item -E +@itemx --canonicalize +@opindex -E +@opindex --canonicalize + +Ensure all but the last component of the specified file name exist. +Otherwise, @command{realpath} will output a diagnostic unless the +@option{-q} option is specified, and exit with a nonzero exit code. A +trailing slash is ignored. This option is the default behavior, but is +included for POSIX compatibility. + @item -e @itemx --canonicalize-existing @opindex -e diff --git a/src/realpath.c b/src/realpath.c index 4bc00edc21..1f7882b493 100644 --- a/src/realpath.c +++ b/src/realpath.c @@ -44,6 +44,7 @@ static char const *can_relative_base; static struct option const longopts[] = { + {"canonicalize", no_argument, nullptr, 'E'}, {"canonicalize-existing", no_argument, nullptr, 'e'}, {"canonicalize-missing", no_argument, nullptr, 'm'}, {"relative-to", required_argument, nullptr, RELATIVE_TO_OPTION}, @@ -68,11 +69,11 @@ usage (int status) { printf (_("Usage: %s [OPTION]... FILE...\n"), program_name); fputs (_("\ -Print the resolved absolute file name;\n\ -all but the last component must exist\n\ -\n\ +Print the resolved absolute file name.\n\ "), stdout); fputs (_("\ + -E, --canonicalize all but the last component must exist (default)\ +\n\ -e, --canonicalize-existing all components of the path must exist\n\ -m, --canonicalize-missing no path components need exist or be a directory\ \n\ @@ -186,11 +187,15 @@ main (int argc, char **argv) while (true) { - int c = getopt_long (argc, argv, "eLmPqsz", longopts, nullptr); + int c = getopt_long (argc, argv, "EeLmPqsz", longopts, nullptr); if (c == -1) break; switch (c) { + case 'E': + can_mode &= ~CAN_MODE_MASK; + can_mode |= CAN_ALL_BUT_LAST; + break; case 'e': can_mode &= ~CAN_MODE_MASK; can_mode |= CAN_EXISTING; diff --git a/tests/misc/realpath.sh b/tests/misc/realpath.sh index 2356cac58b..3ba9bd36c1 100755 --- a/tests/misc/realpath.sh +++ b/tests/misc/realpath.sh @@ -50,6 +50,9 @@ returns_ 1 realpath --relative-base . || fail=1 returns_ 1 realpath -e --relative-to=dir1/f --relative-base=. . || fail=1 realpath -e --relative-to=dir1/ --relative-base=. . || fail=1 +# Check that using -E after -e uses -E as specified by POSIX. +realpath -e -E --relative-to=dir1/f --relative-base=. . || fail=1 + # Note NUL params are unconditionally rejected by canonicalize_filename_mode returns_ 1 realpath -m '' || fail=1 returns_ 1 realpath --relative-base= --relative-to=. . || fail=1