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)))
* 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
* @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().
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 */
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)
{
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;
}