/* * Load the metadata for the specified WIM image into memory and set it * as the WIMStruct's currently selected image. * * @wim * The WIMStruct for the WIM. * @image * The 1-based index of the image in the WIM to select. * * On success, 0 will be returned, wim->current_image will be set to * @image, and wim_get_current_image_metadata() can be used to retrieve * metadata information for the image. * * On failure, WIMLIB_ERR_INVALID_IMAGE, WIMLIB_ERR_METADATA_NOT_FOUND, * or another error code will be returned. */ int select_wim_image(WIMStruct *wim, int image) { struct wim_image_metadata *imd; int ret; if (image == WIMLIB_NO_IMAGE) return WIMLIB_ERR_INVALID_IMAGE; if (image == wim->current_image) return 0; if (image < 1 || image > wim->hdr.image_count) return WIMLIB_ERR_INVALID_IMAGE; if (!wim_has_metadata(wim)) return WIMLIB_ERR_METADATA_NOT_FOUND; /* If a valid image is currently selected, its metadata can be freed if * it has not been modified. */ deselect_current_wim_image(wim); wim->current_image = image; imd = wim_get_current_image_metadata(wim); if (imd->root_dentry || imd->modified) { ret = 0; } else { ret = read_metadata_resource(imd); if (ret) wim->current_image = WIMLIB_NO_IMAGE; } return ret; }
/* API function documented in wimlib.h */ WIMLIBAPI int wimlib_split(WIMStruct *wim, const tchar *swm_name, u64 part_size, int write_flags) { struct swm_info swm_info; unsigned i; int ret; if (swm_name == NULL || swm_name[0] == T('\0') || part_size == 0) return WIMLIB_ERR_INVALID_PARAM; if (write_flags & ~WIMLIB_WRITE_MASK_PUBLIC) return WIMLIB_ERR_INVALID_PARAM; if (!wim_has_metadata(wim)) return WIMLIB_ERR_METADATA_NOT_FOUND; if (wim_has_solid_resources(wim)) { ERROR("Splitting of WIM containing solid resources is not supported.\n" " Export it in non-solid format first."); return WIMLIB_ERR_UNSUPPORTED; } memset(&swm_info, 0, sizeof(swm_info)); swm_info.max_part_size = part_size; for (i = 0; i < wim->hdr.image_count; i++) { ret = add_blob_to_swm(wim->image_metadata[i]->metadata_blob, &swm_info); if (ret) goto out_free_swm_info; } ret = for_blob_in_table_sorted_by_sequential_order(wim->blob_table, add_blob_to_swm, &swm_info); if (ret) goto out_free_swm_info; ret = write_split_wim(wim, swm_name, &swm_info, write_flags); out_free_swm_info: FREE(swm_info.parts); return ret; }
/* Checksum all blobs that are unhashed (other than the metadata blobs), merging * them into the blob table as needed. This is a no-op unless files have been * added to an image in the same WIMStruct. */ int wim_checksum_unhashed_blobs(WIMStruct *wim) { int ret; if (!wim_has_metadata(wim)) return 0; for (int i = 0; i < wim->hdr.image_count; i++) { struct blob_descriptor *blob, *tmp; struct wim_image_metadata *imd = wim->image_metadata[i]; image_for_each_unhashed_blob_safe(blob, tmp, imd) { struct blob_descriptor *new_blob; ret = hash_unhashed_blob(blob, wim->blob_table, &new_blob); if (ret) return ret; if (new_blob != blob) free_blob_descriptor(blob); } } return 0; }
/* API function documented in wimlib.h */ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, int src_image, WIMStruct *dest_wim, const tchar *dest_name, const tchar *dest_description, int export_flags) { int ret; int start_src_image; int end_src_image; int orig_dest_image_count; int image; bool all_images = (src_image == WIMLIB_ALL_IMAGES); /* Check for sane parameters. */ if (export_flags & ~(WIMLIB_EXPORT_FLAG_BOOT | WIMLIB_EXPORT_FLAG_NO_NAMES | WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS | WIMLIB_EXPORT_FLAG_GIFT | WIMLIB_EXPORT_FLAG_WIMBOOT)) return WIMLIB_ERR_INVALID_PARAM; if (src_wim == NULL || dest_wim == NULL) return WIMLIB_ERR_INVALID_PARAM; if (!wim_has_metadata(src_wim) || !wim_has_metadata(dest_wim)) return WIMLIB_ERR_METADATA_NOT_FOUND; if (all_images) { /* Multi-image export. */ if ((!(export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) && dest_name) || (!(export_flags & WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS) && dest_description)) { ERROR("Image name and description must be " "left NULL for multi-image export"); return WIMLIB_ERR_INVALID_PARAM; } start_src_image = 1; end_src_image = src_wim->hdr.image_count; } else { start_src_image = src_image; end_src_image = src_image; } orig_dest_image_count = dest_wim->hdr.image_count; /* Stream checksums must be known before proceeding. */ ret = wim_checksum_unhashed_streams(src_wim); if (ret) return ret; ret = wim_checksum_unhashed_streams(dest_wim); if (ret) return ret; /* Enable rollbacks */ for_lookup_table_entry(dest_wim->lookup_table, lte_set_not_exported, NULL); /* Export each requested image. */ for (src_image = start_src_image; src_image <= end_src_image; src_image++) { const tchar *next_dest_name, *next_dest_description; struct wim_image_metadata *src_imd; struct wim_inode *inode; /* Determine destination image name and description. */ if (export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) next_dest_name = T(""); 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(""); else if (dest_description) next_dest_description = dest_description; else next_dest_description = wimlib_get_image_description(src_wim, src_image); /* Check for name conflict. */ if (wimlib_image_name_in_use(dest_wim, next_dest_name)) { ERROR("There is already an image named \"%"TS"\" " "in the destination WIM", next_dest_name); ret = WIMLIB_ERR_IMAGE_NAME_COLLISION; goto out_rollback; } /* Load metadata for source image into memory. */ ret = select_wim_image(src_wim, src_image); if (ret) goto out_rollback; src_imd = wim_get_current_image_metadata(src_wim); /* Iterate through inodes in the source image and export their * streams 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); 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); if (ret) goto out_rollback; /* Reference the source image metadata from the destination WIM. */ ret = append_image_metadata(dest_wim, src_imd); if (ret) goto out_rollback; src_imd->refcnt++; /* Lock the metadata into memory. XXX: need better solution for * this. */ src_imd->modified = 1; }
/* API function documented in wimlib.h */ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim, int src_image, WIMStruct *dest_wim, const tchar *dest_name, const tchar *dest_description, int export_flags) { int ret; int start_src_image; int end_src_image; int orig_dest_image_count; int image; bool all_images = (src_image == WIMLIB_ALL_IMAGES); /* Check for sane parameters. */ if (export_flags & ~(WIMLIB_EXPORT_FLAG_BOOT | WIMLIB_EXPORT_FLAG_NO_NAMES | WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS | WIMLIB_EXPORT_FLAG_GIFT | WIMLIB_EXPORT_FLAG_WIMBOOT)) return WIMLIB_ERR_INVALID_PARAM; if (!src_wim || !dest_wim) return WIMLIB_ERR_INVALID_PARAM; if (!wim_has_metadata(src_wim) || !wim_has_metadata(dest_wim)) return WIMLIB_ERR_METADATA_NOT_FOUND; if (all_images) { /* Multi-image export. */ if ((!(export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) && dest_name) || (!(export_flags & WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS) && dest_description)) { ERROR("Image name and description must be " "left NULL for multi-image export"); return WIMLIB_ERR_INVALID_PARAM; } start_src_image = 1; end_src_image = src_wim->hdr.image_count; } else { start_src_image = src_image; end_src_image = src_image; } orig_dest_image_count = dest_wim->hdr.image_count; /* 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_blobs(dest_wim); if (ret) return ret; /* Enable rollbacks */ for_blob_in_table(dest_wim->blob_table, blob_set_not_exported, NULL); /* Export each requested image. */ for (src_image = start_src_image; src_image <= end_src_image; src_image++) { const tchar *next_dest_name, *next_dest_description; struct wim_image_metadata *src_imd; struct wim_inode *inode; /* Determine destination image name and description. */ if (export_flags & WIMLIB_EXPORT_FLAG_NO_NAMES) 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 = NULL; else if (dest_description) next_dest_description = dest_description; else next_dest_description = wimlib_get_image_description(src_wim, src_image); /* Check for name conflict. */ if (wimlib_image_name_in_use(dest_wim, next_dest_name)) { ERROR("There is already an image named \"%"TS"\" " "in the destination WIM", next_dest_name); ret = WIMLIB_ERR_IMAGE_NAME_COLLISION; goto out_rollback; } /* Load metadata for source image into memory. */ ret = select_wim_image(src_wim, src_image); if (ret) goto out_rollback; src_imd = wim_get_current_image_metadata(src_wim); /* Iterate through inodes in the source image and export their * blobs into the destination WIM. */ image_for_each_inode(inode, src_imd) { 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->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; /* Reference the source image metadata from the destination WIM. */ ret = append_image_metadata(dest_wim, src_imd); if (ret) goto out_rollback; src_imd->refcnt++; }