From: Eric Biggers Date: Sun, 5 May 2013 01:47:52 +0000 (-0500) Subject: native fds fixes/cleanups X-Git-Tag: v1.4.0~133 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=4f953b223bed60d71a7689d414ccb5cc60be537f native fds fixes/cleanups --- diff --git a/src/header.c b/src/header.c index ff3bb95b..2524793d 100644 --- a/src/header.c +++ b/src/header.c @@ -31,13 +31,13 @@ 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"); diff --git a/src/lookup_table.c b/src/lookup_table.c index 24c13320..c3bd2acb 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -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, <e->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(<e->lookup_table_list, list); + list_add_tail(<e->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); diff --git a/src/resource.c b/src/resource.c index 464ca711..8e1fd241 100644 --- a/src/resource.c +++ b/src/resource.c @@ -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. */ diff --git a/src/split.c b/src/split.c index 417b29ed..47168c8f 100644 --- a/src/split.c +++ b/src/split.c @@ -27,6 +27,8 @@ #include "lookup_table.h" #include "xml.h" #include "buffer_io.h" +#include +#include 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)); diff --git a/src/util.c b/src/util.c index f1ec74f0..485303eb 100644 --- a/src/util.c +++ b/src/util.c @@ -30,16 +30,18 @@ #include #define _GNU_SOURCE -#include -#include "wimlib_internal.h" #include "endianness.h" #include "timestamp.h" +#include "wimlib_internal.h" #include #include -#include #include +#include +#include +#include + #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) diff --git a/src/util.h b/src/util.h index 04020e14..e32496a5 100644 --- a/src/util.h +++ b/src/util.h @@ -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); diff --git a/src/wim.c b/src/wim.c index 27cf93f4..c82730c8 100644 --- 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; } diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h index db8d0351..65dd8a1d 100644 --- a/src/wimlib_internal.h +++ b/src/wimlib_internal.h @@ -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. */ diff --git a/src/win32.c b/src/win32.c index 9a64c05e..d403fba7 100644 --- a/src/win32.c +++ b/src/win32.c @@ -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; } diff --git a/src/write.c b/src/write.c index 9965f5c0..16ce531a 100644 --- a/src/write.c +++ b/src/write.c @@ -65,8 +65,6 @@ #include -#include /* 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"'", diff --git a/wimlib_tchar.h b/wimlib_tchar.h index b27fbeab..e902fab3 100644 --- a/wimlib_tchar.h +++ b/wimlib_tchar.h @@ -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