namedos fix for ~1 ranked
All checks were successful
Source release / source-package (push) Successful in 40s
All checks were successful
Source release / source-package (push) Successful in 40s
This commit is contained in:
191
src/namedos.c
191
src/namedos.c
@@ -178,6 +178,54 @@ static int dos83_same_plain_family(const uint8 *a, const uint8 *b)
|
||||
return !strcmp((char *)aa, (char *)bb);
|
||||
}
|
||||
|
||||
static int dos83_compute_family_rank(const char *dir_unix,
|
||||
const uint8 *src,
|
||||
int options)
|
||||
{
|
||||
DIR *d;
|
||||
struct dirent *dirbuff;
|
||||
int rank = 0;
|
||||
|
||||
if (!dir_unix)
|
||||
return 0;
|
||||
|
||||
d = opendir(dir_unix);
|
||||
if (!d) {
|
||||
if (seteuid(0)) {}
|
||||
d = opendir(dir_unix);
|
||||
reseteuid();
|
||||
}
|
||||
if (!d)
|
||||
return 0;
|
||||
|
||||
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))
|
||||
rank++;
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
return rank;
|
||||
}
|
||||
|
||||
static void dos83_build_ranked_alias(const uint8 *src,
|
||||
int rank,
|
||||
uint8 *out,
|
||||
int out_size)
|
||||
{
|
||||
if (rank <= 0)
|
||||
dos83_build_plain_alias(src, out, out_size);
|
||||
else
|
||||
dos83_build_alias_candidate(src, rank, out, out_size);
|
||||
}
|
||||
|
||||
static int dos83_alias_used_in_dir(const char *dir_unix,
|
||||
const uint8 *src,
|
||||
const uint8 *candidate,
|
||||
@@ -185,6 +233,7 @@ static int dos83_alias_used_in_dir(const char *dir_unix,
|
||||
{
|
||||
DIR *d;
|
||||
struct dirent *dirbuff;
|
||||
int src_rank = dos83_compute_family_rank(dir_unix, src, options);
|
||||
|
||||
d = opendir(dir_unix);
|
||||
if (!d) {
|
||||
@@ -196,10 +245,11 @@ 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'",
|
||||
"DOS83 COLLISION CHECK dir='%s' src='%s' candidate='%s' src_rank=%d",
|
||||
dir_unix ? dir_unix : "(null)",
|
||||
src ? (char *)src : "(null)",
|
||||
candidate ? (char *)candidate : "(null)"));
|
||||
candidate ? (char *)candidate : "(null)",
|
||||
src_rank));
|
||||
|
||||
while ((dirbuff = readdir(d)) != NULL) {
|
||||
uint8 other[DOS83_NAME_MAX + 1];
|
||||
@@ -211,27 +261,44 @@ 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))
|
||||
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);
|
||||
|
||||
strncpy((char *)other, dirbuff->d_name, sizeof(other) - 1);
|
||||
other[sizeof(other) - 1] = '\0';
|
||||
up_fn(other);
|
||||
|
||||
XDPRINTF((2,0,
|
||||
"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 EXISTING8 raw='%s' alias='%s' candidate='%s'",
|
||||
"DOS83 COLLISION EXISTING8 raw='%s' alias='%s' candidate='%s'",
|
||||
dirbuff->d_name,
|
||||
other,
|
||||
candidate));
|
||||
closedir(d);
|
||||
return 1;
|
||||
|
||||
if (!strcmp((char *)other, (const char *)candidate)) {
|
||||
closedir(d);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dos83_same_plain_family((uint8 *)dirbuff->d_name, src)) {
|
||||
int other_rank = dos83_compute_family_rank(dir_unix,
|
||||
(uint8 *)dirbuff->d_name,
|
||||
options);
|
||||
dos83_build_ranked_alias((uint8 *)dirbuff->d_name,
|
||||
other_rank,
|
||||
other,
|
||||
sizeof(other));
|
||||
|
||||
XDPRINTF((2,0,
|
||||
"DOS83 COLLISION FAMILY raw='%s' alias='%s' candidate='%s' other_rank=%d",
|
||||
dirbuff->d_name,
|
||||
other,
|
||||
candidate,
|
||||
other_rank));
|
||||
|
||||
if (!strcmp((char *)other, (const char *)candidate)) {
|
||||
closedir(d);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,9 +312,7 @@ int dos83_build_name_in_dir(const char *dir_unix,
|
||||
int out_size,
|
||||
int options)
|
||||
{
|
||||
char base[260], ext[260];
|
||||
char nbase[9], next[4];
|
||||
int seq;
|
||||
int rank;
|
||||
|
||||
if (!src || !*src || !out || out_size <= 0)
|
||||
return 0;
|
||||
@@ -265,81 +330,31 @@ int dos83_build_name_in_dir(const char *dir_unix,
|
||||
return (int)strlen((char *)out);
|
||||
}
|
||||
|
||||
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);
|
||||
rank = dos83_compute_family_rank(dir_unix, src, options);
|
||||
dos83_build_ranked_alias(src, rank, out, out_size);
|
||||
|
||||
if (*nbase) {
|
||||
if (*next)
|
||||
snprintf((char *)out, out_size, "%s.%s", nbase, next);
|
||||
else
|
||||
snprintf((char *)out, out_size, "%s", nbase);
|
||||
XDPRINTF((2,0,
|
||||
"DOS83 BUILD dir='%s' src='%s' out='%s' valid=%d rank=%d",
|
||||
dir_unix ? dir_unix : "(null)",
|
||||
src ? (char *)src : "(null)",
|
||||
out ? (char *)out : "(null)",
|
||||
dos83_is_valid_name(src, options),
|
||||
rank));
|
||||
|
||||
if (!dir_unix || !dos83_alias_used_in_dir(dir_unix, src, out, options)) {
|
||||
if (dir_unix && dos83_alias_used_in_dir(dir_unix, src, out, options)) {
|
||||
int seq = rank > 0 ? rank : 1;
|
||||
do {
|
||||
seq++;
|
||||
dos83_build_alias_candidate(src, seq, out, out_size);
|
||||
XDPRINTF((2,0,
|
||||
"DOS83 BUILD dir='%s' src='%s' out='%s' valid=%d",
|
||||
"DOS83 BUILD retry dir='%s' src='%s' out='%s' seq=%d",
|
||||
dir_unix ? dir_unix : "(null)",
|
||||
src ? (char *)src : "(null)",
|
||||
out ? (char *)out : "(null)",
|
||||
dos83_is_valid_name(src, options)));
|
||||
return (int)strlen((char *)out);
|
||||
}
|
||||
seq));
|
||||
} while (seq < 1000000 && dos83_alias_used_in_dir(dir_unix, src, out, options));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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,
|
||||
"DOS83 BUILD dir='%s' src='%s' out='%s' valid=%d",
|
||||
dir_unix ? dir_unix : "(null)",
|
||||
src ? (char *)src : "(null)",
|
||||
out ? (char *)out : "(null)",
|
||||
dos83_is_valid_name(src, options)));
|
||||
return (int)strlen((char *)out);
|
||||
}
|
||||
}
|
||||
|
||||
strncpy((char *)out, "FILE~1", out_size - 1);
|
||||
out[out_size - 1] = '\0';
|
||||
return (int)strlen((char *)out);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user