diff options
Diffstat (limited to 'misc/path_utils.c')
-rw-r--r-- | misc/path_utils.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/misc/path_utils.c b/misc/path_utils.c index 14b4a97031..7fbd1084b8 100644 --- a/misc/path_utils.c +++ b/misc/path_utils.c @@ -151,10 +151,61 @@ char *mp_getcwd(void *talloc_ctx) char *mp_normalize_path(void *talloc_ctx, const char *path) { + if (!path) + return NULL; + if (mp_is_url(bstr0(path))) return talloc_strdup(talloc_ctx, path); - return mp_path_join(talloc_ctx, mp_getcwd(talloc_ctx), path); + if (!mp_path_is_absolute(bstr0(path))) { + char *cwd = mp_getcwd(talloc_ctx); + if (!cwd) + return NULL; + path = mp_path_join(talloc_ctx, cwd, path); + } + +#if HAVE_DOS_PATHS + return talloc_strdup(talloc_ctx, path); +#else + char *result = talloc_strdup(talloc_ctx, ""); + const char *next; + const char *end = path + strlen(path); + + for (const char *ptr = path; ptr < end; ptr = next + 1) { + next = memchr(ptr, '/', end - ptr); + if (next == NULL) + next = end; + + switch (next - ptr) { + case 0: + continue; + case 1: + if (ptr[0] == '.') + continue; + break; + case 2: + // Normalizing symlink/.. results in a wrong path: if the + // current working directory is /tmp/foo, and it is a symlink to + // /usr/bin, mpv ../file.mkv opens /usr/file.mkv, so we can't + // normalize the path to /tmp/file.mkv. Resolve symlinks to fix + // this. Otherwise we don't use realpath so users can use + // symlinks e.g. to hide how media files are distributed over + // real storage and move them while still resuming playback as + // long as the symlinked path doesn't change. + if (ptr[0] == '.' && ptr[1] == '.') { + char *tmp_result = realpath(path, NULL); + result = talloc_strdup(talloc_ctx, tmp_result); + free(tmp_result); + return result; + } + } + + result = talloc_strdup_append_buffer(result, "/"); + result = talloc_strndup_append_buffer(result, ptr, next - ptr); + } + + return result; +#endif } bool mp_path_exists(const char *path) |