argv++;
wimlib_set_print_errors(true);
+ ret = wimlib_global_init();
+ if (ret)
+ goto out;
for_imagex_command(cmd) {
if (strcmp(cmd->name, *argv) == 0) {
ret = cmd->func(argc, argv);
- if (ret > 0) {
- imagex_error("Exiting with error code %d:\n"
- " %s.", ret,
- wimlib_get_error_string(ret));
- if (ret == WIMLIB_ERR_NTFS_3G && errno != 0)
- imagex_error_with_errno("errno");
- }
- return ret;
+ goto out;
}
}
imagex_error("Unrecognized command: `%s'", argv[0]);
usage_all();
return 1;
+out:
+ if (ret > 0) {
+ imagex_error("Exiting with error code %d:\n"
+ " %s.", ret,
+ wimlib_get_error_string(ret));
+ if (ret == WIMLIB_ERR_NTFS_3G && errno != 0)
+ imagex_error_with_errno("errno");
+ }
+ wimlib_global_cleanup();
+ return ret;
}
}
#endif /* !WITH_NTFS_3G */
+#ifndef WITH_NTFS_3G
+static iconv_t cd_utf8_to_utf16 = (iconv_t)(-1);
+static iconv_t cd_utf16_to_utf8 = (iconv_t)(-1);
+
+int iconv_global_init()
+{
+ if (cd_utf16_to_utf8 == (iconv_t)(-1)) {
+ cd_utf16_to_utf8 = iconv_open("UTF-8", "UTF-16LE");
+ if (cd_utf16_to_utf8 == (iconv_t)-1) {
+ ERROR_WITH_ERRNO("Failed to get conversion descriptor "
+ "for converting UTF-16LE to UTF-8");
+ if (errno == ENOMEM)
+ return WIMLIB_ERR_NOMEM;
+ else
+ return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
+ }
+ }
+
+ if (cd_utf8_to_utf16 == (iconv_t)(-1)) {
+ cd_utf8_to_utf16 = iconv_open("UTF-16LE", "UTF-8");
+ if (cd_utf8_to_utf16 == (iconv_t)-1) {
+ ERROR_WITH_ERRNO("Failed to get conversion descriptor "
+ "for converting UTF-8 to UTF-16LE");
+ if (errno == ENOMEM)
+ return WIMLIB_ERR_NOMEM;
+ else
+ return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
+ }
+ }
+ return 0;
+}
+
+void iconv_global_cleanup()
+{
+ if (cd_utf8_to_utf16 != (iconv_t)(-1))
+ iconv_close(cd_utf8_to_utf16);
+ if (cd_utf16_to_utf8 != (iconv_t)(-1))
+ iconv_close(cd_utf16_to_utf8);
+}
+#endif
+
/* Converts a string in the UTF-16LE encoding to a newly allocated string in the
* UTF-8 encoding.
*
else
ret = WIMLIB_ERR_INVALID_UTF16_STRING;
}
-#else /* WITH_NTFS_3G */
- static iconv_t cd_utf16_to_utf8 = (iconv_t)(-1);
- if (cd_utf16_to_utf8 == (iconv_t)(-1)) {
- cd_utf16_to_utf8 = iconv_open("UTF-8", "UTF-16LE");
- if (cd_utf16_to_utf8 == (iconv_t)-1) {
- ERROR_WITH_ERRNO("Failed to get conversion descriptor "
- "for converting UTF-16LE to UTF-8");
- if (errno == ENOMEM)
- return WIMLIB_ERR_NOMEM;
- else
- return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
- }
- }
+#else /* !WITH_NTFS_3G */
+
+ ret = iconv_global_init();
+ if (ret != 0)
+ return ret;
+
ret = utf16_to_utf8_size((const u16*)utf16_str, utf16_nbytes / 2);
if (ret >= 0) {
size_t utf8_expected_nbytes;
else
ret = WIMLIB_ERR_INVALID_UTF8_STRING;
}
-#else /* WITH_NTFS_3G */
- static iconv_t cd_utf8_to_utf16 = (iconv_t)(-1);
- if (cd_utf8_to_utf16 == (iconv_t)(-1)) {
- cd_utf8_to_utf16 = iconv_open("UTF-16LE", "UTF-8");
- if (cd_utf8_to_utf16 == (iconv_t)-1) {
- ERROR_WITH_ERRNO("Failed to get conversion descriptor "
- "for converting UTF-8 to UTF-16LE");
- if (errno == ENOMEM)
- return WIMLIB_ERR_NOMEM;
- else
- return WIMLIB_ERR_ICONV_NOT_AVAILABLE;
- }
- }
+#else /* !WITH_NTFS_3G */
+ ret = iconv_global_init();
+ if (ret != 0)
+ return ret;
ret = utf8_to_utf16_size(utf8_str);
if (ret >= 0) {
size_t utf16_expected_nbytes;
/* encoding.c */
+
+#ifdef WITH_NTFS_3G
+static inline int iconv_global_init()
+{
+ return 0;
+}
+
+static inline void iconv_global_cleanup() { }
+#else
+extern int iconv_global_init();
+extern void iconv_global_cleanup();
+#endif
+
extern int utf16_to_utf8(const char *utf16_str, size_t utf16_nbytes,
char **utf8_str_ret, size_t *utf8_nbytes_ret);
#endif
FREE(w);
}
+
+/* Get global memory allocations out of the way. Not strictly necessary in
+ * single-threaded programs like 'imagex'. */
+WIMLIBAPI int wimlib_global_init()
+{
+ libxml_global_init();
+ return iconv_global_init();
+}
+
+/* Free global memory allocations. Not strictly necessary if the process using
+ * wimlib is just about to exit (as is the case for 'imagex'). */
+WIMLIBAPI void wimlib_global_cleanup()
+{
+ libxml_global_cleanup();
+ iconv_global_cleanup();
+}
*/
extern int wimlib_get_part_number(const WIMStruct *wim, int *total_parts_ret);
+/**
+ * Since wimlib 1.2.6: Initialization function for wimlib. This is not
+ * re-entrant. If you are calling wimlib functions concurrently in different
+ * threads, then you must call this function serially first. Otherwise, calling
+ * this function is not required.
+ *
+ * @return 0 on success; nonzero on error.
+ * @retval ::WIMLIB_ERR_NOMEM
+ * Could not allocate memory.
+ * @retval ::WIMLIB_ERR_ICONV_NOT_AVAILABLE
+ * wimlib was configured --without-libntfs-3g at compilation time, and at
+ * runtime the iconv() set of functions did not seem to be available,
+ * perhaps due to missing files in the C library installation.
+ *
+ * If this function is not called or returns nonzero, then it will not be safe
+ * to use wimlib in multiple threads. Furthermore, a nonzero return value here
+ * indicates that further calls into wimlib will probably fail when they try to
+ * repeat the same initializations.
+ */
+extern int wimlib_global_init();
+
+/**
+ * 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.
+ */
+extern void wimlib_global_cleanup();
+
/**
* Returns true if the WIM has an integrity table.
*
putchar('\n');
}
+void libxml_global_init()
+{
+ xmlInitParser();
+}
+
+void libxml_global_cleanup()
+{
+ xmlCleanupParser();
+}
+
/*
* Reads the XML data from a WIM file.
*/
if (resource_is_compressed(res_entry)) {
ERROR("XML data is supposed to be uncompressed");
ret = WIMLIB_ERR_XML;
- goto out_cleanup_parser;
+ goto out;
}
if (res_entry->size < 2) {
ERROR("XML data must be at least 2 bytes long");
ret = WIMLIB_ERR_XML;
- goto out_cleanup_parser;
+ goto out;
}
xml_data = MALLOC(res_entry->size + 2);
if (!xml_data) {
ret = WIMLIB_ERR_NOMEM;
- goto out_cleanup_parser;
+ goto out;
}
ret = read_uncompressed_resource(fp, res_entry->offset,
if (ret != 0)
goto out_free_doc;
- DEBUG("Freeing XML tree.");
-
*xml_data_ret = xml_data;
xml_data = NULL;
out_free_doc:
+ DEBUG("Freeing XML tree.");
xmlFreeDoc(doc);
out_free_xml_data:
FREE(xml_data);
-out_cleanup_parser:
- xmlCleanupParser();
+out:
return ret;
}
extern int write_xml_data(const struct wim_info *wim_info, int image, FILE *out,
u64 total_bytes, struct resource_entry *out_res_entry);
+extern void libxml_global_init();
+extern void libxml_global_cleanup();
+
static inline u64 wim_info_get_total_bytes(const struct wim_info *info)
{
return info->total_bytes;