X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fexport_image.c;h=da638322ee06c32d19217986653be498eea4e63d;hp=425e4a4d1c521d13140493be205b5ededd1af2d2;hb=ae7d142ac04cf51ba134750f3338f43af285a433;hpb=0ac1c0afd3f1b4341409e66cb31c94053d1b8988 diff --git a/src/export_image.c b/src/export_image.c index 425e4a4d..da638322 100644 --- a/src/export_image.c +++ b/src/export_image.c @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2012, 2013, 2014 Eric Biggers + * Copyright (C) 2012, 2013, 2014, 2015 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 @@ -24,84 +24,82 @@ #endif #include "wimlib.h" +#include "wimlib/blob_table.h" #include "wimlib/error.h" #include "wimlib/inode.h" -#include "wimlib/lookup_table.h" #include "wimlib/metadata.h" #include "wimlib/xml.h" static int -lte_set_not_exported(struct wim_lookup_table_entry *lte, void *_ignore) +blob_set_not_exported(struct blob_descriptor *blob, void *_ignore) { - lte->out_refcnt = 0; - lte->was_exported = 0; + blob->out_refcnt = 0; + blob->was_exported = 0; return 0; } static int -lte_rollback_export(struct wim_lookup_table_entry *lte, void *_lookup_table) +blob_rollback_export(struct blob_descriptor *blob, void *_blob_table) { - struct wim_lookup_table *lookup_table = _lookup_table; + struct blob_table *blob_table = _blob_table; - lte->refcnt -= lte->out_refcnt; - if (lte->was_exported) { - lookup_table_unlink(lookup_table, lte); - free_lookup_table_entry(lte); + blob->refcnt -= blob->out_refcnt; + if (blob->was_exported) { + blob_table_unlink(blob_table, blob); + free_blob_descriptor(blob); } return 0; } static int -inode_export_streams(struct wim_inode *inode, - struct wim_lookup_table *src_lookup_table, - struct wim_lookup_table *dest_lookup_table, - bool gift) +inode_export_blobs(struct wim_inode *inode, struct blob_table *src_blob_table, + struct blob_table *dest_blob_table, bool gift) { unsigned i; const u8 *hash; - struct wim_lookup_table_entry *src_lte, *dest_lte; + struct blob_descriptor *src_blob, *dest_blob; - inode_unresolve_streams(inode); - for (i = 0; i <= inode->i_num_ads; i++) { + for (i = 0; i < inode->i_num_streams; i++) { - /* Retrieve SHA1 message digest of stream to export. */ - hash = inode_stream_hash(inode, i); + /* Retrieve SHA-1 message digest of blob to export. */ + hash = stream_hash(&inode->i_streams[i]); if (is_zero_hash(hash)) /* Empty stream? */ continue; - /* Search for the stream (via SHA1 message digest) in the + /* Search for the blob (via SHA-1 message digest) in the * destination WIM. */ - dest_lte = lookup_stream(dest_lookup_table, hash); - if (!dest_lte) { - /* Stream not yet present in destination WIM. Search - * for it in the source WIM, then export it into the + dest_blob = lookup_blob(dest_blob_table, hash); + if (!dest_blob) { + /* Blob not yet present in destination WIM. Search for + * it in the source WIM, then export it into the * destination WIM. */ - src_lte = lookup_stream(src_lookup_table, hash); - if (!src_lte) - return stream_not_found_error(inode, hash); + src_blob = stream_blob(&inode->i_streams[i], + src_blob_table); + if (!src_blob) + return blob_not_found_error(inode, hash); if (gift) { - dest_lte = src_lte; - lookup_table_unlink(src_lookup_table, src_lte); + dest_blob = src_blob; + blob_table_unlink(src_blob_table, src_blob); } else { - dest_lte = clone_lookup_table_entry(src_lte); - if (!dest_lte) + dest_blob = clone_blob_descriptor(src_blob); + if (!dest_blob) return WIMLIB_ERR_NOMEM; } - dest_lte->refcnt = 0; - dest_lte->out_refcnt = 0; - dest_lte->was_exported = 1; - lookup_table_insert(dest_lookup_table, dest_lte); + dest_blob->refcnt = 0; + dest_blob->out_refcnt = 0; + dest_blob->was_exported = 1; + blob_table_insert(dest_blob_table, dest_blob); } - /* Stream is present in destination WIM (either pre-existing, + /* Blob is present in destination WIM (either pre-existing, * already exported, or just exported above). Increment its * reference count appropriately. Note: we use 'refcnt' for * the raw reference count, but 'out_refcnt' for references * arising just from the export operation; this is used to roll * back a failed export if needed. */ - dest_lte->refcnt += inode->i_nlink; - dest_lte->out_refcnt += inode->i_nlink; + dest_blob->refcnt += inode->i_nlink; + dest_blob->out_refcnt += inode->i_nlink; } return 0; } @@ -130,7 +128,7 @@ wimlib_export_image(WIMStruct *src_wim, WIMLIB_EXPORT_FLAG_WIMBOOT)) return WIMLIB_ERR_INVALID_PARAM; - if (src_wim == NULL || dest_wim == NULL) + if (!src_wim || !dest_wim) return WIMLIB_ERR_INVALID_PARAM; if (!wim_has_metadata(src_wim) || !wim_has_metadata(dest_wim)) @@ -143,9 +141,8 @@ wimlib_export_image(WIMStruct *src_wim, (!(export_flags & WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS) && dest_description)) { - ERROR("Image name or image description was " - "specified, but we are exporting " - "multiple images"); + ERROR("Image name and description must be " + "left NULL for multi-image export"); return WIMLIB_ERR_INVALID_PARAM; } start_src_image = 1; @@ -156,16 +153,31 @@ wimlib_export_image(WIMStruct *src_wim, } orig_dest_image_count = dest_wim->hdr.image_count; - /* Stream checksums must be known before proceeding. */ - ret = wim_checksum_unhashed_streams(src_wim); + /* We don't yet support having a single WIMStruct contain duplicate + * 'image_metadata' structures, so we must forbid this from happening. + * A duplication is possible if 'src_wim == dest_wim', if the same image + * is exported to the same destination WIMStruct multiple times, or if + * an image is exported in an A => B => A manner. */ + for (src_image = start_src_image; + src_image <= end_src_image; src_image++) + { + const struct wim_image_metadata *src_imd = + src_wim->image_metadata[src_image - 1]; + for (int i = 0; i < dest_wim->hdr.image_count; i++) + if (dest_wim->image_metadata[i] == src_imd) + return WIMLIB_ERR_DUPLICATE_EXPORTED_IMAGE; + } + + /* Blob checksums must be known before proceeding. */ + ret = wim_checksum_unhashed_blobs(src_wim); if (ret) return ret; - ret = wim_checksum_unhashed_streams(dest_wim); + ret = wim_checksum_unhashed_blobs(dest_wim); if (ret) return ret; /* Enable rollbacks */ - for_lookup_table_entry(dest_wim->lookup_table, lte_set_not_exported, NULL); + for_blob_in_table(dest_wim->blob_table, blob_set_not_exported, NULL); /* Export each requested image. */ for (src_image = start_src_image; @@ -179,14 +191,14 @@ wimlib_export_image(WIMStruct *src_wim, /* Determine destination image name and description. */ if (export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) - next_dest_name = T(""); + next_dest_name = NULL; else if (dest_name) next_dest_name = dest_name; else next_dest_name = wimlib_get_image_name(src_wim, src_image); if (export_flags & WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS) - next_dest_description = T(""); + next_dest_description = NULL; else if (dest_description) next_dest_description = dest_description; else @@ -208,20 +220,21 @@ wimlib_export_image(WIMStruct *src_wim, src_imd = wim_get_current_image_metadata(src_wim); /* Iterate through inodes in the source image and export their - * streams into the destination WIM. */ + * blobs into the destination WIM. */ image_for_each_inode(inode, src_imd) { - ret = inode_export_streams(inode, - src_wim->lookup_table, - dest_wim->lookup_table, - export_flags & WIMLIB_EXPORT_FLAG_GIFT); + ret = inode_export_blobs(inode, + src_wim->blob_table, + dest_wim->blob_table, + export_flags & WIMLIB_EXPORT_FLAG_GIFT); if (ret) goto out_rollback; } /* Export XML information into the destination WIM. */ - ret = xml_export_image(src_wim->wim_info, src_image, - &dest_wim->wim_info, next_dest_name, - next_dest_description); + ret = xml_export_image(src_wim->xml_info, src_image, + dest_wim->xml_info, next_dest_name, + next_dest_description, + export_flags & WIMLIB_EXPORT_FLAG_WIMBOOT); if (ret) goto out_rollback; @@ -231,11 +244,6 @@ wimlib_export_image(WIMStruct *src_wim, if (ret) goto out_rollback; src_imd->refcnt++; - - /* Lock the metadata into memory. XXX: need better solution for - * this. */ - src_imd->modified = 1; - } /* Image export complete. Finish by setting any needed special metadata @@ -251,32 +259,25 @@ wimlib_export_image(WIMStruct *src_wim, int dst_image = orig_dest_image_count + 1 + (src_image - start_src_image); - if (export_flags & WIMLIB_EXPORT_FLAG_WIMBOOT) - wim_info_set_wimboot(dest_wim->wim_info, dst_image, true); - if ((export_flags & WIMLIB_EXPORT_FLAG_BOOT) && (!all_images || src_image == src_wim->hdr.boot_idx)) dest_wim->hdr.boot_idx = dst_image; } - if (export_flags & WIMLIB_EXPORT_FLAG_GIFT) { - free_lookup_table(src_wim->lookup_table); - src_wim->lookup_table = NULL; - } return 0; out_rollback: - while ((image = wim_info_get_num_images(dest_wim->wim_info)) + while ((image = xml_get_image_count(dest_wim->xml_info)) > orig_dest_image_count) { - xml_delete_image(&dest_wim->wim_info, image); + xml_delete_image(dest_wim->xml_info, image); } while (dest_wim->hdr.image_count > orig_dest_image_count) { put_image_metadata(dest_wim->image_metadata[ --dest_wim->hdr.image_count], NULL); } - for_lookup_table_entry(dest_wim->lookup_table, lte_rollback_export, - dest_wim->lookup_table); + for_blob_in_table(dest_wim->blob_table, blob_rollback_export, + dest_wim->blob_table); return ret; }