| From 2041085d1a700201dc088991ca8136e7935bf42f Mon Sep 17 00:00:00 2001 |
| From: Victor Kamensky <kamensky@cisco.com> |
| Date: Wed, 21 Mar 2018 11:35:26 -0500 |
| Subject: [PATCH] sysroot: handle symbolic links with absolute name relative to |
| sysroot |
| |
| In case of symbolic link found under sysroot point to absolute path, |
| instead of trying to look for such absolute path in host system, |
| apply sysroot prefix first. |
| |
| Upstream-Status: Backport |
| Signed-off-by: Victor Kamensky <kamensky@cisco.com> |
| --- |
| util.cxx | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 76 insertions(+) |
| |
| Index: git/util.cxx |
| =================================================================== |
| --- git.orig/util.cxx |
| +++ git/util.cxx |
| @@ -441,6 +441,64 @@ split_lines(const char *buf, size_t n) |
| return lines; |
| } |
| |
| +static string |
| +follow_link(const string& name, const string& sysroot) |
| +{ |
| + char *linkname; |
| + ssize_t r; |
| + string retpath; |
| + struct stat st; |
| + |
| + const char *f = name.c_str(); |
| + |
| + lstat(f, &st); |
| + |
| + linkname = (char *) malloc(st.st_size + 1); |
| + |
| + if (linkname) |
| + { |
| + r = readlink(f, linkname, st.st_size + 1); |
| + linkname[st.st_size] = '\0'; |
| + /* |
| + * If we have non-empty sysroot and we got link that |
| + * points to absolute path name, we need to look at |
| + * this path relative to sysroot itself. access and |
| + * stat will follow symbolic links correctly only in |
| + * case with empty sysroot. |
| + */ |
| + while (r != -1 && linkname && linkname[0] == '/') |
| + { |
| + string fname1 = sysroot + linkname; |
| + const char *f1 = fname1.c_str(); |
| + if (access(f1, X_OK) == 0 |
| + && stat(f1, &st) == 0 |
| + && S_ISREG(st.st_mode)) |
| + { |
| + retpath = fname1; |
| + break; |
| + } |
| + else if (lstat(f1, &st) == 0 |
| + && S_ISLNK(st.st_mode)) |
| + { |
| + free(linkname); |
| + linkname = (char *) malloc(st.st_size + 1); |
| + if (linkname) |
| + { |
| + r = readlink(f1, linkname, st.st_size + 1); |
| + linkname[st.st_size] = '\0'; |
| + } |
| + } |
| + else |
| + { |
| + break; |
| + } |
| + } |
| + } |
| + free(linkname); |
| + |
| + return retpath; |
| +} |
| + |
| // Resolve an executable name to a canonical full path name, with the |
| // same policy as execvp(). A program name not containing a slash |
| // will be searched along the $PATH. |
| @@ -465,6 +523,14 @@ string find_executable(const string& nam |
| if (name.find('/') != string::npos) // slash in the path already? |
| { |
| retpath = sysroot + name; |
| + |
| + const char *f = retpath.c_str(); |
| + if (sysroot != "" |
| + && lstat(f, &st) == 0 |
| + && S_ISLNK(st.st_mode)) |
| + { |
| + retpath = follow_link(f, sysroot); |
| + } |
| } |
| else // Nope, search $PATH. |
| { |
| @@ -493,6 +559,16 @@ string find_executable(const string& nam |
| retpath = fname; |
| break; |
| } |
| + else if (sysroot != "" |
| + && lstat(f, &st) == 0 |
| + && S_ISLNK(st.st_mode)) |
| + { |
| + retpath = follow_link(f, sysroot); |
| + if (retpath != "") |
| + { |
| + break; |
| + } |
| + } |
| } |
| } |
| } |