src/scanner.c

changeset 97
7b0357fdb304
parent 96
eca455ac32c2
--- 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;
 }

mercurial