Fix touching of files that in Windows have the read-only attribute set

This commit is contained in:
Andrea Mazzoleni 2026-06-09 12:41:47 +02:00
parent abcea4d9f3
commit e4aa186b1a
4 changed files with 57 additions and 0 deletions

View file

@ -1,6 +1,12 @@
SnapRAID HISTORY
================
14.7 2026/06
============
* Fix the 'touch' command on Windows for files with the read-only
attribute. The read-only attribute is temporarily removed and
then restored. No need to update if you are not on Windows.
14.6 2026/06
============
* Fix stack overflow in deep directory trees on platforms with a small

View file

@ -766,6 +766,31 @@ int windows_fstat(int fd, struct windows_stat* st)
return windows_info2stat(&info, &tag, st);
}
int windows_get_file_attributes(const char* file)
{
wchar_t conv_buf[CONV_MAX];
DWORD ret = GetFileAttributesW(convert(conv_buf, file));
if (ret == INVALID_FILE_ATTRIBUTES) {
windows_errno(GetLastError());
return -1;
}
return ret;
}
int windows_set_file_attributes(const char* file, int attributes)
{
wchar_t conv_buf[CONV_MAX];
if (!SetFileAttributesW(convert(conv_buf, file), attributes)) {
windows_errno(GetLastError());
return -1;
}
return 0;
}
int windows_lstat(const char* file, struct windows_stat* st)
{
wchar_t conv_buf[CONV_MAX];

View file

@ -381,6 +381,16 @@ ssize_t windows_pwrite(int f, const void* buffer, size_t size, off_t offset);
*/
size_t windows_direct_size(void);
/**
* Like GetFileAttributes()
*/
int windows_get_file_attributes(const char* file);
/**
* Like SetFileAttributes()
*/
int windows_set_file_attributes(const char* file, int attributes);
/****************************************************************************/
/* thread */

View file

@ -63,6 +63,22 @@ void state_touch(struct snapraid_state* state)
/* open it */
f = open(path, flags);
#ifdef _WIN32
if (f == -1) {
/* LCOV_EXCL_START */
if (errno == EACCES) {
int attributes = windows_get_file_attributes(path);
if (attributes != -1 && (attributes & FILE_ATTRIBUTE_READONLY) != 0) {
/* remove read only attribute */
if (windows_set_file_attributes(path, attributes & ~FILE_ATTRIBUTE_READONLY) == 0) {
f = open(path, flags);
windows_set_file_attributes(path, attributes);
}
}
}
/* LCOV_EXCL_STOP */
}
#endif
if (f == -1) {
/* LCOV_EXCL_START */
log_error(errno, "Error opening file '%s'. %s.\n", path, strerror(errno));