mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Use pathcmp for disk name comparisons to enforce case-insensitive uniqueness on Windows
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-arm32 (push) Waiting to run
Build / build-win (push) Waiting to run
Build / build-freebsd (push) Waiting to run
Build / build-musl (push) Waiting to run
CodeQL Advanced / Analyze (c-cpp) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-arm32 (push) Waiting to run
Build / build-win (push) Waiting to run
Build / build-freebsd (push) Waiting to run
Build / build-musl (push) Waiting to run
CodeQL Advanced / Analyze (c-cpp) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
This commit is contained in:
parent
23283e3abd
commit
a77f2a5a4c
6 changed files with 60 additions and 25 deletions
|
|
@ -567,7 +567,7 @@ struct snapraid_handle* handle_mapping(struct snapraid_state* state, unsigned* h
|
|||
map = 0;
|
||||
for (k = state->maplist; k != 0; k = k->next) {
|
||||
map = k->data;
|
||||
if (strcmp(disk->name, map->name) == 0)
|
||||
if (pathcmp(disk->name, map->name) == 0)
|
||||
break;
|
||||
}
|
||||
if (!map) {
|
||||
|
|
|
|||
|
|
@ -1930,6 +1930,24 @@ static void test_disk_name(void)
|
|||
assert(disk_name_invalid_reason("r-parity") != 0);
|
||||
assert(disk_name_invalid_reason("z-parity") != 0);
|
||||
|
||||
#ifdef _WIN32
|
||||
/* case-insensitive parity names rejected on Windows */
|
||||
assert(disk_name_invalid_reason("PARITY") != 0);
|
||||
assert(disk_name_invalid_reason("Parity") != 0);
|
||||
assert(disk_name_invalid_reason("1-PARITY") != 0);
|
||||
assert(disk_name_invalid_reason("2-PARITY") != 0);
|
||||
assert(disk_name_invalid_reason("Q-PARITY") != 0);
|
||||
assert(disk_name_invalid_reason("Z-PARITY") != 0);
|
||||
#else
|
||||
/* case-sensitive on Unix: uppercase variants are distinct from reserved lowercase parity names */
|
||||
assert(disk_name_invalid_reason("PARITY") == 0);
|
||||
assert(disk_name_invalid_reason("Parity") == 0);
|
||||
assert(disk_name_invalid_reason("1-PARITY") == 0);
|
||||
assert(disk_name_invalid_reason("2-PARITY") == 0);
|
||||
assert(disk_name_invalid_reason("Q-PARITY") == 0);
|
||||
assert(disk_name_invalid_reason("Z-PARITY") == 0);
|
||||
#endif
|
||||
|
||||
/* valid names containing parity as substring */
|
||||
assert(disk_name_invalid_reason("parity1") == 0);
|
||||
assert(disk_name_invalid_reason("parity_data") == 0);
|
||||
|
|
|
|||
|
|
@ -178,16 +178,18 @@ void log_open(const char* file)
|
|||
|
||||
void log_close(const char* file)
|
||||
{
|
||||
if (stdlog != stdout && stdlog != stderr && stdlog != 0) {
|
||||
if (fclose(stdlog) != 0) {
|
||||
FILE* log = stdlog;
|
||||
|
||||
/* fclose() invalidates the stream even on error, so fatal reporting must use stderr. */
|
||||
stdlog = 0;
|
||||
if (log != stdout && log != stderr && log != 0) {
|
||||
if (fclose(log) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(errno, "Error closing the log file '%s'. %s.\n", file, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
}
|
||||
|
||||
stdlog = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -117,6 +117,9 @@ static int lev_config_scan(const char* s, unsigned* level, unsigned* mode)
|
|||
const char* disk_name_invalid_reason(const char* name)
|
||||
{
|
||||
unsigned dummy_level;
|
||||
#ifdef _WIN32
|
||||
char lower[DISK_NAME_MAX + 1];
|
||||
#endif
|
||||
|
||||
if (strlen(name) > DISK_NAME_MAX)
|
||||
return "Name is too long (maximum 127 bytes)";
|
||||
|
|
@ -126,8 +129,16 @@ const char* disk_name_invalid_reason(const char* name)
|
|||
return "Name contains '\\'";
|
||||
if (strchr(name, ':') != 0)
|
||||
return "Name contains ':'";
|
||||
|
||||
#ifdef _WIN32
|
||||
pathcpy(lower, sizeof(lower), name);
|
||||
strlwr(lower);
|
||||
if (lev_config_scan(lower, &dummy_level, 0) == 0)
|
||||
return "Name is a reserved parity name";
|
||||
#else
|
||||
if (lev_config_scan(name, &dummy_level, 0) == 0)
|
||||
return "Name is a reserved parity name";
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1081,7 +1092,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
/* check if the disk name already exists */
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
disk = i->data;
|
||||
if (strcmp(disk->name, buffer) == 0)
|
||||
if (pathcmp(disk->name, buffer) == 0)
|
||||
break;
|
||||
}
|
||||
if (i) {
|
||||
|
|
@ -1093,7 +1104,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
|
||||
for (i = state->extralist; i != 0; i = i->next) {
|
||||
struct snapraid_extra* found_extra = i->data;
|
||||
if (strcmp(found_extra->name, buffer) == 0)
|
||||
if (pathcmp(found_extra->name, buffer) == 0)
|
||||
break;
|
||||
}
|
||||
if (i) {
|
||||
|
|
@ -1203,7 +1214,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
/* check if the disk name already exists */
|
||||
for (i = state->extralist; i != 0; i = i->next) {
|
||||
extra = i->data;
|
||||
if (strcmp(extra->name, buffer) == 0)
|
||||
if (pathcmp(extra->name, buffer) == 0)
|
||||
break;
|
||||
}
|
||||
if (i) {
|
||||
|
|
@ -1215,7 +1226,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* found_disk = i->data;
|
||||
if (strcmp(found_disk->name, buffer) == 0)
|
||||
if (pathcmp(found_disk->name, buffer) == 0)
|
||||
break;
|
||||
}
|
||||
if (i) {
|
||||
|
|
@ -1316,7 +1327,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
struct snapraid_disk* found_disk = 0;
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
if (strcmp(disk->name, buffer) == 0) {
|
||||
if (pathcmp(disk->name, buffer) == 0) {
|
||||
found_disk = disk;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1324,7 +1335,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
struct snapraid_extra* found_extra = 0;
|
||||
for (i = state->extralist; i != 0; i = i->next) {
|
||||
struct snapraid_extra* extra = i->data;
|
||||
if (strcmp(extra->name, buffer) == 0) {
|
||||
if (pathcmp(extra->name, buffer) == 0) {
|
||||
found_extra = extra;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1385,7 +1396,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
struct snapraid_disk* found_disk = 0;
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
if (strcmp(disk->name, buffer) == 0) {
|
||||
if (pathcmp(disk->name, buffer) == 0) {
|
||||
found_disk = disk;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1393,7 +1404,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
struct snapraid_extra* found_extra = 0;
|
||||
for (i = state->extralist; i != 0; i = i->next) {
|
||||
struct snapraid_extra* extra = i->data;
|
||||
if (strcmp(extra->name, buffer) == 0) {
|
||||
if (pathcmp(extra->name, buffer) == 0) {
|
||||
found_extra = extra;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1705,7 +1716,7 @@ static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, con
|
|||
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
if (strcmp(disk->name, name) == 0)
|
||||
if (pathcmp(disk->name, name) == 0)
|
||||
return disk;
|
||||
}
|
||||
|
||||
|
|
@ -1804,7 +1815,7 @@ static void state_map(struct snapraid_state* state)
|
|||
/* check if the disk is already mapped */
|
||||
for (j = state->maplist; j != 0; j = j->next) {
|
||||
map = j->data;
|
||||
if (strcmp(disk->name, map->name) == 0) {
|
||||
if (pathcmp(disk->name, map->name) == 0) {
|
||||
/* mapping found */
|
||||
break;
|
||||
}
|
||||
|
|
@ -2096,7 +2107,7 @@ static void state_content_check(struct snapraid_state* state, const char* path)
|
|||
tommy_node* j;
|
||||
for (j = i->next; j != 0; j = j->next) {
|
||||
struct snapraid_map* other = j->data;
|
||||
if (strcmp(map->name, other->name) == 0) {
|
||||
if (pathcmp(map->name, other->name) == 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(ECONTENT, "Conflicting 'map' disk specification in '%s'\n", path);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
|
|||
|
|
@ -375,27 +375,31 @@ static void msg(FILE* out, const char* format, ...)
|
|||
|
||||
void vlog_fatal(int err, const char* format, va_list ap, const char* post)
|
||||
{
|
||||
int log_failed = 0;
|
||||
|
||||
lock_msg();
|
||||
|
||||
if (stdlog) {
|
||||
if (is_hw(err))
|
||||
fprintf(stdlog, "msg:fatal_hardware: ");
|
||||
log_failed = fprintf(stdlog, "msg:fatal_hardware: ") < 0;
|
||||
else
|
||||
fprintf(stdlog, "msg:fatal: ");
|
||||
log_failed = fprintf(stdlog, "msg:fatal: ") < 0;
|
||||
|
||||
va_list ap_copy;
|
||||
va_copy(ap_copy, ap);
|
||||
vfprintf(stdlog, format, ap_copy);
|
||||
if (vfprintf(stdlog, format, ap_copy) < 0)
|
||||
log_failed = 1;
|
||||
va_end(ap_copy);
|
||||
|
||||
if (post)
|
||||
fprintf(stdlog, "%s", post);
|
||||
if (post && fprintf(stdlog, "%s", post) < 0)
|
||||
log_failed = 1;
|
||||
|
||||
fflush(stdlog);
|
||||
if (fflush(stdlog) != 0)
|
||||
log_failed = 1;
|
||||
}
|
||||
|
||||
/* GUI consumers read tagged fatal messages from the log and must not receive a duplicate raw copy. */
|
||||
if (!stdlog || msg_fatal_stderr) {
|
||||
/* A failed tagged write must retain stderr as the only usable fatal diagnostic. */
|
||||
if (!stdlog || log_failed || msg_fatal_stderr) {
|
||||
va_list ap_copy2;
|
||||
va_copy(ap_copy2, ap);
|
||||
vmsg(stderr, format, ap_copy2);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ typedef void log_ptr(int err, const char* format, ...) __attribute__((format(att
|
|||
* Messages printed before an early termination.
|
||||
*
|
||||
* These messages go in the log file and in stderr, except in GUI mode
|
||||
* when a log is configured, where only the tagged log message is emitted.
|
||||
* when the tagged log message is emitted successfully.
|
||||
*/
|
||||
void vlog_fatal(int err, const char* format, va_list ap, const char* post);
|
||||
void log_fatal(int err, const char* format, ...) __attribute__((format(attribute_printf, 2, 3)));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue