diff -r eca455ac32c2 -r 7b0357fdb304 src/scanner.c --- a/src/scanner.c Tue Jun 30 15:49:38 2026 +0200 +++ b/src/scanner.c Tue Jun 30 15:59:40 2026 +0200 @@ -186,13 +186,15 @@ newentry->st_mode = 0; - /* Construct absolute pathname string */ + /* Construct full pathname string */ size_t dirnamelen = strlen(scanner.dir); char *filename = (char*) malloc(2+dirnamelen+newentry->displayname_len); memcpy(filename, scanner.dir, dirnamelen); - filename[dirnamelen] = settings->fileSeparator; - memcpy(filename+dirnamelen+1, entry->d_name, newentry->displayname_len); - filename[1+dirnamelen+newentry->displayname_len] = 0; + if (filename[dirnamelen - 1] != settings->fileSeparator) { + filename[dirnamelen++] = settings->fileSeparator; + } + memcpy(filename+dirnamelen, entry->d_name, newentry->displayname_len); + filename[dirnamelen+newentry->displayname_len] = 0; newentry->filename = filename; /* Obtain file extension */ @@ -429,6 +431,7 @@ #else static char fs = '/'; #endif /* _WIN32 */ + char* abspath; if (path_is_relative(path)) { if (cwdlen == 0) { get_working_dir(&cwd, &cwdlen); @@ -444,8 +447,33 @@ memcpy(result, cwd, cwdlen); memcpy(result+cwdlen, part, partlen); result[cwdlen+partlen] = '\0'; - return result; + abspath = result; } else { - return strdup(path); + abspath = strdup(path); } + /* make path canonical */ + size_t abspathlen = strlen(abspath); + char* canonical = malloc(abspathlen + 1); + size_t canonicallen = 0; + for (size_t j = 0; j < abspathlen; j++) { + canonical[canonicallen++] = abspath[j]; + if (abspath[j] == fs) { + /* collapse consecutive separators */ + while (abspath[j + 1] == fs) j++; + } else if (abspath[j] == '.') { + if (abspath[j + 1] == fs) { + /* skip '.' segments */ + canonicallen--; + j++; + } else if (abspath[j + 1] == '.' && abspath[j + 2] == fs) { + /* trace back '..' segment */ + canonicallen -= 2; + while (canonical[canonicallen - 1] != fs) canonicallen--; + j += 2; + } + } + } + canonical[canonicallen] = '\0'; + free(abspath); + return canonical; }