From: Eric Biggers Date: Wed, 14 Aug 2013 16:19:51 +0000 (-0500) Subject: Don't close file descriptor at end of wimlib_write_to_fd() X-Git-Tag: v1.5.0~78 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=3f10159fec6c397ed4d182a25a1aa5b3147101cf Don't close file descriptor at end of wimlib_write_to_fd() --- diff --git a/include/wimlib.h b/include/wimlib.h index 8c293c8a..f23aa9c9 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -1872,7 +1872,8 @@ wimlib_extract_image(WIMStruct *wim, int image, wimlib_progress_func_t progress_func); /** - * Extract one or more images from a pipe on which a pipable WIM is being sent. + * Since wimlib v1.5.0: Extract one or more images from a pipe on which a + * pipable WIM is being sent. * * See the documentation for ::WIMLIB_WRITE_FLAG_PIPABLE for more information * about pipable WIMs. @@ -2061,7 +2062,9 @@ wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info); /** * Initialization function for wimlib. Call before using any other wimlib - * function. + * function except wimlib_set_print_errors(). (However, currently this is not + * strictly necessary and it will be called automatically if not done manually, + * but you should not rely on this behavior.) * * @param init_flags * On UNIX, specify ::WIMLIB_INIT_FLAG_ASSUME_UTF8 if wimlib should assume @@ -2078,7 +2081,7 @@ wimlib_global_init(int init_flags); /** * Since wimlib 1.2.6: Cleanup function for wimlib. This is not re-entrant. * You are not required to call this function, but it will release any global - * memory allocated by the library. + * resources allocated by the library. */ extern void wimlib_global_cleanup(void); @@ -2784,6 +2787,8 @@ wimlib_set_memory_allocator(void *(*malloc_func)(size_t), * * By default, error messages are not printed. * + * This can be called before wimlib_global_init(). + * * @param show_messages * @c true if error messages are to be printed; @c false if error messages * are not to be printed. @@ -3089,12 +3094,15 @@ wimlib_write(WIMStruct *wim, wimlib_progress_func_t progress_func); /** - * Same as wimlib_write(), but write the WIM directly to a file descriptor, - * which need not be seekable if the write is done in a special pipable WIM - * format by providing ::WIMLIB_WRITE_FLAG_PIPABLE in @p write_flags. This can, - * for example, allow capturing a WIM image and streaming it over the network. - * See the documentation for ::WIMLIB_WRITE_FLAG_PIPABLE for more information - * about pipable WIMs. + * Since wimlib v1.5.0: Same as wimlib_write(), but write the WIM directly to a + * file descriptor, which need not be seekable if the write is done in a special + * pipable WIM format by providing ::WIMLIB_WRITE_FLAG_PIPABLE in @p + * write_flags. This can, for example, allow capturing a WIM image and + * streaming it over the network. See the documentation for + * ::WIMLIB_WRITE_FLAG_PIPABLE for more information about pipable WIMs. + * + * The file descriptor @p fd will not be closed when the write is complete; the + * calling code is responsible for this. * * Return values are mostly the same as wimlib_write(), but also: * diff --git a/programs/imagex.c b/programs/imagex.c index 8947c56d..788ba904 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -3734,8 +3734,8 @@ main(int argc, char **argv) } } - /* Unless already known from the invocation name, search for the - * function to handle the specified subcommand. */ + /* Unless already known from the invocation name, determine which + * command was specified. */ if (cmd == CMD_NONE) { if (argc < 2) { imagex_error(T("No command specified!\n")); @@ -3754,20 +3754,24 @@ main(int argc, char **argv) } } - /* Handle --help and --version for all commands. Note that this will - * not return if either of these arguments are present. */ + /* Handle --help and --version. --help can be either for the program as + * a whole (cmd == CMD_NONE) or just for a specific command (cmd != + * CMD_NONE). Note: help_or_version() will not return if a --help or + * --version argument was found. */ help_or_version(argc, argv, cmd); + /* Bail if a valid command was not specified. */ if (cmd == CMD_NONE) { imagex_error(T("Unrecognized command: `%"TS"'\n"), argv[1]); usage_all(stderr); exit(2); } - /* The user may like to see more informative error messages. */ + /* Enable warning and error messages in the library to be more + * user-friendly. */ wimlib_set_print_errors(true); - /* Initialize the library. */ + /* Initialize wimlib. */ ret = wimlib_global_init(init_flags); if (ret) goto out_check_status; @@ -3785,9 +3789,8 @@ main(int argc, char **argv) } out_check_status: /* Exit status (ret): -1 indicates an error found by 'wimlib-imagex' - * outside of the wimlib library code. 0 indicates success. > 0 - * indicates a wimlib error code from which an error message can be - * printed. */ + * itself (not by wimlib). 0 indicates success. > 0 indicates a wimlib + * error code from which an error message can be printed. */ if (ret > 0) { imagex_error(T("Exiting with error code %d:\n" " %"TS"."), ret, @@ -3795,8 +3798,8 @@ out_check_status: if (ret == WIMLIB_ERR_NTFS_3G && errno != 0) imagex_error_with_errno(T("errno")); } - /* Make the library free any resources it's holding (not strictly - * necessary because the process is ending anyway). */ + /* Make wimlib free any resources it's holding (although this is not + * strictly necessary because the process is ending anyway). */ wimlib_global_cleanup(); return ret; } diff --git a/src/write.c b/src/write.c index 96ada492..3cac5a28 100644 --- a/src/write.c +++ b/src/write.c @@ -1965,6 +1965,34 @@ write_wim_metadata_resources(WIMStruct *wim, int image, int write_flags, return 0; } +static int +open_wim_writable(WIMStruct *wim, const tchar *path, int open_flags) +{ + int raw_fd; + DEBUG("Opening \"%"TS"\" for writing.", path); + + raw_fd = topen(path, open_flags | O_BINARY, 0644); + if (raw_fd < 0) { + ERROR_WITH_ERRNO("Failed to open \"%"TS"\" for writing", path); + return WIMLIB_ERR_OPEN; + } + filedes_init(&wim->out_fd, raw_fd); + return 0; +} + +static int +close_wim_writable(WIMStruct *wim, int write_flags) +{ + int ret = 0; + + if (!(write_flags & WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR)) + if (filedes_valid(&wim->out_fd)) + if (filedes_close(&wim->out_fd)) + ret = WIMLIB_ERR_WRITE; + filedes_invalidate(&wim->out_fd); + return ret; +} + /* * Finish writing a WIM file: write the lookup table, xml data, and integrity * table, then overwrite the WIM header. Always closes the WIM file descriptor @@ -2100,12 +2128,12 @@ finish_write(WIMStruct *wim, int image, int write_flags, ret = 0; out_close_wim: - if (filedes_close(&wim->out_fd)) { - ERROR_WITH_ERRNO("Failed to close the output WIM file"); - if (ret == 0) + if (close_wim_writable(wim, write_flags)) { + if (ret == 0) { + ERROR_WITH_ERRNO("Failed to close the output WIM file"); ret = WIMLIB_ERR_WRITE; + } } - filedes_invalidate(&wim->out_fd); return ret; } @@ -2135,32 +2163,6 @@ lock_wim(WIMStruct *wim, int fd) } #endif -static int -open_wim_writable(WIMStruct *wim, const tchar *path, int open_flags) -{ - int raw_fd; - DEBUG("Opening \"%"TS"\" for writing.", path); - - raw_fd = topen(path, open_flags | O_BINARY, 0644); - if (raw_fd < 0) { - ERROR_WITH_ERRNO("Failed to open \"%"TS"\" for writing", path); - return WIMLIB_ERR_OPEN; - } - filedes_init(&wim->out_fd, raw_fd); - return 0; -} - - -static void -close_wim_writable(WIMStruct *wim) -{ - if (filedes_valid(&wim->out_fd)) { - if (filedes_close(&wim->out_fd)) - WARNING_WITH_ERRNO("Failed to close output WIM"); - filedes_invalidate(&wim->out_fd); - } -} - /* * Perform the intermediate stages of creating a "pipable" WIM (i.e. a WIM * capable of being applied from a pipe). Such a WIM looks like: @@ -2502,7 +2504,7 @@ write_wim_part(WIMStruct *wim, stream_list_override); out_restore_hdr: memcpy(&wim->hdr, &hdr_save, sizeof(struct wim_header)); - close_wim_writable(wim); + close_wim_writable(wim, write_flags); return ret; } @@ -2685,7 +2687,7 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, ret = lock_wim(wim, wim->out_fd.fd); if (ret) { - close_wim_writable(wim); + close_wim_writable(wim, write_flags); return ret; } @@ -2694,13 +2696,13 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, &wim->out_fd); if (ret) { ERROR_WITH_ERRNO("Error updating WIM header flags"); - close_wim_writable(wim); + close_wim_writable(wim, write_flags); goto out_unlock_wim; } if (filedes_seek(&wim->out_fd, old_wim_end) == -1) { ERROR_WITH_ERRNO("Can't seek to end of WIM"); - close_wim_writable(wim); + close_wim_writable(wim, write_flags); ret = WIMLIB_ERR_WRITE; goto out_unlock_wim; } @@ -2728,8 +2730,8 @@ overwrite_wim_inplace(WIMStruct *wim, int write_flags, ret = finish_write(wim, WIMLIB_ALL_IMAGES, write_flags, progress_func, NULL); out_truncate: - close_wim_writable(wim); - if (ret != 0 && !(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) { + close_wim_writable(wim, write_flags); + if (ret && !(write_flags & WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE)) { WARNING("Truncating `%"TS"' to its original size (%"PRIu64" bytes)", wim->filename, old_wim_end); /* Return value of truncate() is ignored because this is already