Example #1
0
File: wim.c Project: twwbond/wimlib
/*
 * 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;
}
Example #2
0
/* 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;
}
Example #3
0
File: wim.c Project: twwbond/wimlib
/* 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;
}
Example #4
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;

	}
Example #5
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 || !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++;
	}