]> wimlib.net Git - wimlib/blobdiff - src/reference.c
Update progress functions
[wimlib] / src / reference.c
index 3238abe464434be1cd5be79e0cfb854ff6122984..d1e34e19733e9bfcd706abcd99786850ff2060c1 100644 (file)
 #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)
 {
@@ -64,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)
@@ -86,21 +146,8 @@ wimlib_reference_resources(WIMStruct *wim,
                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
@@ -108,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;
@@ -122,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;
 
@@ -149,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;
@@ -167,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);
@@ -183,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;
 }
@@ -195,8 +242,7 @@ 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;
@@ -209,15 +255,13 @@ wimlib_reference_resource_files(WIMStruct *wim,
                        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);
        }
 }