From: Eric Biggers Date: Thu, 22 Nov 2012 04:42:59 +0000 (-0600) Subject: Acquire advisory lock when doing a read-write mount X-Git-Tag: v1.2.0~16 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=0abf993ee42a46139cc447f0cc610c1b3a0122dd Acquire advisory lock when doing a read-write mount --- diff --git a/src/mount.c b/src/mount.c index e130b084..1290bd54 100644 --- a/src/mount.c +++ b/src/mount.c @@ -1915,6 +1915,12 @@ WIMLIBAPI int wimlib_mount_image(WIMStruct *wim, int image, const char *dir, goto out; } + if (mount_flags & WIMLIB_MOUNT_FLAG_READWRITE) { + ret = lock_wim(wim->fp, wim->filename); + if (ret != 0) + goto out; + } + if (!(mount_flags & (WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_NONE | WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_XATTR | WIMLIB_MOUNT_FLAG_STREAM_INTERFACE_WINDOWS))) diff --git a/src/wimlib.h b/src/wimlib.h index 0b0f04bf..0ba59d45 100644 --- a/src/wimlib.h +++ b/src/wimlib.h @@ -1399,6 +1399,11 @@ extern int wimlib_join(const char **swms, unsigned num_swms, * directory in the future. Set to @c NULL. * * @return 0 on success; nonzero on error. + * @retval ::WIMLIB_ERR_ALREADY_LOCKED + * A read-write mount was requested, but an an exclusive advisory lock on + * the on-disk WIM file could not be acquired because another thread or + * process has mounted an image from the WIM read-write or is currently + * modifying the WIM in-place. * @retval ::WIMLIB_ERR_DECOMPRESSION * Could not decompress the metadata resource for @a image in @a wim. * @retval ::WIMLIB_ERR_FUSE @@ -1577,10 +1582,10 @@ extern int wimlib_open_wim(const char *wim_file, int open_flags, * @return 0 on success; nonzero on error. This function may return any value * returned by wimlib_write() as well as the following error codes: * @retval ::WIMLIB_ERR_ALREADY_LOCKED - * The append-only overwrite mode was going to be used, but an exclusive - * advisory lock on the on-disk WIM file could not be acquired, probably - * because another thread or process was calling wimlib_overwrite() on the - * same underlying on-disk file at the same time. + * The WIM was going to be modifien in-place (with no temporary file), but + * an exclusive advisory lock on the on-disk WIM file could not be acquired + * because another thread or process has mounted an image from the WIM + * read-write or is currently modifying the WIM in-place. * @retval ::WIMLIB_ERR_NO_FILENAME * @a wim corresponds to a WIM created with wimlib_create_new_wim() rather * than a WIM read with wimlib_open_wim(). diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h index 19497834..9b8c6b72 100644 --- a/src/wimlib_internal.h +++ b/src/wimlib_internal.h @@ -545,5 +545,14 @@ extern int begin_write(WIMStruct *w, const char *path, int write_flags); extern int finish_write(WIMStruct *w, int image, int write_flags, wimlib_progress_func_t progress_func); +#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK) +extern int lock_wim(FILE *fp, const char *path); +#else +static inline int lock_wim(FILE *fp, const char *path) +{ + return 0; +} +#endif + #endif /* _WIMLIB_INTERNAL_H */ diff --git a/src/write.c b/src/write.c index 773de0b7..e441b584 100644 --- a/src/write.c +++ b/src/write.c @@ -1492,6 +1492,29 @@ out: return ret; } +#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK) +int lock_wim(FILE *fp, const char *path) +{ + int ret = 0; + if (fp) { + ret = flock(fileno(fp), LOCK_EX | LOCK_NB); + if (ret != 0) { + if (errno == EWOULDBLOCK) { + ERROR("`%s' is already being modified or has been " + "mounted read-write\n" + " by another process!", path); + ret = WIMLIB_ERR_ALREADY_LOCKED; + } else { + WARNING("Failed to lock `%s': %s", + path, strerror(errno)); + ret = 0; + } + } + } + return ret; +} +#endif + static int open_wim_writable(WIMStruct *w, const char *path, bool trunc, bool readable) { @@ -1513,24 +1536,13 @@ static int open_wim_writable(WIMStruct *w, const char *path, ERROR_WITH_ERRNO("Failed to open `%s' for writing", path); return WIMLIB_ERR_OPEN; } -#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK) - if (!trunc) { - ret = flock(fileno(w->out_fp), LOCK_EX | LOCK_NB); + if (trunc) { + ret = lock_wim(w->out_fp, path); if (ret != 0) { - if (errno == EWOULDBLOCK) { - ERROR("`%s' is already being modified " - "by another process", path); - ret = WIMLIB_ERR_ALREADY_LOCKED; - fclose(w->out_fp); - w->out_fp = NULL; - } else { - WARNING("Failed to lock `%s': %s", - path, strerror(errno)); - ret = 0; - } + fclose(w->out_fp); + w->out_fp = NULL; } } -#endif return ret; }