Don't close file descriptor at end of wimlib_write_to_fd()
authorEric Biggers <ebiggers3@gmail.com>
Wed, 14 Aug 2013 16:19:51 +0000 (11:19 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Wed, 14 Aug 2013 16:19:51 +0000 (11:19 -0500)
include/wimlib.h
programs/imagex.c
src/write.c

index 8c293c8..f23aa9c 100644 (file)
@@ -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:
  *
index 8947c56..788ba90 100644 (file)
@@ -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;
 }
index 96ada49..3cac5a2 100644 (file)
@@ -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