Harden pointer head writes against ENOENT races
This commit is contained in:
parent
03d970c576
commit
327812ca96
|
|
@ -471,6 +471,7 @@ static amduat_asl_pointer_error_t amduat_asl_pointer_write_head(
|
|||
const amduat_reference_t *prev_ref,
|
||||
bool has_prev) {
|
||||
char *tmp_path;
|
||||
char *parent_dir = NULL;
|
||||
size_t tmp_len;
|
||||
int tmp_fd;
|
||||
FILE *fp;
|
||||
|
|
@ -511,9 +512,22 @@ static amduat_asl_pointer_error_t amduat_asl_pointer_write_head(
|
|||
free((void *)prev_bytes.data);
|
||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
||||
}
|
||||
parent_dir = amduat_asl_pointer_parent_dir(path);
|
||||
if (parent_dir == NULL || !amduat_asl_pointer_ensure_directory(parent_dir)) {
|
||||
free(parent_dir);
|
||||
free(tmp_path);
|
||||
free((void *)ref_bytes.data);
|
||||
free((void *)prev_bytes.data);
|
||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
||||
}
|
||||
snprintf(tmp_path, tmp_len, "%s.tmp.XXXXXX", path);
|
||||
tmp_fd = mkstemp(tmp_path);
|
||||
if (tmp_fd < 0 && errno == ENOENT &&
|
||||
amduat_asl_pointer_ensure_directory(parent_dir)) {
|
||||
tmp_fd = mkstemp(tmp_path);
|
||||
}
|
||||
if (tmp_fd < 0) {
|
||||
free(parent_dir);
|
||||
free(tmp_path);
|
||||
free((void *)ref_bytes.data);
|
||||
free((void *)prev_bytes.data);
|
||||
|
|
@ -575,23 +589,25 @@ static amduat_asl_pointer_error_t amduat_asl_pointer_write_head(
|
|||
}
|
||||
|
||||
if (err == AMDUAT_ASL_POINTER_OK && rename(tmp_path, path) != 0) {
|
||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
||||
if (errno == ENOENT && amduat_asl_pointer_ensure_directory(parent_dir) &&
|
||||
rename(tmp_path, path) == 0) {
|
||||
/* Recovered after recreating parent directory. */
|
||||
} else {
|
||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
||||
}
|
||||
}
|
||||
if (err == AMDUAT_ASL_POINTER_OK) {
|
||||
char *parent_dir = amduat_asl_pointer_parent_dir(path);
|
||||
if (parent_dir != NULL) {
|
||||
if (!amduat_asl_pointer_fsync_directory(parent_dir)) {
|
||||
amduat_log(AMDUAT_LOG_WARN,
|
||||
"pointer fsync dir failed for %s", parent_dir);
|
||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
||||
}
|
||||
free(parent_dir);
|
||||
if (!amduat_asl_pointer_fsync_directory(parent_dir)) {
|
||||
amduat_log(AMDUAT_LOG_WARN,
|
||||
"pointer fsync dir failed for %s", parent_dir);
|
||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
||||
}
|
||||
}
|
||||
if (err != AMDUAT_ASL_POINTER_OK) {
|
||||
(void)remove(tmp_path);
|
||||
}
|
||||
|
||||
free(parent_dir);
|
||||
free(tmp_path);
|
||||
free((void *)ref_bytes.data);
|
||||
free((void *)prev_bytes.data);
|
||||
|
|
|
|||
Loading…
Reference in a new issue