X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fwrite.c;h=d184a64a23485689dc27ad3704b3c4b79da6875d;hb=4f8059f2d0a74a9922128b162d9c9343b305999c;hp=9965f5c06bf2d21f853bb6d1bfedda0cbf3d98a3;hpb=f9695b9f40035f1a20968293255761a8301eaba0;p=wimlib diff --git a/src/write.c b/src/write.c index 9965f5c0..d184a64a 100644 --- a/src/write.c +++ b/src/write.c @@ -48,6 +48,7 @@ #endif #include +#include #include #ifdef WITH_NTFS_3G @@ -65,7 +66,9 @@ #include -#include /* writev() */ +#ifndef __WIN32__ +# include /* for `struct iovec' */ +#endif /* 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 @@ -164,7 +167,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 @@ -175,7 +178,7 @@ get_compress_func(int out_ctype) static int write_wim_resource_chunk(const void * restrict chunk, unsigned chunk_size, - filedes_t out_fd, + int out_fd, compress_func_t compress, struct chunk_table * restrict chunk_tab) { @@ -216,7 +219,7 @@ write_wim_resource_chunk(const void * restrict chunk, */ static int finish_wim_resource_chunk_tab(struct chunk_table *chunk_tab, - filedes_t out_fd, u64 *compressed_size_p) + int out_fd, u64 *compressed_size_p) { size_t bytes_written; @@ -241,7 +244,7 @@ finish_wim_resource_chunk_tab(struct chunk_table *chunk_tab, } static int -seek_and_truncate(filedes_t out_fd, off_t offset) +seek_and_truncate(int out_fd, off_t offset) { if (lseek(out_fd, offset, SEEK_SET) == -1 || ftruncate(out_fd, offset)) @@ -277,7 +280,7 @@ finalize_and_check_sha1(SHA_CTX * restrict sha_ctx, struct write_resource_ctx { compress_func_t compress; struct chunk_table *chunk_tab; - filedes_t out_fd; + int out_fd; SHA_CTX sha_ctx; bool doing_sha; }; @@ -301,7 +304,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. @@ -321,7 +324,7 @@ write_resource_cb(const void *restrict chunk, size_t chunk_size, */ int write_wim_resource(struct wim_lookup_table_entry *lte, - filedes_t out_fd, int out_ctype, + int out_fd, int out_ctype, struct resource_entry *out_res_entry, int flags) { @@ -617,7 +620,7 @@ do_write_streams_progress(union wimlib_progress_info *progress, } struct serial_write_stream_ctx { - filedes_t out_fd; + int out_fd; int out_ctype; int write_resource_flags; }; @@ -712,7 +715,7 @@ do_write_stream_list(struct list_head *stream_list, static int do_write_stream_list_serial(struct list_head *stream_list, struct wim_lookup_table *lookup_table, - filedes_t out_fd, + int out_fd, int out_ctype, int write_resource_flags, wimlib_progress_func_t progress_func, @@ -744,7 +747,7 @@ write_flags_to_resource_flags(int write_flags) static int write_stream_list_serial(struct list_head *stream_list, struct wim_lookup_table *lookup_table, - filedes_t out_fd, + int out_fd, int out_ctype, int write_resource_flags, wimlib_progress_func_t progress_func, @@ -765,59 +768,26 @@ write_stream_list_serial(struct list_head *stream_list, #ifdef ENABLE_MULTITHREADED_COMPRESSION static int -write_wim_chunks(struct message *msg, filedes_t out_fd, +write_wim_chunks(struct message *msg, int 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 { struct list_head *stream_list; struct wim_lookup_table *lookup_table; - filedes_t out_fd; + int out_fd; int out_ctype; int write_resource_flags; struct shared_queue *res_to_compress_queue; @@ -1253,7 +1223,7 @@ get_default_num_threads() static int write_stream_list_parallel(struct list_head *stream_list, struct wim_lookup_table *lookup_table, - filedes_t out_fd, + int out_fd, int out_ctype, int write_resource_flags, wimlib_progress_func_t progress_func, @@ -1391,7 +1361,7 @@ out_serial_quiet: static int write_stream_list(struct list_head *stream_list, struct wim_lookup_table *lookup_table, - filedes_t out_fd, int out_ctype, int write_flags, + int out_fd, int out_ctype, int write_flags, unsigned num_threads, wimlib_progress_func_t progress_func) { struct wim_lookup_table_entry *lte; @@ -1688,7 +1658,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, @@ -1835,16 +1805,16 @@ out_close_wim: if (ret == 0) ret = WIMLIB_ERR_WRITE; } - w->out_fd = INVALID_FILEDES; + w->out_fd = -1; return ret; } #if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK) int -lock_wim(WIMStruct *w, filedes_t fd) +lock_wim(WIMStruct *w, int fd) { int ret = 0; - if (fd != INVALID_FILEDES && !w->wim_locked) { + if (fd != -1 && !w->wim_locked) { ret = flock(fd, LOCK_EX | LOCK_NB); if (ret != 0) { if (errno == EWOULDBLOCK) { @@ -1868,9 +1838,8 @@ 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) { + w->out_fd = topen(path, open_flags | O_BINARY, 0644); + if (w->out_fd == -1) { ERROR_WITH_ERRNO("Failed to open `%"TS"' for writing", path); return WIMLIB_ERR_OPEN; } @@ -1881,10 +1850,10 @@ open_wim_writable(WIMStruct *w, const tchar *path, int open_flags) void close_wim_writable(WIMStruct *w) { - if (w->out_fd != INVALID_FILEDES) { + if (w->out_fd != -1) { if (close(w->out_fd)) WARNING_WITH_ERRNO("Failed to close output WIM"); - w->out_fd = INVALID_FILEDES; + w->out_fd = -1; } } @@ -1905,8 +1874,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 +2142,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"'",