/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
+/* Define to 1 if you have the `flock' function. */
+#undef HAVE_FLOCK
+
/* Define if you have the iconv() function and it works. */
#undef HAVE_ICONV
/* Define to 1 if you have the <sys/endian.h> header file. */
#undef HAVE_SYS_ENDIAN_H
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
AC_PROG_CC
AM_PROG_CC_C_O
-AC_CHECK_FUNCS([utimensat lutimes utime])
+AC_CHECK_FUNCS([utimensat lutimes utime flock])
AC_CHECK_HEADERS([endian.h byteswap.h sys/byteorder.h sys/endian.h \
sys/param.h machine/endian.h alloca.h stdlib.h stdarg.h \
- errno.h attr/xattr.h utime.h])
+ errno.h attr/xattr.h utime.h sys/file.h])
AM_ICONV
static const char *error_strings[] = {
[WIMLIB_ERR_SUCCESS]
= "Success",
+ [WIMLIB_ERR_ALREADY_LOCKED]
+ = "The WIM is already locked for writing",
[WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE]
= "Lookup table is compressed",
[WIMLIB_ERR_DECOMPRESSION]
static bool seeded = false;
+static void seed_random()
+{
+ srand(time(NULL) * getpid());
+ seeded = true;
+}
+
/* Fills @n bytes pointed to by @p with random alphanumeric characters. */
void randomize_char_array_with_alnum(char p[], size_t n)
{
- int r;
-
- if (!seeded) {
- srand(time(NULL));
- seeded = true;
- }
+ if (!seeded)
+ seed_random();
while (n--) {
- r = rand() % 62;
+ int r = rand() % 62;
if (r < 26)
*p++ = r + 'a';
else if (r < 52)
/* Fills @n bytes pointer to by @p with random numbers. */
void randomize_byte_array(u8 *p, size_t n)
{
- if (!seeded) {
- srand(time(NULL));
- seeded = true;
- }
+ if (!seeded)
+ seed_random();
while (n--)
*p++ = rand();
}
#include "lookup_table.h"
#include "xml.h"
-
static int print_metadata(WIMStruct *w)
{
DEBUG("Printing metadata for image %d", w->current_image);
}
/* Opens a WIM readable */
-int open_wim_readable(WIMStruct *w, const char *path)
+static int open_wim_readable(WIMStruct *w, const char *path)
{
if (w->fp != NULL)
fclose(w->fp);
return 0;
}
-/* Opens a WIM writable */
-int open_wim_writable(WIMStruct *w, const char *path,
- bool trunc, bool readable)
-{
- const char *mode;
- if (trunc)
- if (readable)
- mode = "w+b";
- else
- mode = "wb";
- else
- mode = "r+b";
-
- DEBUG("Opening `%s' read-write", path);
- wimlib_assert(w->out_fp == NULL);
- wimlib_assert(path != NULL);
- w->out_fp = fopen(path, mode);
- if (!w->out_fp) {
- ERROR_WITH_ERRNO("Failed to open `%s' for writing", path);
- return WIMLIB_ERR_OPEN;
- }
- return 0;
-}
-
/*
* Begins the reading of a WIM file; opens the file and reads its header and
* lookup table, and optionally checks the integrity.
*/
enum wimlib_error_code {
WIMLIB_ERR_SUCCESS = 0,
+ WIMLIB_ERR_ALREADY_LOCKED,
WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE,
WIMLIB_ERR_DECOMPRESSION,
WIMLIB_ERR_DELETE_STAGING_DIR,
*
* @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.
* @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().
* image, indexed starting at 1, is returned. If the keyword "all" or "*"
* was specified, ::WIMLIB_ALL_IMAGES is returned. Otherwise,
* ::WIMLIB_NO_IMAGE is returned. If @a image_name_or_num was @c NULL or
- * the empty string, ::WIM_NO_IMAGE is returned, even if one or more images
- * in @a wim has no name.
+ * the empty string, ::WIMLIB_NO_IMAGE is returned, even if one or more
+ * images in @a wim has no name.
*/
extern int wimlib_resolve_image(WIMStruct *wim, const char *image_name_or_num);
extern int select_wim_image(WIMStruct *w, int image);
extern int wim_hdr_flags_compression_type(int wim_hdr_flags);
extern int for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *));
-extern int open_wim_readable(WIMStruct *w, const char *path);
-extern int open_wim_writable(WIMStruct *w, const char *path,
- bool trunc, bool readable);
/* Internal use only */
#define WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE 0x80000000
#include <stdlib.h>
#endif
+#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK)
+#include <sys/file.h>
+#endif
+
+
static int do_fflush(FILE *fp)
{
int ret = fflush(fp);
return ret;
}
+static int open_wim_writable(WIMStruct *w, const char *path,
+ bool trunc, bool readable)
+{
+ const char *mode;
+ int ret = 0;
+ if (trunc)
+ if (readable)
+ mode = "w+b";
+ else
+ mode = "wb";
+ else
+ mode = "r+b";
+
+ DEBUG("Opening `%s' read-write", path);
+ wimlib_assert(w->out_fp == NULL);
+ wimlib_assert(path != NULL);
+ w->out_fp = fopen(path, mode);
+ if (!w->out_fp) {
+ 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 (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;
+ }
+ }
+ }
+#endif
+ return ret;
+}
+
+
static void close_wim_writable(WIMStruct *w)
{
if (w->out_fp) {