1 #ifndef _WIMLIB_PROGRESS_H
2 #define _WIMLIB_PROGRESS_H
3 
4 #include "wimlib.h"
5 #include "wimlib/paths.h"
6 #include "wimlib/types.h"
7 
8 /* If specified, call the user-provided progress function and check its result.
9  */
10 static inline int
call_progress(wimlib_progress_func_t progfunc,enum wimlib_progress_msg msg,union wimlib_progress_info * info,void * progctx)11 call_progress(wimlib_progress_func_t progfunc,
12 	      enum wimlib_progress_msg msg,
13 	      union wimlib_progress_info *info,
14 	      void *progctx)
15 {
16 	if (progfunc) {
17 		enum wimlib_progress_status status;
18 
19 		status = (*progfunc)(msg, info, progctx);
20 
21 		switch (status) {
22 		case WIMLIB_PROGRESS_STATUS_CONTINUE:
23 			return 0;
24 		case WIMLIB_PROGRESS_STATUS_ABORT:
25 			return WIMLIB_ERR_ABORTED_BY_PROGRESS;
26 		default:
27 			return WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS;
28 		}
29 	}
30 	return 0;
31 }
32 
33 extern int
34 report_error(wimlib_progress_func_t progfunc,
35 	     void *progctx, int error_code, const tchar *path);
36 
37 /* Rate-limiting of byte-count based progress messages: update *next_progress_p
38  * to the value that completed_bytes needs to reach before the next progress
39  * message will be sent.  */
40 static inline void
set_next_progress(u64 completed_bytes,u64 total_bytes,u64 * next_progress_p)41 set_next_progress(u64 completed_bytes, u64 total_bytes, u64 *next_progress_p)
42 {
43 	if (*next_progress_p < total_bytes) {
44 		/*
45 		 * Send the next message as soon as:
46 		 *	- another 1/128 of the total has been processed;
47 		 *	- OR another 5000000 bytes have been processed;
48 		 *	- OR all bytes have been processed.
49 		 */
50 		*next_progress_p = min(min(completed_bytes + total_bytes / 128,
51 					   completed_bytes + 5000000),
52 				       total_bytes);
53 	} else {
54 		/* Last message has been sent.  */
55 		*next_progress_p = ~0;
56 	}
57 }
58 
59 /* Windows: temporarily remove the stream name from the path  */
60 static inline tchar *
progress_get_streamless_path(const tchar * path)61 progress_get_streamless_path(const tchar *path)
62 {
63 	tchar *cookie = NULL;
64 #ifdef __WIN32__
65 	cookie = (wchar_t *)path_stream_name(path);
66 	if (cookie)
67 		*--cookie = L'\0'; /* Overwrite the colon  */
68 #endif
69 	return cookie;
70 }
71 
72 /* Windows: temporarily replace \??\ with \\?\ (to make an NT namespace path
73  * into a Win32 namespace path)  */
74 static inline tchar *
progress_get_win32_path(const tchar * path)75 progress_get_win32_path(const tchar *path)
76 {
77 #ifdef __WIN32__
78 	if (!wcsncmp(path, L"\\??\\", 4)) {
79 		((wchar_t *)path)[1] = L'\\';
80 		return (wchar_t *)&path[1];
81 	}
82 #endif
83 	return NULL;
84 }
85 
86 /* Windows: restore the NT namespace path  */
87 static inline void
progress_put_win32_path(tchar * cookie)88 progress_put_win32_path(tchar *cookie)
89 {
90 #ifdef __WIN32__
91 	if (cookie)
92 		*cookie = L'?';
93 #endif
94 }
95 
96 /* Windows: restore the stream name part of the path  */
97 static inline void
progress_put_streamless_path(tchar * cookie)98 progress_put_streamless_path(tchar *cookie)
99 {
100 #ifdef __WIN32__
101 	if (cookie)
102 		*cookie = L':';
103 #endif
104 }
105 
106 #endif /* _WIMLIB_PROGRESS_H */
107