summaryrefslogtreecommitdiffstats
path: root/misc/path_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc/path_utils.c')
-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)