summaryrefslogtreecommitdiffstats
path: root/misc
diff options
context:
space:
mode:
authorGuido Cella <guido@guidocella.xyz>2024-05-05 18:11:00 +0200
committerKacper Michajłow <kasper93@gmail.com>2024-05-05 19:37:57 +0200
commit1d640c9887f97ff0f94f4fb631aea3728589abeb (patch)
tree27ea2d0822405947dce99c2940c79a06a43f60cd /misc
parent8a61929eb8e62097cf8ef0764dba233000fd1e5f (diff)
downloadmpv-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.c53
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)