Track read-only handle fallback to report accurate write permission errors instead of EBADF

This commit is contained in:
Andrea Mazzoleni 2026-08-14 11:40:15 +02:00
parent 05778a9a46
commit 59f3086841
2 changed files with 27 additions and 0 deletions

View file

@ -32,6 +32,7 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in
/* initial values, changed later if required */
handle->created = 0;
handle->readonly_errno = 0;
/*
* Flags for opening
@ -45,8 +46,12 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in
/* if failed for missing write permission */
if (handle->f == -1 && (errno == EACCES || errno == EROFS)) {
int saved_errno = errno;
/* open for read-only */
handle->f = open(handle->path, flags | O_RDONLY);
if (handle->f != -1) {
handle->readonly_errno = saved_errno;
}
}
/* if failed for missing file */
@ -109,6 +114,16 @@ int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file)
{
int ret;
if (handle->readonly_errno != 0) {
if (file->size == handle->st.st_size)
return 0;
/* LCOV_EXCL_START */
errno = handle->readonly_errno;
log_fatal(errno, "Failed to truncate file '%s' for missing write permission. %s.\n", handle->path, strerror(errno));
return -1;
/* LCOV_EXCL_STOP */
}
ret = ftruncate(handle->f, file->size);
if (ret != 0) {
/* LCOV_EXCL_START */
@ -145,6 +160,7 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int
/* for sure not created */
handle->created = 0;
handle->readonly_errno = 0;
/*
* Flags for opening
@ -220,6 +236,7 @@ int handle_close(struct snapraid_handle* handle)
handle->file = 0;
handle->f = -1;
handle->valid_size = 0;
handle->readonly_errno = 0;
return 0;
}
@ -304,6 +321,14 @@ int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned
ssize_t count;
int ret;
if (handle->readonly_errno != 0) {
/* LCOV_EXCL_START */
errno = handle->readonly_errno;
log_fatal(errno, "Failed to write file '%s' for missing write permission. %s.\n", handle->path, strerror(errno));
return -1;
/* LCOV_EXCL_STOP */
}
offset = file_pos * (data_off_t)block_size;
write_size = file_block_size(handle->file, file_pos, block_size);
@ -390,6 +415,7 @@ struct snapraid_handle* handle_mapping(struct snapraid_state* state, unsigned* h
handle[j].file = 0;
handle[j].f = -1;
handle[j].valid_size = 0;
handle[j].readonly_errno = 0;
handle[j].bw = 0;
}

View file

@ -20,6 +20,7 @@ struct snapraid_handle {
struct advise_struct advise; /**< Advise information. */
data_off_t valid_size; /**< Size of the valid data. */
int created; /**< If the file was created, otherwise it was already existing. */
int readonly_errno; /**< Non-zero if opened read-only as fallback. */
struct snapraid_bw* bw; /**< Context for bandwidth limiting. */
};