perf buildid-cache: Fix symbolic link handling
Franck Bui-Huu [Fri, 10 Dec 2010 21:06:26 +0000 (22:06 +0100)]
This was broken since link(2) doesn't dereference symbolic
links. Instead 'filename' becomes a symbolic link to the same file
that 'name' refers to.

This had the bad effect to create dangling symlinks in the case that
even can't be removed with perf-buildid-cache(1).

LKML-Reference: <m38vzxxrql.fsf@gmail.com>
Signed-off-by: Franck Bui-Huu <fbuihuu@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

tools/perf/util/header.c

index 64a85ba..7cba055 100644 (file)
@@ -265,15 +265,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
                          const char *name, bool is_kallsyms)
 {
        const size_t size = PATH_MAX;
-       char *filename = malloc(size),
+       char *realname = realpath(name, NULL),
+            *filename = malloc(size),
             *linkname = malloc(size), *targetname;
        int len, err = -1;
 
-       if (filename == NULL || linkname == NULL)
+       if (realname == NULL || filename == NULL || linkname == NULL)
                goto out_free;
 
        len = snprintf(filename, size, "%s%s%s",
-                      debugdir, is_kallsyms ? "/" : "", name);
+                      debugdir, is_kallsyms ? "/" : "", realname);
        if (mkdir_p(filename, 0755))
                goto out_free;
 
@@ -283,7 +284,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
                if (is_kallsyms) {
                         if (copyfile("/proc/kallsyms", filename))
                                goto out_free;
-               } else if (link(name, filename) && copyfile(name, filename))
+               } else if (link(realname, filename) && copyfile(name, filename))
                        goto out_free;
        }
 
@@ -300,6 +301,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
        if (symlink(targetname, linkname) == 0)
                err = 0;
 out_free:
+       free(realname);
        free(filename);
        free(linkname);
        return err;