summaryrefslogtreecommitdiffstats
path: root/lib/canonicalize.c
diff options
context:
space:
mode:
authorKarel Zak2016-03-24 11:51:12 +0100
committerKarel Zak2016-04-13 12:29:16 +0200
commit2238214ddc81d8ecab386d9e38d68f9357e2ad74 (patch)
tree6787fb2fb67d2b7fdac7c1e75af87828e51a6686 /lib/canonicalize.c
parentscript: use empty-slave heuristic more carefully (diff)
downloadkernel-qcow2-util-linux-2238214ddc81d8ecab386d9e38d68f9357e2ad74.tar.gz
kernel-qcow2-util-linux-2238214ddc81d8ecab386d9e38d68f9357e2ad74.tar.xz
kernel-qcow2-util-linux-2238214ddc81d8ecab386d9e38d68f9357e2ad74.zip
libmount: try absolute target before canonicalize
The path canonicalization is expensive and in many cases unwanted due to problems with readlink() on unreachable NFS and automounters. This patch add a possibility to search also by $(CWD)/<path> if the <path> is relative to reduce number of situation when we convert the path to the canonical absolute path. The common use-case: # cd /some/long/path # umount ./mountpoint old version: 15543: libmount: TAB: [0x560a99a54230]: lookup TARGET: './test' 15543: libmount: CACHE: [0x560a99a54290]: canonicalize path ./test 15543: libmount: CACHE: [0x560a99a54290]: add entry [ 1] (path): /mnt/test: ./test 15543: libmount: TAB: [0x560a99a54230]: lookup canonical TARGET: '/mnt/test' 15543: libmount: CXT: [0x560a99a54050]: umount fs: /mnt/test new version: 15597: libmount: TAB: [0xabf230]: lookup TARGET: './test' 15597: libmount: TAB: [0xabf230]: lookup absolute TARGET: '/mnt/test' 15597: libmount: CXT: [0xabf050]: umount fs: /mnt/test Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib/canonicalize.c')
-rw-r--r--lib/canonicalize.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/lib/canonicalize.c b/lib/canonicalize.c
index 49ac80246..93782e894 100644
--- a/lib/canonicalize.c
+++ b/lib/canonicalize.c
@@ -66,6 +66,47 @@ static int is_dm_devname(char *canonical, char **name)
return 1;
}
+/*
+ * This function does not cannonicalize the path! It just prepends CWD before a
+ * relative path. If the path is no relative than returns NULL. The path does
+ * not have to exist.
+ */
+char *absolute_path(const char *path)
+{
+ char cwd[PATH_MAX], *res, *p;
+ size_t psz, csz;
+
+ if (!is_relative_path(path)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (!getcwd(cwd, sizeof(cwd)))
+ return NULL;
+
+ /* simple clean up */
+ if (startswith(path, "./"))
+ path += 2;
+ else if (strcmp(path, ".") == 0)
+ path = NULL;
+
+ if (!path || !*path)
+ return strdup(cwd);
+
+ csz = strlen(cwd);
+ psz = strlen(path);
+
+ p = res = malloc(csz + 1 + psz + 1);
+ if (!res)
+ return NULL;
+
+ memcpy(p, cwd, csz);
+ p += csz;
+ *p++ = '/';
+ memcpy(p, path, psz + 1);
+
+ return res;
+}
+
char *canonicalize_path(const char *path)
{
char *canonical, *dmname;
@@ -139,7 +180,6 @@ int main(int argc, char **argv)
fprintf(stdout, "orig: %s\n", argv[1]);
fprintf(stdout, "real: %s\n", canonicalize_path(argv[1]));
-
exit(EXIT_SUCCESS);
}
#endif