Exemple #1
0
/* API function documented in wimlib.h  */
WIMLIBAPI int
wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
{
	int ret;

	ret = can_modify_wim(wim);
	if (ret)
		return ret;

	if (!name)
		name = T("");

	if (wimlib_image_name_in_use(wim, name)) {
		ERROR("There is already an image named \"%"TS"\" in the WIM!",
		      name);
		return WIMLIB_ERR_IMAGE_NAME_COLLISION;
	}

	ret = add_empty_image_metadata(wim);
	if (ret)
		return ret;

	ret = xml_add_image(wim, name);
	if (ret) {
		put_image_metadata(wim->image_metadata[--wim->hdr.image_count],
				   NULL);
		return ret;
	}

	if (new_idx_ret)
		*new_idx_ret = wim->hdr.image_count;
	return 0;
}
Exemple #2
0
/*
 * Begins the reading of a WIM file; opens the file and reads its header and
 * blob table, and optionally checks the integrity.
 */
static int
begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags)
{
    int ret;
    int xml_num_images;
    const tchar *wimfile;

    if (open_flags & WIMLIB_OPEN_FLAG_FROM_PIPE) {
        wimfile = NULL;
        filedes_init(&wim->in_fd, *(const int*)wim_filename_or_fd);
        wim->in_fd.is_pipe = 1;
    } else {
        wimfile = wim_filename_or_fd;
        ret = open_wim_file(wimfile, &wim->in_fd);
        if (ret)
            return ret;

        /* The absolute path to the WIM is requested so that
         * wimlib_overwrite() still works even if the process changes
         * its working directory.  This actually happens if a WIM is
         * mounted read-write, since the FUSE thread changes directory
         * to "/", and it needs to be able to find the WIM file again.
         *
         * This will break if the full path to the WIM changes in the
         * intervening time...
         *
         * Warning: in Windows native builds, realpath() calls the
         * replacement function in win32_replacements.c.
         */
        wim->filename = realpath(wimfile, NULL);
        if (!wim->filename) {
            ERROR_WITH_ERRNO("Failed to get full path to file "
                             "\"%"TS"\"", wimfile);
            if (errno == ENOMEM)
                return WIMLIB_ERR_NOMEM;
            else
                return WIMLIB_ERR_NO_FILENAME;
        }
    }

    ret = read_wim_header(wim, &wim->hdr);
    if (ret)
        return ret;

    if (wim->hdr.flags & WIM_HDR_FLAG_WRITE_IN_PROGRESS) {
        WARNING("The WIM_HDR_FLAG_WRITE_IN_PROGRESS flag is set in the header of\n"
                "          \"%"TS"\".  It may be being changed by another process,\n"
                "          or a process may have crashed while writing the WIM.",
                wimfile);
    }

    if (open_flags & WIMLIB_OPEN_FLAG_WRITE_ACCESS) {
        ret = can_modify_wim(wim);
        if (ret)
            return ret;
    }

    if ((open_flags & WIMLIB_OPEN_FLAG_ERROR_IF_SPLIT) &&
            (wim->hdr.total_parts != 1))
        return WIMLIB_ERR_IS_SPLIT_WIM;

    /* If the boot index is invalid, print a warning and set it to 0 */
    if (wim->hdr.boot_idx > wim->hdr.image_count) {
        WARNING("Ignoring invalid boot index.");
        wim->hdr.boot_idx = 0;
    }

    /* Check and cache the compression type */
    if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESSION) {
        if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_LZX) {
            wim->compression_type = WIMLIB_COMPRESSION_TYPE_LZX;
        } else if (wim->hdr.flags & (WIM_HDR_FLAG_COMPRESS_XPRESS |
                                     WIM_HDR_FLAG_COMPRESS_XPRESS_2)) {
            wim->compression_type = WIMLIB_COMPRESSION_TYPE_XPRESS;
        } else if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_LZMS) {
            wim->compression_type = WIMLIB_COMPRESSION_TYPE_LZMS;
        } else {
            return WIMLIB_ERR_INVALID_COMPRESSION_TYPE;
        }
    } else {
        wim->compression_type = WIMLIB_COMPRESSION_TYPE_NONE;
    }
    wim->out_compression_type = wim->compression_type;

    /* Check and cache the chunk size.  */
    wim->chunk_size = wim->hdr.chunk_size;
    wim->out_chunk_size = wim->chunk_size;
    if (!wim_chunk_size_valid(wim->chunk_size, wim->compression_type)) {
        ERROR("Invalid chunk size (%"PRIu32" bytes) "
              "for compression type %"TS"!", wim->chunk_size,
              wimlib_get_compression_type_string(wim->compression_type));
        return WIMLIB_ERR_INVALID_CHUNK_SIZE;
    }

    if (open_flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) {
        ret = check_wim_integrity(wim);
        if (ret == WIM_INTEGRITY_NONEXISTENT) {
            WARNING("\"%"TS"\" does not contain integrity "
                    "information.  Skipping integrity check.",
                    wimfile);
        } else if (ret == WIM_INTEGRITY_NOT_OK) {
            return WIMLIB_ERR_INTEGRITY;
        } else if (ret != WIM_INTEGRITY_OK) {
            return ret;
        }
    }

    if (wim->hdr.image_count != 0 && wim->hdr.part_number == 1) {
        wim->image_metadata = new_image_metadata_array(wim->hdr.image_count);
        if (!wim->image_metadata)
            return WIMLIB_ERR_NOMEM;
    }

    if (open_flags & WIMLIB_OPEN_FLAG_FROM_PIPE) {
        wim->blob_table = new_blob_table(9001);
        if (!wim->blob_table)
            return WIMLIB_ERR_NOMEM;
    } else {

        ret = read_wim_xml_data(wim);
        if (ret)
            return ret;

        xml_num_images = wim_info_get_num_images(wim->wim_info);
        if (xml_num_images != wim->hdr.image_count) {
            ERROR("The WIM's header is inconsistent with its XML data.\n"
                  "        Please submit a bug report if you believe this "
                  "WIM file should be considered valid.");
            return WIMLIB_ERR_IMAGE_COUNT;
        }

        ret = read_blob_table(wim);
        if (ret)
            return ret;
    }
    return 0;
}