realpath,readlink -f: coreutils compat, closes 11021
No binary (build failed)
—
(log yok)
| @@ -86,7 +86,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) | |
| /* NOFORK: only one alloc is allowed; must free */ | |
| if (opt & 1) { /* -f */ | |
| - | buf = xmalloc_realpath(fname); |
| + | buf = xmalloc_realpath_coreutils(fname); |
| } else { | |
| buf = xmalloc_readlink_or_warn(fname); | |
| } | |
| @@ -38,7 +38,7 @@ int realpath_main(int argc UNUSED_PARAM, char **argv) | |
| do { | |
| /* NOFORK: only one alloc is allowed; must free */ | |
| - | char *resolved_path = xmalloc_realpath(*argv); |
| + | char *resolved_path = xmalloc_realpath_coreutils(*argv); |
| if (resolved_path != NULL) { | |
| puts(resolved_path); | |
| free(resolved_path); | |
| @@ -485,6 +485,7 @@ DIR *xopendir(const char *path) FAST_FUNC; | |
| DIR *warn_opendir(const char *path) FAST_FUNC; | |
| char *xmalloc_realpath(const char *path) FAST_FUNC RETURNS_MALLOC; | |
| + | char *xmalloc_realpath_coreutils(const char *path) FAST_FUNC RETURNS_MALLOC; |
| char *xmalloc_readlink(const char *path) FAST_FUNC RETURNS_MALLOC; | |
| char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC RETURNS_MALLOC; | |
| /* !RETURNS_MALLOC: it's a realloc-like function */ | |
| @@ -122,3 +122,33 @@ char* FAST_FUNC xmalloc_realpath(const char *path) | |
| return xstrdup(realpath(path, buf)); | |
| #endif | |
| } | |
| + | |
| + | char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) |
| + | { |
| + | char *buf; |
| + | |
| + | errno = 0; |
| + | buf = xmalloc_realpath(path); |
| + | /* |
| + | * There is one case when "readlink -f" and |
| + | * "realpath" from coreutils succeed, |
| + | * even though file does not exist, such as: |
| + | * /tmp/file_does_not_exist |
| + | * (the directory must exist). |
| + | */ |
| + | if (!buf && errno == ENOENT) { |
| + | char *last_slash = strrchr(path, '/'); |
| + | if (last_slash) { |
| + | *last_slash++ = '\0'; |
| + | buf = xmalloc_realpath(path); |
| + | if (buf) { |
| + | unsigned len = strlen(buf); |
| + | buf = xrealloc(buf, len + strlen(last_slash) + 2); |
| + | buf[len++] = '/'; |
| + | strcpy(buf + len, last_slash); |
| + | } |
| + | } |
| + | } |
| + | |
| + | return buf; |
| + | } |