]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Fix path canonicalization in make_relative_path when path doesn't exist
authorJoel Rosdahl <joel@rosdahl.net>
Thu, 8 Aug 2013 16:06:16 +0000 (18:06 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 8 Aug 2013 16:06:16 +0000 (18:06 +0200)
ccache.c
test/test_argument_processing.c

index 38652e12b6051906febe149eaaf45cd90e06bce7..c02868fcfa75f15396258084ae620342a27715c3 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -387,12 +387,14 @@ ignore:
 static char *
 make_relative_path(char *path)
 {
-       char *relpath, *canon_path;
+       char *relpath, *canon_path, *path_suffix = NULL;
+       struct stat st;
 
        if (!base_dir || !str_startswith(path, base_dir)) {
                return path;
        }
 
+       /* Look up CWD and cache it in the global current_working_dir variable. */
        if (!current_working_dir) {
                char *cwd = get_cwd();
                if (cwd) {
@@ -406,17 +408,43 @@ make_relative_path(char *path)
                }
        }
 
+       /* x_realpath only works for existing paths, so if path doesn't exist, try
+        * dirname(path) and assemble the path afterwards. We only bother to try
+        * canonicalizing one of these two paths since a compiler path argument
+        * typically only makes sense if path or dirname(path) exists. */
+       if (stat(path, &st) != 0) {
+               /* path doesn't exist. */
+               char *dir, *p;
+               dir = dirname(path);
+               if (stat(dir, &st) != 0) {
+                       /* And neither does its parent directory, so no action to take. */
+                       free(dir);
+                       return path;
+               }
+               path_suffix = basename(path);
+               p = path;
+               path = dirname(path);
+               free(p);
+       }
+
        canon_path = x_realpath(path);
        if (canon_path) {
                free(path);
-               path = canon_path;
+               relpath = get_relative_path(current_working_dir, canon_path);
+               free(canon_path);
+               if (path_suffix) {
+                       path = format("%s/%s", relpath, path_suffix);
+                       free(relpath);
+                       free(path_suffix);
+                       return path;
+               } else {
+                       return relpath;
+               }
        } else {
                /* path doesn't exist, so leave it as it is. */
+               free(path_suffix);
+               return path;
        }
-
-       relpath = get_relative_path(current_working_dir, path);
-       free(path);
-       return relpath;
 }
 
 /*
index 94e46f4ffd7c72bd84d0a31deaf4185d469f8530..6ed0daa8ea01f3792e9ce477916159419c7ea9ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2012 Joel Rosdahl
+ * Copyright (C) 2010-2013 Joel Rosdahl
  *
  * 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
@@ -90,20 +90,19 @@ TEST(sysroot_should_be_rewritten_if_basedir_is_used)
 {
        extern char *base_dir;
        extern char *current_working_dir;
-       struct args *orig =
-               args_init_from_string("cc --sysroot=/some/directory -c foo.c");
+       char *arg_string;
+       struct args *orig;
        struct args *act_cpp = NULL, *act_cc = NULL;
-       create_file("foo.c", "");
-
-       CHECK(cc_process_args(orig, &act_cpp, &act_cc));
-       CHECK_STR_EQ(act_cpp->argv[1], "--sysroot=/some/directory");
 
-       cc_reset();
-       base_dir = "/some";
+       create_file("foo.c", "");
        current_working_dir = get_cwd();
+       arg_string = format("cc --sysroot=%s/foo -c foo.c", current_working_dir);
+       orig = args_init_from_string(arg_string);
+
+       base_dir = "/";
 
        CHECK(cc_process_args(orig, &act_cpp, &act_cc));
-       CHECK(str_startswith(act_cpp->argv[1], "--sysroot=../"));
+       CHECK(str_startswith(act_cpp->argv[1], "--sysroot=./foo"));
 
        args_free(orig);
        base_dir = NULL;