diff --git a/src/namedos.c b/src/namedos.c index 485e7e8..9cfcd72 100644 --- a/src/namedos.c +++ b/src/namedos.c @@ -150,6 +150,16 @@ static void dos83_build_alias_candidate(const uint8 *src, int seq, snprintf((char *)out, out_size, "%s%s", stem, seqbuf); } +static int dos83_candidate_sequence(const uint8 *candidate) +{ + const char *tilde = strchr((const char *)candidate, '~'); + + if (!tilde) + return 0; + + return atoi(tilde + 1); +} + static int dos83_alias_used_in_dir(const char *dir_unix, const uint8 *src, const uint8 *candidate, @@ -157,6 +167,7 @@ static int dos83_alias_used_in_dir(const char *dir_unix, { DIR *d; struct dirent *dirbuff; + int candidate_seq = dos83_candidate_sequence(candidate); d = opendir(dir_unix); if (!d) { @@ -167,6 +178,13 @@ static int dos83_alias_used_in_dir(const char *dir_unix, if (!d) return 0; + XDPRINTF((2,0, + "DOS83 COLLISION CHECK dir='%s' src='%s' candidate='%s' seq=%d", + dir_unix ? dir_unix : "(null)", + src ? (char *)src : "(null)", + candidate ? (char *)candidate : "(null)", + candidate_seq)); + while ((dirbuff = readdir(d)) != NULL) { uint8 other[DOS83_NAME_MAX + 1]; @@ -181,20 +199,23 @@ static int dos83_alias_used_in_dir(const char *dir_unix, strncpy((char *)other, dirbuff->d_name, sizeof(other) - 1); other[sizeof(other) - 1] = '\0'; up_fn(other); - - if (!strcmp((char *)other, (const char *)candidate)) { - closedir(d); - return 1; - } + } else if (candidate_seq > 0) { + /* + * When the current candidate is a numbered alias, compare other long + * filenames against the same numbered candidate. This avoids treating + * every later long filename as if only ~1 mattered. + */ + dos83_build_alias_candidate((uint8 *)dirbuff->d_name, + candidate_seq, + other, + sizeof(other)); } else { char base[260], ext[260]; char nbase[9], next[4]; /* - * First test the same unnumbered short alias that dos83_build_name_in_dir() - * tries before falling back to ~n aliases. This prevents two different long - * filenames like "long_file_name.txt" and "long_file_name_too.txt" from - * both receiving "LONG_FIL.TXT". + * For the first unnumbered probe, compare other long filenames against + * the same unnumbered short alias. */ dos83_split_name((uint8 *)dirbuff->d_name, base, sizeof(base), ext, sizeof(ext)); dos83_normalize_part(base, nbase, sizeof(nbase), 8); @@ -205,23 +226,25 @@ static int dos83_alias_used_in_dir(const char *dir_unix, snprintf((char *)other, sizeof(other), "%s.%s", nbase, next); else snprintf((char *)other, sizeof(other), "%s", nbase); - - if (!strcmp((char *)other, (const char *)candidate)) { - closedir(d); - return 1; - } + } else { + other[0] = '\0'; } + } - /* - * Also test the first numbered alias candidate. This keeps the old behavior - * for collision checks once numbering starts. - */ - dos83_build_alias_candidate((uint8 *)dirbuff->d_name, 1, other, sizeof(other)); + XDPRINTF((2,0, + "DOS83 COLLISION OTHER raw='%s' alias='%s' candidate='%s'", + dirbuff->d_name, + other, + candidate)); - if (!strcmp((char *)other, (const char *)candidate)) { - closedir(d); - return 1; - } + if (!strcmp((char *)other, (const char *)candidate)) { + XDPRINTF((2,0, + "DOS83 COLLISION HIT raw='%s' alias='%s' candidate='%s'", + dirbuff->d_name, + other, + candidate)); + closedir(d); + return 1; } }