mdbx: refine handling EACCESS while trying create LCK-file on a read-only filesystem.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2022-06-04 02:04:55 +03:00
parent a4da10bc62
commit d1e67645a2
2 changed files with 39 additions and 14 deletions

View File

@ -12440,17 +12440,29 @@ __cold static int mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
int err = mdbx_openfile(MDBX_OPEN_LCK, env, lck_pathname, &env->me_lfd, mode);
if (err != MDBX_SUCCESS) {
if (!(err == MDBX_ENOFILE && (env->me_flags & MDBX_EXCLUSIVE)) &&
!((err == MDBX_EROFS || err == MDBX_EACCESS || err == MDBX_EPERM) &&
(env->me_flags & MDBX_RDONLY)))
switch (err) {
default:
return err;
case MDBX_ENOFILE:
case MDBX_EACCESS:
case MDBX_EPERM:
if (!F_ISSET(env->me_flags, MDBX_RDONLY | MDBX_EXCLUSIVE))
return err;
break;
case MDBX_EROFS:
if ((env->me_flags & MDBX_RDONLY) == 0)
return err;
break;
}
/* ensure the file system is read-only */
err = mdbx_check_fs_rdonly(env->me_lazy_fd, lck_pathname, err);
if (err != MDBX_SUCCESS &&
/* ignore ERROR_NOT_SUPPORTED for exclusive mode */
!(err == MDBX_ENOSYS && (env->me_flags & MDBX_EXCLUSIVE)))
return err;
if (err != MDBX_ENOFILE) {
/* ensure the file system is read-only */
err = mdbx_check_fs_rdonly(env->me_lazy_fd, lck_pathname, err);
if (err != MDBX_SUCCESS &&
/* ignore ERROR_NOT_SUPPORTED for exclusive mode */
!(err == MDBX_ENOSYS && (env->me_flags & MDBX_EXCLUSIVE)))
return err;
}
/* LY: without-lck mode (e.g. exclusive or on read-only filesystem) */
/* beginning of a locked section ---------------------------------------- */

View File

@ -610,8 +610,15 @@ MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
*fd = CreateFileW(pathnameW, DesiredAccess, ShareMode, NULL,
CreationDisposition, FlagsAndAttributes, NULL);
if (*fd == INVALID_HANDLE_VALUE)
return (int)GetLastError();
if (*fd == INVALID_HANDLE_VALUE) {
int err = (int)GetLastError();
if (err == ERROR_ACCESS_DENIED && purpose == MDBX_OPEN_LCK) {
if (GetFileAttributesW(pathnameW) == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND)
err = ERROR_FILE_NOT_FOUND;
}
return err;
}
BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle(*fd, &info)) {
@ -706,6 +713,12 @@ MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
}
#endif /* O_DIRECT */
if (*fd < 0 && errno == EACCES && purpose == MDBX_OPEN_LCK) {
struct stat unused;
if (stat(pathname, &unused) == 0 || errno != ENOENT)
errno = EACCES /* restore errno if file exists */;
}
/* Safeguard for todo4recovery://erased_by_github/libmdbx/issues/144 */
#if STDIN_FILENO == 0 && STDOUT_FILENO == 1 && STDERR_FILENO == 2
if (*fd == STDIN_FILENO) {
@ -1091,10 +1104,10 @@ MDBX_INTERNAL_FUNC int mdbx_check_fs_rdonly(mdbx_filehandle_t handle,
#else
struct statvfs info;
if (err != MDBX_ENOFILE) {
if (statvfs(pathname, &info))
return errno;
if ((info.f_flag & ST_RDONLY) == 0)
if (statvfs(pathname, &info) == 0 && (info.f_flag & ST_RDONLY) == 0)
return err;
if (errno != MDBX_ENOFILE)
return errno;
}
if (fstatvfs(handle, &info))
return errno;