Add WIMLIB_PROGRESS_MSG_HANDLE_ERROR
authorEric Biggers <ebiggers3@gmail.com>
Wed, 22 Oct 2014 03:17:30 +0000 (22:17 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Wed, 22 Oct 2014 03:25:27 +0000 (22:25 -0500)
Makefile.am
include/wimlib.h
include/wimlib/progress.h
src/progress.c [new file with mode: 0644]

index c6f8301..612de3e 100644 (file)
@@ -59,6 +59,7 @@ libwim_la_SOURCES =           \
        src/mount_image.c       \
        src/pathlist.c          \
        src/paths.c             \
+       src/progress.c          \
        src/resource.c          \
        src/reference.c         \
        src/security.c          \
index 59e4fb6..ffc9cdb 100644 (file)
@@ -708,6 +708,25 @@ enum wimlib_progress_msg {
         * mechanism.
         */
        WIMLIB_PROGRESS_MSG_TEST_FILE_EXCLUSION = 30,
+
+       /**
+        * An error has occurred and the progress function is being asked
+        * whether to ignore the error or not.  @p info will point to
+        * ::wimlib_progress_info.handle_error.  This is a bidirectional
+        * message.
+        *
+        * This message provides a limited capability for applications to
+        * recover from "unexpected" errors (i.e. those with no in-library
+        * handling policy) arising from the underlying operating system.
+        * Normally, any such error will cause the library to abort the current
+        * operation.  By implementing a handler for this message, the
+        * application can instead choose to ignore a given error.
+        *
+        * Currently, only the following types of errors will result in this
+        * progress message being sent:
+        *
+        */
+       WIMLIB_PROGRESS_MSG_HANDLE_ERROR = 31,
 };
 
 /** Valid return values from user-provided progress functions
@@ -1204,6 +1223,24 @@ union wimlib_progress_info {
                 */
                bool will_exclude;
        } test_file_exclusion;
+
+       /** Valid on messages ::WIMLIB_PROGRESS_MSG_HANDLE_ERROR.  */
+       struct wimlib_progress_info_handle_error {
+
+               /** Path to the file for which the error occurred, or NULL if
+                * not relevant.  */
+               const wimlib_tchar *path;
+
+               /** The wimlib error code associated with the error.  */
+               int error_code;
+
+               /**
+                * Indicates whether the error will be ignored or not.  This
+                * will be <tt>false</tt> by default; the progress function may
+                * set it to <tt>true</tt>.
+                */
+               bool will_ignore;
+       } handle_error;
 };
 
 /**
@@ -1724,7 +1761,7 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour
  * Note: This method for file exclusions is independent from the capture
  * configuration file mechanism.
  */
-#define WIMLIB_ADD_FLAG_TEST_FILE_EXCLUSION 0x00004000
+#define WIMLIB_ADD_FLAG_TEST_FILE_EXCLUSION    0x00004000
 
 #define WIMLIB_ADD_IMAGE_FLAG_NTFS             WIMLIB_ADD_FLAG_NTFS
 #define WIMLIB_ADD_IMAGE_FLAG_DEREFERENCE      WIMLIB_ADD_FLAG_DEREFERENCE
index 387afd8..8dbb4c4 100644 (file)
@@ -2,6 +2,7 @@
 #define _WIMLIB_PROGRESS_H
 
 #include "wimlib.h"
+#include "wimlib/types.h"
 
 /* If specified, call the user-provided progress function and check its result.
  */
@@ -28,4 +29,8 @@ call_progress(wimlib_progress_func_t progfunc,
        return 0;
 }
 
-#endif
+extern int
+report_error(wimlib_progress_func_t progfunc,
+            void *progctx, int error_code, const tchar *path);
+
+#endif /* _WIMLIB_PROGRESS_H */
diff --git a/src/progress.c b/src/progress.c
new file mode 100644 (file)
index 0000000..b616dff
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * progress.c
+ */
+
+/*
+ * Copyright (C) 2014 Eric Biggers
+ *
+ * This file is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This file is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this file; if not, see http://www.gnu.org/licenses/.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "wimlib/progress.h"
+
+int
+report_error(wimlib_progress_func_t progfunc,
+            void *progctx, int error_code, const tchar *path)
+{
+       int ret;
+       union wimlib_progress_info progress;
+
+       if (error_code == WIMLIB_ERR_SUCCESS ||
+           error_code == WIMLIB_ERR_ABORTED_BY_PROGRESS ||
+           error_code == WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS)
+               return error_code;
+
+       progress.handle_error.path = path;
+       progress.handle_error.error_code = error_code;
+       progress.handle_error.will_ignore = false;
+
+#ifdef __WIN32__
+       /* Hack for Windows...  */
+
+       wchar_t *p_question_mark = NULL;
+
+       if (!wcsncmp(path, L"\\??\\", 4)) {
+               /* Trivial transformation:  NT namespace => Win32 namespace  */
+               p_question_mark = (wchar_t *)&path[1];
+               *p_question_mark = L'\\';
+       }
+#endif
+
+       ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_HANDLE_ERROR,
+                           &progress, progctx);
+
+#ifdef __WIN32__
+       if (p_question_mark)
+               *p_question_mark = L'?';
+#endif
+
+       if (ret)
+               return ret;
+
+       if (!progress.handle_error.will_ignore)
+               return error_code;
+
+       return 0;
+}