]> wimlib.net Git - wimlib/commitdiff
native fds fixes/cleanups
authorEric Biggers <ebiggers3@gmail.com>
Sun, 5 May 2013 01:47:52 +0000 (20:47 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 5 May 2013 01:47:52 +0000 (20:47 -0500)
src/header.c
src/lookup_table.c
src/resource.c
src/split.c
src/util.c
src/util.h
src/wim.c
src/wimlib_internal.h
src/win32.c
src/write.c
wimlib_tchar.h

index ff3bb95b016a8e8a8193f4fca4e265882cb9c984..2524793d5c66b89de94d45a298cde5c4647a0787 100644 (file)
 static const u8 wim_magic_chars[WIM_MAGIC_LEN] = {
                        'M', 'S', 'W', 'I', 'M', '\0', '\0', '\0' };
 
-/* Reads the header for a WIM file.  */
+/* Reads the header from a WIM file.  */
 int
 read_header(filedes_t in_fd, struct wim_header *hdr, int open_flags)
 {
        size_t bytes_read;
        u8 buf[WIM_HEADER_DISK_SIZE];
-       const u8 *p;
+       const void *p;
 
        u32 hdr_size;
        u32 wim_version;
@@ -45,35 +45,29 @@ read_header(filedes_t in_fd, struct wim_header *hdr, int open_flags)
 
        DEBUG("Reading WIM header.");
 
-       bytes_read = full_read(in_fd, buf, WIM_HEADER_DISK_SIZE);
+       bytes_read = full_pread(in_fd, buf, WIM_HEADER_DISK_SIZE, 0);
 
        if (bytes_read != WIM_HEADER_DISK_SIZE) {
                ERROR_WITH_ERRNO("Error reading WIM header");
                return WIMLIB_ERR_READ;
        }
 
-       /* Byte 8 */
-
        p = buf;
-
        if (memcmp(p, wim_magic_chars, WIM_MAGIC_LEN)) {
                ERROR("Invalid magic characters in WIM header");
                return WIMLIB_ERR_NOT_A_WIM_FILE;
        }
 
-       p += 8;
-       p = get_u32(p, &hdr_size);
-
-       /* Byte 12 */
-
+       /* Byte 8 */
+       p = get_u32(p + 8, &hdr_size);
        if (hdr_size != WIM_HEADER_DISK_SIZE) {
                ERROR("Header is %u bytes (expected %u bytes)",
                      hdr_size, WIM_HEADER_DISK_SIZE);
                return WIMLIB_ERR_INVALID_HEADER_SIZE;
        }
 
+       /* Byte 12 */
        p = get_u32(buf + WIM_MAGIC_LEN + sizeof(u32), &wim_version);
-
        if (wim_version != WIM_VERSION) {
                ERROR("The WIM header says the WIM version is %u, but wimlib "
                      "only knows about version %u",
@@ -151,7 +145,8 @@ read_header(filedes_t in_fd, struct wim_header *hdr, int open_flags)
  *
  * @hdr:       A pointer to a struct wim_header structure that describes the header.
  * @out_fd:    The file descriptor to the WIM file, opened for writing.
- * @return:    Zero on success, nonzero on failure.
+ * 
+ * Returns zero on success, nonzero on failure.
  */
 int
 write_header(const struct wim_header *hdr, int out_fd)
@@ -166,12 +161,12 @@ write_header(const struct wim_header *hdr, int out_fd)
        p = put_u32(p, hdr->flags);
        p = put_u32(p, (hdr->flags & WIM_HDR_FLAG_COMPRESSION) ?
                                WIM_CHUNK_SIZE : 0);
-       /* byte 24 */
+       /* Byte 24 */
 
        p = put_bytes(p, WIM_GID_LEN, hdr->guid);
        p = put_u16(p, hdr->part_number);
 
-       /* byte 40 */
+       /* Byte 40 */
 
        p = put_u16(p, hdr->total_parts);
        p = put_u32(p, hdr->image_count);
@@ -181,7 +176,7 @@ write_header(const struct wim_header *hdr, int out_fd)
        p = put_u32(p, hdr->boot_idx);
        p = put_resource_entry(p, &hdr->integrity);
        p = put_zeroes(p, WIM_UNUSED_LEN);
-       assert(p - buf == sizeof(buf));
+       wimlib_assert(p - buf == sizeof(buf));
 
        if (full_pwrite(out_fd, buf, sizeof(buf), 0) != sizeof(buf)) {
                ERROR_WITH_ERRNO("Failed to write WIM header");
index 24c133205ab8cb6a5aa286dc5595beca0f87a67a..c3bd2acbb7cb7fd56e4767228add616bd5797e06 100644 (file)
@@ -50,8 +50,8 @@ new_lookup_table(size_t capacity)
                } else {
                        FREE(table);
                        table = NULL;
-                       ERROR("Failed to allocate memory for lookup table with capacity %zu",
-                             capacity);
+                       ERROR("Failed to allocate memory for lookup table "
+                             "with capacity %zu", capacity);
                }
        }
        return table;
@@ -350,13 +350,15 @@ for_lookup_table_entry_pos_sorted(struct wim_lookup_table *table,
 int
 read_lookup_table(WIMStruct *w)
 {
-       u64 num_entries;
        int ret;
+       size_t num_entries;
        struct wim_lookup_table *table;
        struct wim_lookup_table_entry *cur_entry, *duplicate_entry;
-       void *table_buf;
-       size_t table_size;
-       const void *p;
+       u8 table_buf[(BUFFER_SIZE / WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE) *
+                       WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE];
+       const u8 *p;
+       off_t offset;
+       size_t buf_entries_remaining;
 
        DEBUG("Reading lookup table: offset %"PRIu64", size %"PRIu64"",
              w->hdr.lookup_table_res_entry.offset,
@@ -368,34 +370,36 @@ read_lookup_table(WIMStruct *w)
                return WIMLIB_ERR_COMPRESSED_LOOKUP_TABLE;
        }
 
-       table_size = w->hdr.lookup_table_res_entry.size;
-       if (table_size != w->hdr.lookup_table_res_entry.size) {
-               ERROR("Lookup table is invalid");
-               return WIMLIB_ERR_INVALID_LOOKUP_TABLE_ENTRY;
-       }
-
-       table_buf = MALLOC(table_size);
-       if (!table_buf)
-               return WIMLIB_ERR_NOMEM;
-
-       if (full_pread(w->in_fd, table_buf, table_size,
-                      w->hdr.lookup_table_res_entry.offset) != table_size)
-       {
-               ret = WIMLIB_ERR_READ;
-               goto out_free_table_buf;
-       }
-
-       num_entries = w->hdr.lookup_table_res_entry.original_size /
+       num_entries = w->hdr.lookup_table_res_entry.size /
                      WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE;
        table = new_lookup_table(num_entries * 2 + 1);
-       if (!table) {
-               ret = WIMLIB_ERR_NOMEM;
-               goto out_free_table_buf;
-       }
+       if (!table)
+               return WIMLIB_ERR_NOMEM;
 
        w->current_image = 0;
-       p = table_buf;
-       while (num_entries--) {
+       offset = w->hdr.lookup_table_res_entry.offset;
+       buf_entries_remaining = 0;
+       for (; num_entries != 0; num_entries--, buf_entries_remaining--) {
+               if (buf_entries_remaining == 0) {
+                       size_t entries_to_read, bytes_to_read;
+
+                       entries_to_read = min(sizeof(table_buf) /
+                                               WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE,
+                                             num_entries);
+                       bytes_to_read = entries_to_read *
+                                               WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE;
+                       if (full_pread(w->in_fd, table_buf,
+                                      bytes_to_read, offset) != bytes_to_read)
+                       {
+                               ERROR_WITH_ERRNO("Error reading lookup table "
+                                                "(offset=%"PRIu64")", offset);
+                               ret = WIMLIB_ERR_READ;
+                               goto out_free_lookup_table;
+                       }
+                       offset += bytes_to_read;
+                       p = table_buf;
+                       buf_entries_remaining = entries_to_read;
+               }
                cur_entry = new_lookup_table_entry();
                if (!cur_entry) {
                        ret = WIMLIB_ERR_NOMEM;
@@ -496,8 +500,7 @@ read_lookup_table(WIMStruct *w)
                }
        }
 
-       if (w->hdr.part_number == 1 &&
-           w->current_image != w->hdr.image_count)
+       if (w->hdr.part_number == 1 && w->current_image != w->hdr.image_count)
        {
                ERROR("The WIM header says there are %u images "
                      "in the WIM, but we only found %d metadata "
@@ -508,23 +511,19 @@ read_lookup_table(WIMStruct *w)
        DEBUG("Done reading lookup table.");
        w->lookup_table = table;
        ret = 0;
-       goto out_free_table_buf;
+       goto out;
 out_free_cur_entry:
        FREE(cur_entry);
 out_free_lookup_table:
        free_lookup_table(table);
-out_free_table_buf:
-       FREE(table_buf);
+out:
        w->current_image = 0;
        return ret;
 }
 
 
-/*
- * Writes a lookup table entry to the output file.
- */
-static void *
-write_lookup_table_entry(struct wim_lookup_table_entry *lte, void *buf_p)
+static u8 *
+write_lookup_table_entry(struct wim_lookup_table_entry *lte, u8 *buf_p)
 {
        buf_p = put_resource_entry(buf_p, &lte->output_resource_entry);
        buf_p = put_u16(buf_p, lte->part_number);
@@ -538,63 +537,60 @@ write_lookup_table_from_stream_list(struct list_head *stream_list,
                                    filedes_t out_fd,
                                    struct resource_entry *out_res_entry)
 {
-       size_t num_entries;
-       struct list_head *pos;
+       int ret;
+       off_t start_offset;
+       u8 table_buf[(BUFFER_SIZE / WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE) *
+                       WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE];
+       u8 *buf_p;
        size_t table_size;
-       void *table_buf;
-       void *buf_p;
+       size_t bytes_to_write;
        struct wim_lookup_table_entry *lte;
-       off_t start_offset;
-       int ret;
 
        start_offset = filedes_offset(out_fd);
        if (start_offset == -1)
-               return WIMLIB_ERR_WRITE;
-
-       num_entries = 0;
-       list_for_each(pos, stream_list)
-               num_entries++;
-       table_size = num_entries * WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE;
-
-       table_buf = MALLOC(table_size);
-       if (!table_buf) {
-               ERROR("Failed to allocate lookup table buffer of %zu bytes", table_size);
-               return WIMLIB_ERR_NOMEM;
-       }
+               goto write_error;
 
        buf_p = table_buf;
-       list_for_each_entry(lte, stream_list, lookup_table_list)
-               buf_p =  write_lookup_table_entry(lte, buf_p);
-
-       wimlib_assert(buf_p - table_buf == table_size);
-
-       if (full_write(out_fd, table_buf, table_size) != table_size) {
-               ERROR_WITH_ERRNO("Failed to write lookup table");
-               ret = WIMLIB_ERR_WRITE;
-               goto out_free_table_buf;
+       table_size = 0;
+       list_for_each_entry(lte, stream_list, lookup_table_list) {
+               if (buf_p == table_buf + sizeof(table_buf)) {
+                       bytes_to_write = sizeof(table_buf);
+                       if (full_write(out_fd, table_buf,
+                                      bytes_to_write) != bytes_to_write)
+                               goto write_error;
+                       table_size += bytes_to_write;
+                       buf_p = table_buf;
+               }
+               buf_p = write_lookup_table_entry(lte, buf_p);
+       }
+       bytes_to_write = buf_p - table_buf;
+       if (bytes_to_write != 0) {
+               if (full_write(out_fd, table_buf,
+                              bytes_to_write) != bytes_to_write)
+                       goto write_error;
+               table_size += bytes_to_write;
        }
-
        out_res_entry->offset        = start_offset;
        out_res_entry->size          = table_size;
        out_res_entry->original_size = table_size;
        out_res_entry->flags         = WIM_RESHDR_FLAG_METADATA;
        ret = 0;
-out_free_table_buf:
-       FREE(table_buf);
+out:
        return ret;
+write_error:
+       ERROR_WITH_ERRNO("Failed to write lookup table");
+       ret = WIMLIB_ERR_WRITE;
+       goto out;
 }
 
 static int
 append_lookup_table_entry(struct wim_lookup_table_entry *lte, void *_list)
 {
-       struct list_head *list = _list;
-
        if (lte->out_refcnt != 0)
-               list_add_tail(&lte->lookup_table_list, list);
+               list_add_tail(&lte->lookup_table_list, (struct list_head*)_list);
        return 0;
 }
 
-
 /* Writes the WIM lookup table to the output file. */
 int
 write_lookup_table(WIMStruct *w, int image, struct resource_entry *out_res_entry)
@@ -619,7 +615,6 @@ write_lookup_table(WIMStruct *w, int image, struct resource_entry *out_res_entry
                metadata_lte->output_resource_entry.flags |= WIM_RESHDR_FLAG_METADATA;
                append_lookup_table_entry(metadata_lte, &stream_list);
        }
-
        for_lookup_table_entry(w->lookup_table,
                               append_lookup_table_entry,
                               &stream_list);
index 464ca711ea43a3dbb7dda4d87b3a4d9a8e0b20ec..8e1fd2415693d6d2da8cb9351fbc8215359f4320 100644 (file)
@@ -344,31 +344,6 @@ read_error:
        goto out;
 }
 
-/*
- * Reads uncompressed data from an open file stream.
- */
-int
-read_uncompressed_resource(FILE *fp, u64 offset, u64 len, void *contents_ret)
-{
-       if (fseeko(fp, offset, SEEK_SET) != 0) {
-               ERROR("Failed to seek to byte %"PRIu64" of input file "
-                     "to read uncompressed resource (len = %"PRIu64")",
-                     offset, len);
-               return WIMLIB_ERR_READ;
-       }
-       if (fread(contents_ret, 1, len, fp) != len) {
-               if (feof(fp)) {
-                       ERROR("Unexpected EOF in uncompressed file resource");
-               } else {
-                       ERROR("Failed to read %"PRIu64" bytes from "
-                             "uncompressed resource at offset %"PRIu64,
-                             len, offset);
-               }
-               return WIMLIB_ERR_READ;
-       }
-       return 0;
-}
-
 /* Reads the contents of a struct resource_entry, as represented in the on-disk
  * format, from the memory pointed to by @p, and fills in the fields of @entry.
  * A pointer to the byte after the memory read at @p is returned. */
index 417b29ed468bfccc769524e3af4df31e8c19f283..47168c8f379b549258b43eb890d05e61ae7a4e79 100644 (file)
@@ -27,6 +27,8 @@
 #include "lookup_table.h"
 #include "xml.h"
 #include "buffer_io.h"
+#include <unistd.h>
+#include <fcntl.h>
 
 struct split_args {
        WIMStruct *w;
@@ -211,6 +213,10 @@ wimlib_split(WIMStruct *w, const tchar *swm_name,
        int total_parts = args.cur_part_number;
        for (int i = 1; i <= total_parts; i++) {
                const tchar *part_name;
+               int part_fd;
+               u8 part_data_buf[4];
+               size_t bytes_written;
+
                if (i == 1) {
                        part_name = swm_name;
                } else {
@@ -219,26 +225,26 @@ wimlib_split(WIMStruct *w, const tchar *swm_name,
                        part_name = swm_base_name;
                }
 
-               FILE *fp = tfopen(part_name, T("r+b"));
-               if (!fp) {
+               part_fd = topen(part_name, O_WRONLY);
+               if (part_fd == INVALID_FILEDES) {
                        ERROR_WITH_ERRNO("Failed to open `%"TS"'", part_name);
                        ret = WIMLIB_ERR_OPEN;
                        goto out;
                }
-               u8 buf[4];
-               put_u16(&buf[0], i);
-               put_u16(&buf[2], total_parts);
-
-               if (fseek(fp, 40, SEEK_SET) != 0 ||
-                   fwrite(buf, 1, sizeof(buf), fp) != sizeof(buf) ||
-                   fclose(fp) != 0)
-               {
-                       ERROR_WITH_ERRNO("Error overwriting header of `%"TS"'",
+               put_u16(&part_data_buf[0], i);
+               put_u16(&part_data_buf[2], total_parts);
+
+               bytes_written = full_pwrite(part_fd, part_data_buf,
+                                           sizeof(part_data_buf), 40);
+               ret = close(part_fd);
+               if (bytes_written != sizeof(part_data_buf) || ret != 0) {
+                       ERROR_WITH_ERRNO("Error updating header of `%"TS"'",
                                         part_name);
                        ret = WIMLIB_ERR_WRITE;
-                       break;
+                       goto out;
                }
        }
+       ret = 0;
 out:
        close_wim_writable(w);
        memcpy(&w->hdr, &hdr_save, sizeof(struct wim_header));
index f1ec74f0730176770f44f88927c05497be5fe71f..485303eb834da3063befa35f3730aec6d0b7638b 100644 (file)
 #include <string.h>
 
 #define _GNU_SOURCE
-#include <unistd.h>
 
-#include "wimlib_internal.h"
 #include "endianness.h"
 #include "timestamp.h"
+#include "wimlib_internal.h"
 
 #include <ctype.h>
 #include <errno.h>
-#include <stdlib.h>
 #include <stdarg.h>
+#include <stdlib.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
 
 #ifdef __WIN32__
 #include "win32.h"
@@ -564,79 +566,75 @@ zap_backslashes(tchar *s)
        }
 }
 
-/* Write @n bytes from @buf to the file descriptor @fd, retrying on internupt
- * and on short writes.
- *
- * Returns short count and set errno on failure. */
+/* Like read(), but keep trying until everything has been written or we know for
+ * sure that there was an error (or end-of-file). */
 size_t
-full_write(int fd, const void *buf, size_t n)
+full_read(int fd, void *buf, size_t count)
 {
-       const void *p = buf;
-       ssize_t ret;
-       ssize_t total = 0;
+       ssize_t bytes_read;
+       size_t bytes_remaining;
 
-       while (total != n) {
-               ret = write(fd, p, n);
-               if (ret <= 0) {
-                       if (errno == EINTR)
-                               continue;
-                       if (ret == 0)
+       for (bytes_remaining = count;
+            bytes_remaining != 0;
+            bytes_remaining -= bytes_read, buf += bytes_read)
+       {
+               bytes_read = read(fd, buf, bytes_remaining);
+               if (bytes_read <= 0) {
+                       if (bytes_read == 0)
                                errno = EIO;
+                       else if (errno == EINTR)
+                               continue;
                        break;
                }
-               total += ret;
-               p += ret;
        }
-       return total;
+       return count - bytes_remaining;
 }
 
-/* Read @n bytes from the file descriptor @fd to the buffer @buf, retrying on
- * interrupt and on short reads.
- *
- * Returns short count and set errno on failure. */
+/* Like write(), but keep trying until everything has been written or we know
+ * for sure that there was an error. */
 size_t
-full_read(int fd, void *buf, size_t n)
+full_write(int fd, const void *buf, size_t count)
 {
-       size_t bytes_remaining = n;
-       while (bytes_remaining) {
-               ssize_t bytes_read = read(fd, buf, bytes_remaining);
-               if (bytes_read <= 0) {
+       ssize_t bytes_written;
+       size_t bytes_remaining;
+
+       for (bytes_remaining = count;
+            bytes_remaining != 0;
+            bytes_remaining -= bytes_written, buf += bytes_written)
+       {
+               bytes_written = write(fd, buf, bytes_remaining);
+               if (bytes_written < 0) {
                        if (errno == EINTR)
                                continue;
-                       if (bytes_read == 0)
-                               errno = EIO;
                        break;
                }
-               bytes_remaining -= bytes_read;
-               buf += bytes_read;
        }
-       return n - bytes_remaining;
+       return count - bytes_remaining;
 }
 
-/* Read @n bytes from the file descriptor @fd at the offset @offset to the
- * buffer @buf, retrying on interrupt and on short reads.
- *
- * Returns short count and set errno on failure. */
+/* Like pread(), but keep trying until everything has been read or we know for
+ * sure that there was an error (or end-of-file) */
 size_t
-full_pread(int fd, void *buf, size_t nbyte, off_t offset)
+full_pread(int fd, void *buf, size_t count, off_t offset)
 {
-       size_t bytes_remaining = nbyte;
        ssize_t bytes_read;
+       size_t bytes_remaining;
 
-       while (bytes_remaining) {
+       for (bytes_remaining = count;
+            bytes_remaining != 0;
+            bytes_remaining -= bytes_read, buf += bytes_read,
+               offset += bytes_read)
+       {
                bytes_read = pread(fd, buf, bytes_remaining, offset);
                if (bytes_read <= 0) {
-                       if (errno == EINTR)
-                               continue;
                        if (bytes_read == 0)
                                errno = EIO;
+                       else if (errno == EINTR)
+                               continue;
                        break;
                }
-               bytes_remaining -= bytes_read;
-               buf += bytes_read;
-               offset += bytes_read;
        }
-       return nbyte - bytes_remaining;
+       return count - bytes_remaining;
 }
 
 /* Like pwrite(), but keep trying until everything has been written or we know
@@ -644,25 +642,54 @@ full_pread(int fd, void *buf, size_t nbyte, off_t offset)
 size_t
 full_pwrite(int fd, const void *buf, size_t count, off_t offset)
 {
-       ssize_t bytes_remaining = count;
        ssize_t bytes_written;
+       size_t bytes_remaining;
 
-       while (bytes_remaining > 0) {
+       for (bytes_remaining = count;
+            bytes_remaining != 0;
+            bytes_remaining -= bytes_written, buf += bytes_written,
+               offset += bytes_written)
+       {
                bytes_written = pwrite(fd, buf, bytes_remaining, offset);
-               if (bytes_written <= 0) {
+               if (bytes_written < 0) {
                        if (errno == EINTR)
                                continue;
-                       if (bytes_written == 0)
-                               errno = EIO;
                        break;
                }
-               bytes_remaining -= bytes_written;
-               buf += bytes_written;
-               offset += bytes_written;
        }
        return count - bytes_remaining;
 }
 
+/* Like writev(), but keep trying until everything has been written or we know
+ * for sure that there was an error. */
+size_t
+full_writev(int fd, struct iovec *iov, int iovcnt)
+{
+       size_t total_bytes_written = 0;
+       while (iovcnt > 0) {
+               ssize_t bytes_written;
+
+               bytes_written = writev(fd, iov, iovcnt);
+               if (bytes_written < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       break;
+               }
+               total_bytes_written += bytes_written;
+               while (bytes_written) {
+                       if (bytes_written >= iov[0].iov_len) {
+                               bytes_written -= iov[0].iov_len;
+                               iov++;
+                               iovcnt--;
+                       } else {
+                               iov[0].iov_base += bytes_written;
+                               iov[0].iov_len -= bytes_written;
+                               bytes_written = 0;
+                       }
+               }
+       }
+       return total_bytes_written;
+}
 
 off_t
 filedes_offset(filedes_t fd)
index 04020e14b455879c0b7eb11ba3f3b0c0e1124411..e32496a500ce95c809577d4d88edee9885078dea 100644 (file)
@@ -297,7 +297,12 @@ extern size_t
 full_pread(filedes_t fd, void *buf, size_t nbyte, off_t offset);
 
 extern size_t
-full_pwrite(int fd, const void *buf, size_t count, off_t offset);
+full_pwrite(filedes_t fd, const void *buf, size_t count, off_t offset);
+
+struct iovec;
+
+extern size_t
+full_writev(int fd, struct iovec *iov, int iovcnt);
 
 extern off_t
 filedes_offset(filedes_t fd);
index 27cf93f4587f3e477da4a33a1ffdc85cd2e9f3cf..c82730c8a5e9e126b2dc8ea49658578503fc6705 100644 (file)
--- a/src/wim.c
+++ b/src/wim.c
@@ -65,9 +65,10 @@ static WIMStruct *
 new_wim_struct()
 {
        WIMStruct *w = CALLOC(1, sizeof(WIMStruct));
-       w->in_fd = INVALID_FILEDES;
-       w->out_fd = INVALID_FILEDES;
-       w->current_image = WIMLIB_NO_IMAGE;
+       if (w) {
+               w->in_fd = INVALID_FILEDES;
+               w->out_fd = INVALID_FILEDES;
+       }
        return w;
 }
 
@@ -388,8 +389,8 @@ do_open_wim(const tchar *filename, filedes_t *fd_ret)
 {
        int fd;
 
-       fd = open(filename, O_RDONLY);
-       if (fd == -1) {
+       fd = topen(filename, O_RDONLY);
+       if (fd == INVALID_FILEDES) {
                ERROR_WITH_ERRNO("Can't open \"%"TS"\" read-only", filename);
                return WIMLIB_ERR_OPEN;
        }
@@ -407,8 +408,10 @@ reopen_wim(WIMStruct *w)
 int
 close_wim(WIMStruct *w)
 {
-       close(w->in_fd);
-       w->in_fd = INVALID_FILEDES;
+       if (w->in_fd != INVALID_FILEDES) {
+               close(w->in_fd);
+               w->in_fd = INVALID_FILEDES;
+       }
        return 0;
 }
 
index db8d03518a04fab4b37a3be38bf6690ebec8e709..65dd8a1d7f4acf41c1956d962a732e92dc2203bb 100644 (file)
@@ -284,7 +284,9 @@ struct WIMStruct {
         * not been opened or there is no associated file backing it yet. */
        filedes_t in_fd;
 
-       /* FILE pointer for the WIM file (if any) currently being written. */
+       /* File descriptor, opened either for writing only or for
+        * reading+writing, for the WIM file (if any) currently being written.
+        * */
        filedes_t out_fd;
 
        /* The name of the WIM file (if any) that has been opened. */
index 9a64c05ef9fec6717fa6c3b13feb62b2d06fa424..d403fba7ca611a7a5f5d7563122c66059e0011a2 100644 (file)
@@ -2646,10 +2646,6 @@ win32_rename_replacement(const wchar_t *oldpath, const wchar_t *newpath)
                return 0;
        } else {
                /* As usual, the possible error values are not documented */
-               DWORD err = GetLastError();
-               ERROR("MoveFileEx(): Can't rename \"%ls\" to \"%ls\"",
-                     oldpath, newpath);
-               win32_error(err);
                errno = -1;
                return -1;
        }
index 9965f5c06bf2d21f853bb6d1bfedda0cbf3d98a3..16ce531aacc2850b1d096f243d6e257030c566f9 100644 (file)
@@ -65,8 +65,6 @@
 
 #include <limits.h>
 
-#include <sys/uio.h> /* writev() */
-
 /* Chunk table that's located at the beginning of each compressed resource in
  * the WIM.  (This is not the on-disk format; the on-disk format just has an
  * array of offsets.) */
@@ -164,7 +162,7 @@ get_compress_func(int out_ctype)
  *
  * @chunk:       Uncompressed data of the chunk.
  * @chunk_size:          Size of the chunk (<= WIM_CHUNK_SIZE)
- * @out_fd:      FILE descriptor to write the chunk to.
+ * @out_fd:      File descriptor to write the chunk to.
  * @compress:     Compression function to use (NULL if writing uncompressed
  *                     data).
  * @chunk_tab:   Pointer to chunk table being created.  It is updated with the
@@ -301,7 +299,7 @@ write_resource_cb(const void *restrict chunk, size_t chunk_size,
  * @lte:  Lookup table entry for the resource, which could be in another WIM,
  *        in an external file, or in another location.
  *
- * @out_fp:  File descriptor opened to the output WIM.
+ * @out_fd:  File descriptor opened to the output WIM.
  *
  * @out_ctype:  One of the WIMLIB_COMPRESSION_TYPE_* constants to indicate
  *              which compression algorithm to use.
@@ -768,50 +766,17 @@ static int
 write_wim_chunks(struct message *msg, filedes_t out_fd,
                 struct chunk_table *chunk_tab)
 {
-       ssize_t bytes_remaining = msg->total_out_bytes;
-       struct iovec *vecs = msg->out_chunks;
-       unsigned nvecs = msg->num_chunks;
-       int ret;
-
-       wimlib_assert(nvecs != 0);
-       wimlib_assert(msg->total_out_bytes != 0);
-
        for (unsigned i = 0; i < msg->num_chunks; i++) {
                *chunk_tab->cur_offset_p++ = chunk_tab->cur_offset;
-               chunk_tab->cur_offset += vecs[i].iov_len;
-       }
-       for (;;) {
-               ssize_t bytes_written;
-
-               bytes_written = writev(out_fd, vecs, nvecs);
-               if (bytes_written <= 0) {
-                       if (bytes_written < 0 && errno == EINTR)
-                               continue;
-                       else if (bytes_written == 0)
-                               errno = EIO;
-                       ERROR_WITH_ERRNO("Failed to write WIM chunks");
-                       ret = WIMLIB_ERR_WRITE;
-                       break;
-               }
-               bytes_remaining -= bytes_written;
-               if (bytes_remaining <= 0) {
-                       ret = 0;
-                       break;
-               }
-               while (bytes_written >= 0) {
-                       wimlib_assert(nvecs != 0);
-                       if (bytes_written >= vecs[0].iov_len) {
-                               vecs++;
-                               nvecs--;
-                               bytes_written -= vecs[0].iov_len;
-                       } else {
-                               vecs[0].iov_base += bytes_written;
-                               vecs[0].iov_len -= bytes_written;
-                               bytes_written = 0;
-                       }
-               }
+               chunk_tab->cur_offset += msg->out_chunks[i].iov_len;
        }
-       return ret;
+       if (full_writev(out_fd, msg->out_chunks,
+                       msg->num_chunks) != msg->total_out_bytes)
+       {
+               ERROR_WITH_ERRNO("Failed to write WIM chunks");
+               return WIMLIB_ERR_WRITE;
+       }
+       return 0;
 }
 
 struct main_writer_thread_ctx {
@@ -1688,7 +1653,7 @@ prepare_stream_list(WIMStruct *wim, int image, struct list_head *stream_list)
        return ret;
 }
 
-/* Writes the streams for the specified @image in @wim to @wim->out_fp.
+/* Writes the streams for the specified @image in @wim to @wim->out_fd.
  */
 static int
 write_wim_streams(WIMStruct *wim, int image, int write_flags,
@@ -1868,7 +1833,6 @@ lock_wim(WIMStruct *w, filedes_t fd)
 static int
 open_wim_writable(WIMStruct *w, const tchar *path, int open_flags)
 {
-       wimlib_assert(w->out_fd == INVALID_FILEDES);
        w->out_fd = open(path, open_flags, 0644);
        if (w->out_fd == INVALID_FILEDES) {
                ERROR_WITH_ERRNO("Failed to open `%"TS"' for writing", path);
@@ -1905,8 +1869,8 @@ begin_write(WIMStruct *w, const tchar *path, int write_flags)
        ret = write_header(&w->hdr, w->out_fd);
        if (ret)
                return ret;
-       if (lseek(w->out_fd, 0, SEEK_END) == -1) {
-               ERROR_WITH_ERRNO("Failed to seek to end of WIM");
+       if (lseek(w->out_fd, WIM_HEADER_DISK_SIZE, SEEK_SET) == -1) {
+               ERROR_WITH_ERRNO("Failed to seek to end of WIM header");
                return WIMLIB_ERR_WRITE;
        }
        return 0;
@@ -2173,19 +2137,9 @@ overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
                goto out_unlink;
        }
 
-       DEBUG("Renaming `%"TS"' to `%"TS"'", tmpfile, w->filename);
-
-#ifdef __WIN32__
-       /* Windows won't let you delete open files unless FILE_SHARE_DELETE was
-        * specified to CreateFile().  The WIM was opened with fopen(), which
-        * didn't provided this flag to CreateFile, so the handle must be closed
-        * before executing the rename(). */
-       if (w->fp != NULL) {
-               fclose(w->fp);
-               w->fp = NULL;
-       }
-#endif
+       close_wim(w);
 
+       DEBUG("Renaming `%"TS"' to `%"TS"'", tmpfile, w->filename);
        /* Rename the new file to the old file .*/
        if (trename(tmpfile, w->filename) != 0) {
                ERROR_WITH_ERRNO("Failed to rename `%"TS"' to `%"TS"'",
index b27fbeabf8bb994116e1fe2759f669c5411d2ef7..e902fab39a4e2227cb92888a0e0f346f28c5d5c3 100644 (file)
@@ -41,6 +41,7 @@ typedef wchar_t tchar;
 #  define tputs                _putws
 #  define tfputs       fputws
 #  define tfopen       _wfopen
+#  define topen                _wopen
 #  define tstat                _wstati64
 #  define tstrtol      wcstol
 #  define tstrtod      wcstod
@@ -96,6 +97,7 @@ typedef char tchar;
 #  define tputs                puts
 #  define tfputs       fputs
 #  define tfopen       fopen
+#  define topen                open
 #  define tstat                stat
 #  define tunlink      unlink
 #  define tstrerror    strerror