Refactor error functions; make re-entrant
authorEric Biggers <ebiggers3@gmail.com>
Sun, 3 Mar 2013 21:47:12 +0000 (15:47 -0600)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 3 Mar 2013 21:56:47 +0000 (15:56 -0600)
Use strerror_r() (the "XSI-compliant" version) instead of strerror().

src/extract_image.c
src/util.c
src/util.h
src/wimlib.h
src/write.c

index 0d1db2c..c202156 100644 (file)
@@ -321,8 +321,8 @@ static int apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg)
                }
                #endif
                if (errno != ENOSYS || args->num_lutimes_warnings < 10) {
-                       /*WARNING("Failed to set timestamp on file `%s': %s",*/
-                               /*output_path, strerror(errno));*/
+                       /*WARNING_WITH_ERRNO("Failed to set timestamp on file `%s',*/
+                                           /*output_path");*/
                        args->num_lutimes_warnings++;
                }
        }
index e8e3a37..9aad4b2 100644 (file)
  * along with wimlib; if not, see http://www.gnu.org/licenses/.
  */
 
+#undef _GNU_SOURCE
+/* Make sure the POSIX-compatible strerror_r() is declared, rather than the GNU
+ * version, which has a different return type. */
+#define _POSIX_C_SOURCE 200112
+#include <string.h>
+#define _GNU_SOURCE
+
 #include "wimlib_internal.h"
 #include "endianness.h"
 #include "timestamp.h"
 #include <ctype.h>
 #include <errno.h>
 #include <stdlib.h>
-#include <string.h>
+
 #include <unistd.h> /* for getpid() */
 
 /* True if wimlib is to print an informational message when an error occurs.
  * This can be turned off by calling wimlib_set_print_errors(false). */
 #ifdef ENABLE_ERROR_MESSAGES
 #include <stdarg.h>
-bool __wimlib_print_errors = false;
+static bool wimlib_print_errors = false;
 
-void wimlib_error(const char *format, ...)
+static void wimlib_vmsg(const char *tag, const char *format,
+                       va_list va, bool perror)
 {
-       if (__wimlib_print_errors) {
-               va_list va;
-               int errno_save;
-
-               va_start(va, format);
-               errno_save = errno;
-               fputs("[ERROR] ", stderr);
+       if (wimlib_print_errors) {
+               int errno_save = errno;
+               fflush(stdout);
+               fputs(tag, stderr);
                vfprintf(stderr, format, va);
+               if (perror && errno_save != 0) {
+                       char buf[50];
+                       int res = strerror_r(errno_save, buf, sizeof(buf));
+                       if (res) {
+                               snprintf(buf, sizeof(buf),
+                                        "unknown error (errno=%d)", errno_save);
+                       }
+                       fputs(buf, stderr);
+               }
                putc('\n', stderr);
                errno = errno_save;
-               va_end(va);
        }
 }
 
+void wimlib_error(const char *format, ...)
+{
+       va_list va;
+
+       va_start(va, format);
+       wimlib_vmsg("[ERROR] ", format, va, false);
+       va_end(va);
+}
+
 void wimlib_error_with_errno(const char *format, ...)
 {
-       if (__wimlib_print_errors) {
-               va_list va;
-               int errno_save;
+       va_list va;
 
-               va_start(va, format);
-               errno_save = errno;
-               fflush(stdout);
-               fputs("[ERROR] ", stderr);
-               vfprintf(stderr, format, va);
-               if (errno_save != 0)
-                       fprintf(stderr, ": %s", strerror(errno_save));
-               putc('\n', stderr);
-               errno = errno_save;
-               va_end(va);
-       }
+       va_start(va, format);
+       wimlib_vmsg("[ERROR] ", format, va, true);
+       va_end(va);
 }
 
 void wimlib_warning(const char *format, ...)
 {
-       if (__wimlib_print_errors) {
-               va_list va;
-               int errno_save;
+       va_list va;
 
-               va_start(va, format);
-               errno_save = errno;
-               fflush(stdout);
-               fputs("[WARNING] ", stderr);
-               vfprintf(stderr, format, va);
-               putc('\n', stderr);
-               errno = errno_save;
-               va_end(va);
-       }
+       va_start(va, format);
+       wimlib_vmsg("[WARNING] ", format, va, false);
+       va_end(va);
+}
+
+void wimlib_warning_with_errno(const char *format, ...)
+{
+       va_list va;
+
+       va_start(va, format);
+       wimlib_vmsg("[WARNING] ", format, va, true);
+       va_end(va);
 }
 
 #endif
@@ -94,7 +107,7 @@ void wimlib_warning(const char *format, ...)
 WIMLIBAPI int wimlib_set_print_errors(bool show_error_messages)
 {
 #ifdef ENABLE_ERROR_MESSAGES
-       __wimlib_print_errors = show_error_messages;
+       wimlib_print_errors = show_error_messages;
        return 0;
 #else
        if (show_error_messages)
index 0979d98..4f40566 100644 (file)
@@ -86,20 +86,25 @@ typedef uint64_t u64;
 #define BUFFER_SIZE 4096
 
 #ifdef ENABLE_ERROR_MESSAGES
-extern bool __wimlib_print_errors;
 extern void wimlib_error(const char *format, ...)
                FORMAT(printf, 1, 2) COLD;
 extern void wimlib_error_with_errno(const char *format, ...)
                FORMAT(printf, 1, 2) COLD;
 extern void wimlib_warning(const char *format, ...)
                FORMAT(printf, 1, 2) COLD;
-#      define ERROR            wimlib_error
-#      define ERROR_WITH_ERRNO wimlib_error_with_errno
-#      define WARNING          wimlib_warning
+extern void wimlib_warning_with_errno(const char *format, ...)
+               FORMAT(printf, 1, 2) COLD;
+#      define ERROR                    wimlib_error
+#      define ERROR_WITH_ERRNO         wimlib_error_with_errno
+#      define WARNING                  wimlib_warning
+#      define WARNING_WITH_ERRNO       wimlib_warning
 #else
-#      define ERROR(format, ...)
-#      define ERROR_WITH_ERRNO(format, ...)
-#      define WARNING(format, ...)
+static inline FORMAT(printf, 1, 2) void
+dummy_printf(const char *format, ...) { }
+#      define ERROR(format, ...)               dummy_printf
+#      define ERROR_WITH_ERRNO(format, ...)    dummy_printf
+#      define WARNING(format, ...)             dummy_printf
+#      define WARNING_WITH_ERRNO(format, ...)  dummy_printf
 #endif /* ENABLE_ERROR_MESSAGES */
 
 #if defined(ENABLE_DEBUG) || defined(ENABLE_MORE_DEBUG)
index 1de5d04..55289fe 100644 (file)
  *
  * wimlib is thread-safe as long as different ::WIMStruct's are used, except for
  * the fact that wimlib_set_print_errors() and wimlib_set_memory_allocator()
- * both apply globally.
+ * both apply globally, and you also must call wimlib_global_init() in the main
+ * thread to avoid any race conditions with one-time allocations of memory.
  *
  * To open an existing WIM, use wimlib_open_wim().
  *
index 1f471d6..4b06146 100644 (file)
@@ -1265,8 +1265,8 @@ out_join:
 
        for (unsigned i = 0; i < num_threads; i++) {
                if (pthread_join(compressor_threads[i], NULL)) {
-                       WARNING("Failed to join compressor thread %u: %s",
-                               i, strerror(errno));
+                       WARNING_WITH_ERRNO("Failed to join compressor "
+                                          "thread %u", i);
                }
        }
        FREE(compressor_threads);
@@ -1603,8 +1603,8 @@ int lock_wim(WIMStruct *w, FILE *fp)
                                      "        by another process!", w->filename);
                                ret = WIMLIB_ERR_ALREADY_LOCKED;
                        } else {
-                               WARNING("Failed to lock `%s': %s",
-                                       w->filename, strerror(errno));
+                               WARNING_WITH_ERRNO("Failed to lock `%s'",
+                                                  w->filename);
                                ret = 0;
                        }
                } else {
@@ -1642,8 +1642,7 @@ void close_wim_writable(WIMStruct *w)
 {
        if (w->out_fp) {
                if (fclose(w->out_fp) != 0) {
-                       WARNING("Failed to close output WIM: %s",
-                               strerror(errno));
+                       WARNING_WITH_ERRNO("Failed to close output WIM");
                }
                w->out_fp = NULL;
        }
@@ -1929,8 +1928,8 @@ static int overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
        w->fp = fopen(w->filename, "rb");
        if (w->fp == NULL) {
                ret = WIMLIB_ERR_REOPEN;
-               WARNING("Failed to re-open `%s' read-only: %s",
-                       w->filename, strerror(errno));
+               WARNING_WITH_ERRNO("Failed to re-open `%s' read-only",
+                                  w->filename);
                FREE(w->filename);
                w->filename = NULL;
        }
@@ -1938,7 +1937,7 @@ static int overwrite_wim_via_tmpfile(WIMStruct *w, int write_flags,
 err:
        /* Remove temporary file. */
        if (unlink(tmpfile) != 0)
-               WARNING("Failed to remove `%s': %s", tmpfile, strerror(errno));
+               WARNING_WITH_ERRNO("Failed to remove `%s'", tmpfile);
        return ret;
 }