namedos fix for ~1 sequenced by map
All checks were successful
Source release / source-package (push) Successful in 42s

This commit is contained in:
Mario Fetka
2026-05-20 10:15:07 +02:00
parent 796b864075
commit 4c6f38869a

View File

@@ -150,14 +150,32 @@ 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)
static void dos83_build_plain_alias(const uint8 *src, uint8 *out, int out_size)
{
const char *tilde = strchr((const char *)candidate, '~');
char base[260], ext[260];
char nbase[9], next[4];
if (!tilde)
return 0;
dos83_split_name(src, base, sizeof(base), ext, sizeof(ext));
dos83_normalize_part(base, nbase, sizeof(nbase), 8);
dos83_normalize_part(ext, next, sizeof(next), 3);
return atoi(tilde + 1);
if (!*nbase)
strcpy(nbase, "FILE");
if (*next)
snprintf((char *)out, out_size, "%s.%s", nbase, next);
else
snprintf((char *)out, out_size, "%s", nbase);
}
static int dos83_same_plain_family(const uint8 *a, const uint8 *b)
{
uint8 aa[DOS83_NAME_MAX + 1];
uint8 bb[DOS83_NAME_MAX + 1];
dos83_build_plain_alias(a, aa, sizeof(aa));
dos83_build_plain_alias(b, bb, sizeof(bb));
return !strcmp((char *)aa, (char *)bb);
}
static int dos83_alias_used_in_dir(const char *dir_unix,
@@ -167,7 +185,6 @@ 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) {
@@ -179,11 +196,10 @@ static int dos83_alias_used_in_dir(const char *dir_unix,
return 0;
XDPRINTF((2,0,
"DOS83 COLLISION CHECK dir='%s' src='%s' candidate='%s' seq=%d",
"DOS83 COLLISION CHECK dir='%s' src='%s' candidate='%s'",
dir_unix ? dir_unix : "(null)",
src ? (char *)src : "(null)",
candidate ? (char *)candidate : "(null)",
candidate_seq));
candidate ? (char *)candidate : "(null)"));
while ((dirbuff = readdir(d)) != NULL) {
uint8 other[DOS83_NAME_MAX + 1];
@@ -195,51 +211,22 @@ static int dos83_alias_used_in_dir(const char *dir_unix,
if (!strcmp(dirbuff->d_name, (const char *)src))
continue;
if (dos83_is_valid_name((uint8 *)dirbuff->d_name, options)) {
strncpy((char *)other, dirbuff->d_name, sizeof(other) - 1);
other[sizeof(other) - 1] = '\0';
up_fn(other);
} 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];
if (!dos83_is_valid_name((uint8 *)dirbuff->d_name, options))
continue;
/*
* 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);
dos83_normalize_part(ext, next, sizeof(next), 3);
if (*nbase) {
if (*next)
snprintf((char *)other, sizeof(other), "%s.%s", nbase, next);
else
snprintf((char *)other, sizeof(other), "%s", nbase);
} else {
other[0] = '\0';
}
}
strncpy((char *)other, dirbuff->d_name, sizeof(other) - 1);
other[sizeof(other) - 1] = '\0';
up_fn(other);
XDPRINTF((2,0,
"DOS83 COLLISION OTHER raw='%s' alias='%s' candidate='%s'",
"DOS83 COLLISION EXISTING8 raw='%s' alias='%s' candidate='%s'",
dirbuff->d_name,
other,
candidate));
if (!strcmp((char *)other, (const char *)candidate)) {
XDPRINTF((2,0,
"DOS83 COLLISION HIT raw='%s' alias='%s' candidate='%s'",
"DOS83 COLLISION HIT EXISTING8 raw='%s' alias='%s' candidate='%s'",
dirbuff->d_name,
other,
candidate));
@@ -299,7 +286,46 @@ int dos83_build_name_in_dir(const char *dir_unix,
}
}
for (seq = 1; seq < 1000000; seq++) {
/*
* Number colliding long names by their directory order within the same
* unnumbered alias family. This gives stable ~1, ~2, ... aliases without
* comparing against hypothetical aliases of every other long filename.
*/
seq = 1;
if (dir_unix) {
DIR *d = opendir(dir_unix);
if (!d) {
if (seteuid(0)) {}
d = opendir(dir_unix);
reseteuid();
}
if (d) {
struct dirent *dirbuff;
while ((dirbuff = readdir(d)) != NULL) {
if (!dirbuff->d_ino)
continue;
if (!strcmp(dirbuff->d_name, ".") || !strcmp(dirbuff->d_name, ".."))
continue;
if (!strcmp(dirbuff->d_name, (const char *)src))
break;
if (!dos83_is_valid_name((uint8 *)dirbuff->d_name, options) &&
dos83_same_plain_family((uint8 *)dirbuff->d_name, src)) {
seq++;
XDPRINTF((2,0,
"DOS83 FAMILY PRIOR raw='%s' src='%s' seq_now=%d",
dirbuff->d_name,
src,
seq));
}
}
closedir(d);
}
}
for (; seq < 1000000; seq++) {
dos83_build_alias_candidate(src, seq, out, out_size);
if (!dir_unix || !dos83_alias_used_in_dir(dir_unix, src, out, options)) {
XDPRINTF((2,0,