From 89d5cec83465d56c6ee742693f1ea07f844e2c3b Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Wed, 20 May 2026 17:53:29 +0200 Subject: [PATCH] namspace: fix parent directory used for DOS alias collisions Build DOS 8.3 aliases against the real parent directory instead of the full path of the current entry. This fixes duplicate aliases for long directories in the same parent, for example LONG_DIR and LONG_DI0. --- src/namspace.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/namspace.c b/src/namspace.c index 6bd779d..25fd4b0 100644 --- a/src/namspace.c +++ b/src/namspace.c @@ -912,10 +912,32 @@ static int build_dos_name(DIR_BASE_ENTRY *e, uint8 *fname, int size_fname) { char *parent_unix; int result; + N_NW_PATH parent_path; + int plen; if (!e || !fname || size_fname < 2) return(0); - parent_unix = alloc_nwpath2unix(&(e->nwpath), 1|2); + /* + * e->nwpath.path contains the full entry path and e->nwpath.fn points to + * the last component inside that buffer. alloc_nwpath2unix(..., 1|2) + * only gives the parent if fn is behind path. For entries directly in the + * volume root fn == path, so the old code accidentally used the entry + * itself as parent. That made collision checks local to each directory and + * both "long directory name one" and "long directory name two" became + * LONG_DIR. + */ + memcpy(&parent_path, &(e->nwpath), sizeof(parent_path)); + if (e->nwpath.fn && e->nwpath.fn > e->nwpath.path) { + plen = (int)(e->nwpath.fn - e->nwpath.path); + if (plen > 0 && e->nwpath.path[plen-1] == '/') --plen; + memcpy(parent_path.path, e->nwpath.path, plen); + parent_path.path[plen] = '\0'; + } else { + parent_path.path[0] = '\0'; + } + parent_path.fn = parent_path.path + strlen((char*)parent_path.path); + + parent_unix = alloc_nwpath2unix(&parent_path, 2); result = build_dos_83_alias(get_volume_options(e->nwpath.volume), (uint8*)parent_unix, e->nwpath.fn,