diff options
author | Guido Cella <guido@guidocella.xyz> | 2024-05-05 18:11:00 +0200 |
---|---|---|
committer | Kacper Michajłow <kasper93@gmail.com> | 2024-05-05 19:37:57 +0200 |
commit | 1d640c9887f97ff0f94f4fb631aea3728589abeb (patch) | |
tree | 27ea2d0822405947dce99c2940c79a06a43f60cd /misc | |
parent | 8a61929eb8e62097cf8ef0764dba233000fd1e5f (diff) | |
download | mpv-1d640c9887f97ff0f94f4fb631aea3728589abeb.tar.bz2 mpv-1d640c9887f97ff0f94f4fb631aea3728589abeb.tar.xz |
player: normalize paths for resuming playback
Paths like foo.mkv, ./foo.mkv .//foo.mkv, ../"$(basename
"$PWD")"/foo.mkv, and C:\foo.mkv and C:/foo.mkv on Windows, use
different config files for resuming playback, so if you quit-watch-later
and later play the same file with a different path, mpv does not resume
playback. This commit normalizes the paths on Unix to fix this.
Diffstat (limited to 'misc')
-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) |