/* 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; }
/* * 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; }