X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Freference.c;h=d1e34e19733e9bfcd706abcd99786850ff2060c1;hp=1a83a4a6cbcf315b85051e591c758fac90a10e0f;hb=af141a23c4d1540b8a64759bb68c7cd7ff054e72;hpb=5d3d469e410dc5f4a28814ad231336fc174cba56 diff --git a/src/reference.c b/src/reference.c index 1a83a4a6..d1e34e19 100644 --- a/src/reference.c +++ b/src/reference.c @@ -33,6 +33,33 @@ #include "wimlib/lookup_table.h" #include "wimlib/wim.h" +#define WIMLIB_REF_MASK_PUBLIC (WIMLIB_REF_FLAG_GLOB_ENABLE | \ + WIMLIB_REF_FLAG_GLOB_ERR_ON_NOMATCH) + +#define WIMLIB_REF_FLAG_GIFT 0x80000000 + +struct lookup_tables { + struct wim_lookup_table *src_table; + struct wim_lookup_table *dest_table; +}; + +static int +lte_gift(struct wim_lookup_table_entry *lte, void *_tables) +{ + struct lookup_tables *tables = _tables; + struct wim_lookup_table *src_table = tables->src_table; + struct wim_lookup_table *dest_table = tables->dest_table; + + lookup_table_unlink(src_table, lte); + if (lookup_stream(dest_table, lte->hash)) { + free_lookup_table_entry(lte); + } else { + lte->out_refcnt = 1; + lookup_table_insert(dest_table, lte); + } + return 0; +} + static int lte_clone_if_new(struct wim_lookup_table_entry *lte, void *_lookup_table) { @@ -61,13 +88,49 @@ lte_delete_if_new(struct wim_lookup_table_entry *lte, void *_lookup_table) return 0; } +static int +do_wimlib_reference_resources(WIMStruct *wim, WIMStruct **resource_wims, + unsigned num_resource_wims, int ref_flags) +{ + unsigned i; + int ret; + + if (ref_flags & WIMLIB_REF_FLAG_GIFT) { + struct lookup_tables tables; + + tables.dest_table = wim->lookup_table; + + for (i = 0; i < num_resource_wims; i++) { + + tables.src_table = resource_wims[i]->lookup_table; + + ret = for_lookup_table_entry(resource_wims[i]->lookup_table, + lte_gift, &tables); + if (ret) + goto out_rollback; + } + } else { + for (i = 0; i < num_resource_wims; i++) { + ret = for_lookup_table_entry(resource_wims[i]->lookup_table, + lte_clone_if_new, wim->lookup_table); + if (ret) + goto out_rollback; + } + } + return 0; + +out_rollback: + for_lookup_table_entry(wim->lookup_table, lte_delete_if_new, + wim->lookup_table); + return ret; +} + /* API function documented in wimlib.h */ WIMLIBAPI int wimlib_reference_resources(WIMStruct *wim, WIMStruct **resource_wims, unsigned num_resource_wims, int ref_flags) { - int ret; unsigned i; if (wim == NULL) @@ -76,25 +139,15 @@ wimlib_reference_resources(WIMStruct *wim, if (num_resource_wims != 0 && resource_wims == NULL) return WIMLIB_ERR_INVALID_PARAM; + if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC) + return WIMLIB_ERR_INVALID_PARAM; + for (i = 0; i < num_resource_wims; i++) if (resource_wims[i] == NULL) return WIMLIB_ERR_INVALID_PARAM; - for_lookup_table_entry(wim->lookup_table, lte_zero_out_refcnt, NULL); - - for (i = 0; i < num_resource_wims; i++) { - ret = for_lookup_table_entry(resource_wims[i]->lookup_table, - lte_clone_if_new, - wim->lookup_table); - if (ret) - goto out_rollback; - } - return 0; - -out_rollback: - for_lookup_table_entry(wim->lookup_table, lte_delete_if_new, - wim->lookup_table); - return ret; + return do_wimlib_reference_resources(wim, resource_wims, + num_resource_wims, ref_flags); } static int @@ -102,8 +155,7 @@ reference_resource_paths(WIMStruct *wim, const tchar * const *resource_wimfiles, unsigned num_resource_wimfiles, int ref_flags, - int open_flags, - wimlib_progress_func_t progress_func) + int open_flags) { WIMStruct **resource_wims; unsigned i; @@ -116,14 +168,18 @@ reference_resource_paths(WIMStruct *wim, for (i = 0; i < num_resource_wimfiles; i++) { DEBUG("Referencing resources from path \"%"TS"\"", resource_wimfiles[i]); - ret = wimlib_open_wim(resource_wimfiles[i], open_flags, - &resource_wims[i], progress_func); + ret = wimlib_open_wim_with_progress(resource_wimfiles[i], + open_flags, + &resource_wims[i], + wim->progfunc, + wim->progctx); if (ret) goto out_free_resource_wims; } - ret = wimlib_reference_resources(wim, resource_wims, - num_resource_wimfiles, ref_flags); + ret = do_wimlib_reference_resources(wim, resource_wims, + num_resource_wimfiles, + ref_flags | WIMLIB_REF_FLAG_GIFT); if (ret) goto out_free_resource_wims; @@ -143,8 +199,7 @@ out_free_array: static int reference_resource_glob(WIMStruct *wim, const tchar *refglob, - int ref_flags, int open_flags, - wimlib_progress_func_t progress_func) + int ref_flags, int open_flags) { glob_t globbuf; int ret; @@ -161,8 +216,7 @@ reference_resource_glob(WIMStruct *wim, const tchar *refglob, &refglob, 1, ref_flags, - open_flags, - progress_func); + open_flags); } } else { ERROR_WITH_ERRNO("Failed to process glob \"%"TS"\"", refglob); @@ -177,8 +231,7 @@ reference_resource_glob(WIMStruct *wim, const tchar *refglob, (const tchar * const *)globbuf.gl_pathv, globbuf.gl_pathc, ref_flags, - open_flags, - progress_func); + open_flags); globfree(&globbuf); return ret; } @@ -189,26 +242,26 @@ wimlib_reference_resource_files(WIMStruct *wim, const tchar * const * resource_wimfiles_or_globs, unsigned count, int ref_flags, - int open_flags, - wimlib_progress_func_t progress_func) + int open_flags) { unsigned i; int ret; + if (ref_flags & ~WIMLIB_REF_MASK_PUBLIC) + return WIMLIB_ERR_INVALID_PARAM; + if (ref_flags & WIMLIB_REF_FLAG_GLOB_ENABLE) { for (i = 0; i < count; i++) { ret = reference_resource_glob(wim, resource_wimfiles_or_globs[i], ref_flags, - open_flags, - progress_func); + open_flags); if (ret) return ret; } return 0; } else { return reference_resource_paths(wim, resource_wimfiles_or_globs, - count, ref_flags, - open_flags, progress_func); + count, ref_flags, open_flags); } }