summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2012-03-14 13:42:59 -0600
committerEric Blake <eblake@redhat.com>2012-03-15 13:28:19 -0600
commitbe17e3b98a178ea6e2c973bf49282f11f7060353 (patch)
treefc13d79392e4c5e416a9838b33c6f8f5e14f2d1a
parent9f5aa4850133976eee22dcc0b506d7b632cd674c (diff)
downloadcoreutils-be17e3b98a178ea6e2c973bf49282f11f7060353.tar.gz
realpath: optimize --relative-base usage
There is no need to recompute for every path being visited whether the base is a prefix of the relative location. * src/realpath.c (relpath): Hoist base check... (main): ...here. Based on a suggestion by Pádraig Brady.
-rw-r--r--src/realpath.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/src/realpath.c b/src/realpath.c
index f95535b12..206f8006d 100644
--- a/src/realpath.c
+++ b/src/realpath.c
@@ -179,12 +179,8 @@ 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;
- }
+ if (can_relative_base && !path_prefix (can_relative_base, can_fname))
+ return false;
/* Skip the prefix common to --relative-to and path. */
int common_index = path_common_prefix (can_relative_to, can_fname);
@@ -341,13 +337,25 @@ main (int argc, char **argv)
if (need_dir && !isdir (can_relative_to))
error (EXIT_FAILURE, ENOTDIR, "%s", quote (relative_to));
}
- if (relative_base)
+ if (relative_base == relative_to)
+ can_relative_base = can_relative_to;
+ else if (relative_base)
{
- can_relative_base = realpath_canon (relative_base, can_mode);
- if (!can_relative_base)
+ char *base = realpath_canon (relative_base, can_mode);
+ if (!base)
error (EXIT_FAILURE, errno, "%s", quote (relative_base));
- if (need_dir && !isdir (can_relative_base))
+ if (need_dir && !isdir (base))
error (EXIT_FAILURE, ENOTDIR, "%s", quote (relative_base));
+ /* --relative-to is a no-op if it does not have --relative-base
+ as a prefix */
+ if (path_prefix (base, can_relative_to))
+ can_relative_base = base;
+ else
+ {
+ free (base);
+ can_relative_base = can_relative_to;
+ can_relative_to = NULL;
+ }
}
for (; optind < argc; ++optind)