1
0
mirror of https://git.savannah.gnu.org/git/coreutils.git synced 2025-07-02 21:22:27 +03:00

realpath: a new program to print the resolved path

This program is compatible with other realpath(1)
implementations, and also incorporates relpath like support,
through the --relative options.  The relpath support
was suggested by Peng Yu, who also provided an initial
implemenation of that functionality.

* AUTHORS: Add my name.
* NEWS: Mention the new command.
* README: Likewise.
* doc/coreutils.texi (realpath invocation): Add realpath info.
* man/Makefile.am (realpath.1): Add dependency.
* man/realpath.x: New template.
* man/.gitignore: Ignore generated man page.
* po/POTFILES.in: Add src/realpath.c.
* src/.gitignore: Exclude realpath.
* src/Makefile.am (EXTRA_PROGRAMS): Add realpath.
* src/realpath.c: New file.
* scripts/git-hooks/commit-msg: Add realpath to the list of prefixes.
* tests/Makefile.am (TESTS): Add misc/realpath.
* tests/misc/realpath: New file.
This commit is contained in:
Pádraig Brady
2011-12-27 00:30:23 +00:00
parent 76352c770e
commit 77ea441f79
15 changed files with 527 additions and 10 deletions

View File

@ -62,6 +62,7 @@ printf: David MacKenzie
ptx: François Pinard ptx: François Pinard
pwd: Jim Meyering pwd: Jim Meyering
readlink: Dmitry V. Levin readlink: Dmitry V. Levin
realpath: Pádraig Brady
rm: Paul Rubin, David MacKenzie, Richard M. Stallman, Jim Meyering rm: Paul Rubin, David MacKenzie, Richard M. Stallman, Jim Meyering
rmdir: David MacKenzie rmdir: David MacKenzie
runcon: Russell Coker runcon: Russell Coker

4
NEWS
View File

@ -41,6 +41,10 @@ GNU coreutils NEWS -*- outline -*-
argument, tail -f prints a warning with the FS type magic number and a argument, tail -f prints a warning with the FS type magic number and a
request to report it to the bug-reporting address. request to report it to the bug-reporting address.
** New programs
realpath: print resolved file names.
* Noteworthy changes in release 8.14 (2011-10-12) [stable] * Noteworthy changes in release 8.14 (2011-10-12) [stable]

10
README
View File

@ -11,11 +11,11 @@ The programs that can be built with this package are:
csplit cut date dd df dir dircolors dirname du echo env expand expr csplit cut date dd df dir dircolors dirname du echo env expand expr
factor false fmt fold groups head hostid hostname id install join kill factor false fmt fold groups head hostid hostname id install join kill
link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup
nproc od paste pathchk pinky pr printenv printf ptx pwd readlink rm rmdir nproc od paste pathchk pinky pr printenv printf ptx pwd readlink realpath
runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf rm rmdir runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred
sleep sort split stat stdbuf stty su sum sync tac tail tee test timeout shuf sleep sort split stat stdbuf stty su sum sync tac tail tee test
touch tr true truncate tsort tty uname unexpand uniq unlink uptime users timeout touch tr true truncate tsort tty uname unexpand uniq unlink
vdir wc who whoami yes uptime users vdir wc who whoami yes
See the file NEWS for a list of major changes in the current release. See the file NEWS for a list of major changes in the current release.

View File

@ -94,6 +94,7 @@
* ptx: (coreutils)ptx invocation. Produce permuted indexes. * ptx: (coreutils)ptx invocation. Produce permuted indexes.
* pwd: (coreutils)pwd invocation. Print working directory. * pwd: (coreutils)pwd invocation. Print working directory.
* readlink: (coreutils)readlink invocation. Print referent of a symlink. * readlink: (coreutils)readlink invocation. Print referent of a symlink.
* realpath: (coreutils)readpath invocation. Print resolved file names.
* rm: (coreutils)rm invocation. Remove files. * rm: (coreutils)rm invocation. Remove files.
* rmdir: (coreutils)rmdir invocation. Remove empty directories. * rmdir: (coreutils)rmdir invocation. Remove empty directories.
* runcon: (coreutils)runcon invocation. Run in specified SELinux CTX. * runcon: (coreutils)runcon invocation. Run in specified SELinux CTX.
@ -194,7 +195,7 @@ Free Documentation License''.
* Printing text:: echo printf yes * Printing text:: echo printf yes
* Conditions:: false true test expr * Conditions:: false true test expr
* Redirection:: tee * Redirection:: tee
* File name manipulation:: dirname basename pathchk mktemp * File name manipulation:: dirname basename pathchk mktemp realpath
* Working context:: pwd stty printenv tty * Working context:: pwd stty printenv tty
* User information:: id logname whoami groups users who * User information:: id logname whoami groups users who
* System context:: date arch nproc uname hostname hostid uptime * System context:: date arch nproc uname hostname hostid uptime
@ -381,6 +382,7 @@ File name manipulation
* dirname invocation:: Strip last file name component * dirname invocation:: Strip last file name component
* pathchk invocation:: Check file name validity and portability * pathchk invocation:: Check file name validity and portability
* mktemp invocation:: Create temporary file or directory * mktemp invocation:: Create temporary file or directory
* realpath invocation:: Print resolved file names
Working context Working context
@ -9603,7 +9605,6 @@ Set the default SELinux security context to be used for created files.
@cindex displaying value of a symbolic link @cindex displaying value of a symbolic link
@cindex canonical file name @cindex canonical file name
@cindex canonicalize a file name @cindex canonicalize a file name
@pindex realpath
@findex realpath @findex realpath
@command{readlink} may work in one of two supported modes: @command{readlink} may work in one of two supported modes:
@ -9686,8 +9687,8 @@ Report error messages.
The @command{readlink} utility first appeared in OpenBSD 2.1. The @command{readlink} utility first appeared in OpenBSD 2.1.
There is a @command{realpath} command on some systems The @command{realpath} command without options, operates like
which operates like @command{readlink} in canonicalize mode. @command{readlink} in canonicalize mode.
@exitstatus @exitstatus
@ -12354,6 +12355,7 @@ This section describes commands that manipulate file names.
* dirname invocation:: Strip last file name component. * dirname invocation:: Strip last file name component.
* pathchk invocation:: Check file name validity and portability. * pathchk invocation:: Check file name validity and portability.
* mktemp invocation:: Create temporary file or directory. * mktemp invocation:: Create temporary file or directory.
* realpath invocation:: Print resolved file names.
@end menu @end menu
@ -12707,6 +12709,119 @@ Exit status:
@end display @end display
@node realpath invocation
@section @command{realpath}: Print the resolved file name.
@pindex realpath
@cindex file names, canonicalization
@cindex symlinks, resolution
@cindex canonical file name
@cindex canonicalize a file name
@pindex realpath
@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:
@example
realpath [@var{option}]@dots{} @var{file}@dots{}
@end example
The program accepts the following options. Also see @ref{Common options}.
@table @samp
@item -e
@itemx --canonicalize-existing
@opindex -e
@opindex --canonicalize-existing
Ensure that all components of the specified file names exist.
If any component is missing or unavailable, @command{realpath} will output
a diagnostic unless the @option{-q} option is specified, and exit with a
nonzero exit code. A trailing slash requires that the name resolve to a
directory.
@item -m
@itemx --canonicalize-missing
@opindex -m
@opindex --canonicalize-missing
If any component of a specified file name is missing or unavailable,
treat it as a directory.
@item -L
@itemx --logical
@opindex -L
@opindex --logical
Symbolic links are resolved in the specified file names,
but they are resolved after any subsequent @samp{..} components are processed.
@item -P
@itemx --physical
@opindex -P
@opindex --physical
Symbolic links are resolved in the specified file names,
and they are resolved before any subsequent @samp{..} components are processed.
This is the default mode of operation.
@item -q
@itemx --quiet
@opindex -q
@opindex --quiet
Suppress diagnostic messages for specified file names.
@item -s
@itemx --strip
@itemx --no-symlinks
@opindex -s
@opindex --strip
@opindex --no-symlinks
Do not resolve symbolic links. Only resolve references to
@samp{/./}, @samp{/../} and remove extra @samp{/} characters.
When combined with the @option{-m} option, realpath operates
only on the file name, and does not touch any actual file.
@item -z
@itemx --zero
@opindex -z
@opindex --zero
Separate output items with @sc{nul} characters.
@itemx --relative-to=@var{file}
@opindex --relative-to
@cindex relpath
Print the resolved file names relative to the specified file.
Note this option honors the @option{-m} and @option{-e} options
pertaining to file existence.
@itemx --relative-base=@var{base}
@opindex --relative-base
This option is valid when used with @option{--relative-to}, and will restrict
the output of @option{--relative-to} so that relative names are output,
only when @var{file}s are descendants of @var{base}. Otherwise output the
absolute file name. Note: this option honors the @option{-m} and @option{-e}
options pertaining to file existence. For example:
@example
realpath --relative-to=/usr /tmp /usr/bin
@result{} ../tmp
@result{} bin
realpath --relative-base=/usr --relative-to=/usr /tmp /usr/bin
@result{} /tmp
@result{} bin
@end example
@end table
@cindex exit status of @command{realpath}
Exit status:
@display
0 if all file names were printed without issue.
1 otherwise.
@end display
@node Working context @node Working context
@chapter Working context @chapter Working context

1
man/.gitignore vendored
View File

@ -59,6 +59,7 @@ printf.1
ptx.1 ptx.1
pwd.1 pwd.1
readlink.1 readlink.1
realpath.1
rm.1 rm.1
rmdir.1 rmdir.1
seq.1 seq.1

View File

@ -92,6 +92,7 @@ printf.1: $(common_dep) $(srcdir)/printf.x ../src/printf.c
ptx.1: $(common_dep) $(srcdir)/ptx.x ../src/ptx.c ptx.1: $(common_dep) $(srcdir)/ptx.x ../src/ptx.c
pwd.1: $(common_dep) $(srcdir)/pwd.x ../src/pwd.c pwd.1: $(common_dep) $(srcdir)/pwd.x ../src/pwd.c
readlink.1: $(common_dep) $(srcdir)/readlink.x ../src/readlink.c readlink.1: $(common_dep) $(srcdir)/readlink.x ../src/readlink.c
realpath.1: $(common_dep) $(srcdir)/realpath.x ../src/realpath.c
rm.1: $(common_dep) $(srcdir)/rm.x ../src/rm.c rm.1: $(common_dep) $(srcdir)/rm.x ../src/rm.c
rmdir.1: $(common_dep) $(srcdir)/rmdir.x ../src/rmdir.c rmdir.1: $(common_dep) $(srcdir)/rmdir.x ../src/rmdir.c
runcon.1: $(common_dep) $(srcdir)/runcon.x ../src/runcon.c runcon.1: $(common_dep) $(srcdir)/runcon.x ../src/runcon.c

6
man/realpath.x Normal file
View File

@ -0,0 +1,6 @@
[NAME]
realpath \- print the resolved path
[DESCRIPTION]
.\" Add any additional description here
[SEE ALSO]
readlink(1), readlink(2), realpath(3)

View File

@ -99,6 +99,7 @@ src/printf.c
src/ptx.c src/ptx.c
src/pwd.c src/pwd.c
src/readlink.c src/readlink.c
src/realpath.c
src/remove.c src/remove.c
src/rm.c src/rm.c
src/rmdir.c src/rmdir.c

View File

@ -17,7 +17,7 @@ my @valid = qw(
expr factor false fmt fold groups head hostid hostname id install expr factor false fmt fold groups head hostid hostname id install
join kill link ln logname ls md5sum mkdir mkfifo mknod mktemp join kill link ln logname ls md5sum mkdir mkfifo mknod mktemp
mv nice nl nohup nproc od paste pathchk pinky pr printenv printf mv nice nl nohup nproc od paste pathchk pinky pr printenv printf
ptx pwd readlink rm rmdir runcon seq sha1sum sha224sum sha256sum ptx pwd readlink realpath rm rmdir runcon seq sha1sum sha224sum sha256sum
sha384sum sha512sum shred shuf sleep sort split stat stdbuf stty sha384sum sha512sum shred shuf sleep sort split stat stdbuf stty
su sum sync tac tail tee test timeout touch tr true truncate tsort su sum sync tac tail tee test timeout touch tr true truncate tsort
tty uname unexpand uniq unlink uptime users vdir wc who whoami yes tty uname unexpand uniq unlink uptime users vdir wc who whoami yes

1
src/.gitignore vendored
View File

@ -68,6 +68,7 @@ printf
ptx ptx
pwd pwd
readlink readlink
realpath
rm rm
rmdir rmdir
runcon runcon

View File

@ -97,6 +97,7 @@ EXTRA_PROGRAMS = \
ptx \ ptx \
pwd \ pwd \
readlink \ readlink \
realpath \
rm \ rm \
rmdir \ rmdir \
runcon \ runcon \
@ -248,6 +249,7 @@ printf_LDADD = $(LDADD)
ptx_LDADD = $(LDADD) ptx_LDADD = $(LDADD)
pwd_LDADD = $(LDADD) pwd_LDADD = $(LDADD)
readlink_LDADD = $(LDADD) readlink_LDADD = $(LDADD)
realpath_LDADD = $(LDADD)
rm_LDADD = $(LDADD) rm_LDADD = $(LDADD)
rmdir_LDADD = $(LDADD) rmdir_LDADD = $(LDADD)
runcon_LDADD = $(LDADD) runcon_LDADD = $(LDADD)
@ -373,6 +375,7 @@ du_LDADD += $(LIBICONV)
getlimits_LDADD += $(LIBICONV) getlimits_LDADD += $(LIBICONV)
printf_LDADD += $(LIBICONV) printf_LDADD += $(LIBICONV)
ptx_LDADD += $(LIBICONV) ptx_LDADD += $(LIBICONV)
realpath_LDADD += $(LIBICONV)
split_LDADD += $(LIBICONV) split_LDADD += $(LIBICONV)
stdbuf_LDADD += $(LIBICONV) stdbuf_LDADD += $(LIBICONV)
timeout_LDADD += $(LIBICONV) timeout_LDADD += $(LIBICONV)

329
src/realpath.c Normal file
View File

@ -0,0 +1,329 @@
/* realpath - print the resolved path
Copyright (C) 2011-2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Written by Pádraig Brady. */
#include <config.h>
#include <getopt.h>
#include <stdio.h>
#include <sys/types.h>
#include "system.h"
#include "canonicalize.h"
#include "error.h"
#include "quote.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "realpath"
#define AUTHORS proper_name_utf8 ("Padraig Brady", "P\303\241draig Brady")
enum
{
RELATIVE_TO_OPTION = CHAR_MAX + 1,
RELATIVE_BASE_OPTION
};
static bool verbose = true;
static bool logical;
static bool use_nuls;
static const char *can_relative_to;
static const char *can_relative_base;
static struct option const longopts[] =
{
{"canonicalize-existing", no_argument, NULL, 'e'},
{"canonicalize-missing", no_argument, NULL, 'm'},
{"relative-to", required_argument, NULL, RELATIVE_TO_OPTION},
{"relative-base", required_argument, NULL, RELATIVE_BASE_OPTION},
{"quiet", no_argument, NULL, 'q'},
{"strip", no_argument, NULL, 's' /* FIXME: deprecate in 2013 or so */},
{"no-symlinks", no_argument, NULL, 's'},
{"zero", no_argument, NULL, 'z'},
{"logical", no_argument, NULL, 'L'},
{"physical", no_argument, NULL, 'P'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
};
void
usage (int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else
{
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\
"), stdout);
fputs (_("\
-e, --canonicalize-existing all components of the path must exist\n\
-m, --canonicalize-missing no components of the path need exist\n\
-L, --logical resolve `..' components before symlinks\n\
-P, --physical resolve symlinks as encountered (default)\n\
-q, --quiet suppress most error messages\n\
--relative-to=FILE print the resolved path relative to FILE\n\
--relative-base=FILE print absolute paths unless paths below FILE\n\
-s, --strip, --no-symlinks don't expand symlinks\n\
-z, --zero separate output with NUL rather than newline\n\
\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
emit_ancillary_info ();
}
exit (status);
}
/* A wrapper around canonicalize_filename_mode(),
to call it twice when in LOGICAL mode. */
static char *
realpath_canon (const char *fname, int can_mode)
{
char *can_fname = canonicalize_filename_mode (fname, can_mode);
if (logical && can_fname) /* canonicalize again to resolve symlinks. */
{
can_mode &= ~CAN_NOLINKS;
char *can_fname2 = canonicalize_filename_mode (can_fname, can_mode);
free (can_fname);
return can_fname2;
}
return can_fname;
}
/* Test whether prefix is parent or match of path. */
static bool _GL_ATTRIBUTE_PURE
path_prefix (const char *prefix, const char *path)
{
while (*prefix && *path)
{
if (*prefix != *path)
break;
prefix++;
path++;
}
return (!*prefix && (*path == '/' || !*path));
}
/* Return the length of the longest common prefix
of PATH1 and PATH2, ensuring only full path components
are matched. Return 0 on no match. */
static int _GL_ATTRIBUTE_PURE
path_common_prefix (const char *path1, const char *path2)
{
int i = 0;
int ret = 0;
while (*path1 && *path2)
{
if (*path1 != *path2)
break;
if (*path1 == '/')
ret = i;
path1++;
path2++;
i++;
}
if (!*path1 && !*path2)
ret = i;
if (!*path1 && *path2 == '/')
ret = i;
if (!*path2 && *path1 == '/')
ret = i;
return ret;
}
/* Output the relative representation if requested. */
static bool
relpath (const char *can_fname)
{
if (can_relative_to)
{
/* Enforce --relative-base. */
if (can_relative_base)
{
if (!path_prefix (can_relative_base, can_fname)
|| !path_prefix (can_relative_base, can_relative_to))
return false;
}
/* Skip the prefix common to --relative-to and path. */
int common_index = path_common_prefix (can_relative_to, can_fname);
const char *relto_suffix = can_relative_to + common_index;
const char *fname_suffix = can_fname + common_index;
/* Replace remaining components of --relative-to with '..', to get
to a common directory. Then output the remainder of fname. */
if (*relto_suffix)
{
++relto_suffix;
printf ("%s", "..");
for (; *relto_suffix; ++relto_suffix)
{
if (*relto_suffix == '/')
printf ("%s", "/..");
}
printf ("%s", fname_suffix);
}
else
{
if (*fname_suffix)
printf ("%s", ++fname_suffix);
else
printf ("%c", '.');
}
putchar (use_nuls ? '\0' : '\n');
return true;
}
return false;
}
static bool
isdir (const char *path)
{
struct stat sb;
if (stat (path, &sb) != 0)
error (EXIT_FAILURE, errno, _("cannot stat %s"), quote (path));
return S_ISDIR (sb.st_mode);
}
static bool
process_path (const char *fname, int can_mode)
{
char *can_fname = realpath_canon (fname, can_mode);
if (!can_fname)
{
if (verbose)
error (0, errno, "%s", quote (fname));
return false;
}
if (!relpath (can_fname))
printf ("%s%c", can_fname, (use_nuls ? '\0' : '\n'));
free (can_fname);
return true;
}
int
main (int argc, char **argv)
{
bool ok = true;
int can_mode = CAN_ALL_BUT_LAST;
const char *relative_to = NULL;
const char *relative_base = NULL;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
atexit (close_stdout);
while (1)
{
int c = getopt_long (argc, argv, "eLmPqsz", longopts, NULL);
if (c == -1)
break;
switch (c)
{
case 'e':
can_mode &= ~CAN_MODE_MASK;
can_mode |= CAN_EXISTING;
break;
case 'm':
can_mode &= ~CAN_MODE_MASK;
can_mode |= CAN_MISSING;
break;
case 'L':
can_mode |= CAN_NOLINKS;
logical = true;
break;
case 's':
can_mode |= CAN_NOLINKS;
logical = false;
break;
case 'P':
can_mode &= ~CAN_NOLINKS;
logical = false;
break;
case 'q':
verbose = false;
break;
case 'z':
use_nuls = true;
break;
case RELATIVE_TO_OPTION:
relative_to = optarg;
break;
case RELATIVE_BASE_OPTION:
relative_base = optarg;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
usage (EXIT_FAILURE);
}
}
if (optind >= argc)
{
error (0, 0, _("missing operand"));
usage (EXIT_FAILURE);
}
if (relative_base && !relative_to)
{
error (0, 0, _("--relative-base requires --relative-to"));
usage (EXIT_FAILURE);
}
bool need_dir = (can_mode & CAN_MODE_MASK) == CAN_EXISTING;
if (relative_to)
{
can_relative_to = realpath_canon (relative_to, can_mode);
if (!can_relative_to)
error (EXIT_FAILURE, errno, "%s", quote (relative_to));
if (need_dir && !isdir (can_relative_to))
error (EXIT_FAILURE, ENOTDIR, "%s", quote (relative_to));
}
if (relative_base)
{
can_relative_base = realpath_canon (relative_base, can_mode);
if (!can_relative_base)
error (EXIT_FAILURE, errno, "%s", quote (relative_base));
if (need_dir && !isdir (can_relative_base))
error (EXIT_FAILURE, ENOTDIR, "%s", quote (relative_base));
}
for (; optind < argc; ++optind)
ok &= process_path (argv[optind], can_mode);
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}

View File

@ -220,6 +220,7 @@ TESTS = \
misc/printf-surprise \ misc/printf-surprise \
misc/pwd-long \ misc/pwd-long \
misc/readlink-fp-loop \ misc/readlink-fp-loop \
misc/realpath \
misc/runcon-no-reorder \ misc/runcon-no-reorder \
misc/sha1sum \ misc/sha1sum \
misc/sha1sum-vec \ misc/sha1sum-vec \

View File

@ -177,6 +177,7 @@ ln_setup () { args="$tmp_in ln-target"; }
ginstall_setup () { args="$tmp_in $tmp_in2"; } ginstall_setup () { args="$tmp_in $tmp_in2"; }
mv_setup () { args="$tmp_in $tmp_in2"; } mv_setup () { args="$tmp_in $tmp_in2"; }
mkdir_setup () { args=$tmp_dir/subdir; } mkdir_setup () { args=$tmp_dir/subdir; }
realpath_setup () { args=$tmp_in; }
rmdir_setup () { args=$tmp_dir; } rmdir_setup () { args=$tmp_dir; }
rm_setup () { args=$tmp_in; } rm_setup () { args=$tmp_in; }
shred_setup () { args=$tmp_in; } shred_setup () { args=$tmp_in; }

53
tests/misc/realpath Executable file
View File

@ -0,0 +1,53 @@
#!/bin/sh
# Validate realpath operation
# Copyright (C) 2011-2012 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
. "${srcdir=.}/init.sh"; path_prepend_ ../src
print_ver_ realpath
# Setup dir, file, symlink structure
mkdir -p dir1/dir2
ln -s dir1/dir2 ldir2
touch dir1/f dir1/dir2/f
# Basic operaion
realpath -Pqz . >/dev/null || fail=1
# --relative-base and --relative-to require params
realpath --relative-base --relative-to . && fail=1
# --relative-base requires --relative-to
realpath --relative-base=dir1 . && fail=1
# -e --relative-* require directories
realpath -e --relative-to=dir1/f --relative-base=. . && fail=1
realpath -e --relative-to=dir1/ --relative-base=. . || fail=1
# Note NUL params are unconditionally rejected by canonicalize_filename_mode
realpath -m '' && fail=1
# symlink resolution
this=$(realpath .)
test $(realpath $relative ldir2/..) = "$this/dir1" || fail=1
test $(realpath -L $relative ldir2/..) = "$this" || fail=1
test $(realpath -s $relative ldir2) = "$this/ldir2" || fail=1
# relative string handling
test $(realpath -m --relative-to=prefix prefixed/1) = '../prefixed/1' || fail=1
test $(realpath -m --relative-to=prefixed prefix/1) = '../prefix/1' || fail=1
test $(realpath -m --relative-to=prefixed prefixed/1) = '1' || fail=1
Exit $fail