void deselect_current_wim_image(WIMStruct *wim) { struct wim_image_metadata *imd; if (wim->current_image == WIMLIB_NO_IMAGE) return; imd = wim_get_current_image_metadata(wim); if (!imd->modified) { wimlib_assert(list_empty(&imd->unhashed_blobs)); destroy_image_metadata(imd, NULL, false); } wim->current_image = WIMLIB_NO_IMAGE; }
static void do_unlink(struct wim_dentry *subject, struct wim_dentry *parent, struct wim_dentry **root_p) { if (parent) { /* Unlink @subject from its @parent. */ wimlib_assert(subject->d_parent == parent); unlink_dentry(subject); } else { /* Unset @subject as the root of the image. */ *root_p = NULL; } subject->d_parent = subject; }
static void do_link(struct wim_dentry *subject, struct wim_dentry *parent, struct wim_dentry **root_p) { if (parent) { /* Link @subject to its @parent */ struct wim_dentry *existing; existing = dentry_add_child(parent, subject); wimlib_assert(!existing); } else { /* Set @subject as root of the image */ *root_p = subject; } }
static inline const tchar * update_op_to_str(int op) { switch (op) { case WIMLIB_UPDATE_OP_ADD: return T("add"); case WIMLIB_UPDATE_OP_DELETE: return T("delete"); case WIMLIB_UPDATE_OP_RENAME: return T("rename"); default: wimlib_assert(0); return NULL; } }
void * wimlib_aligned_malloc(size_t size, size_t alignment) { wimlib_assert(alignment != 0 && is_power_of_2(alignment) && alignment <= 4096); const uintptr_t mask = alignment - 1; char *ptr = NULL; char *raw_ptr; raw_ptr = MALLOC(mask + sizeof(size_t) + size); if (raw_ptr) { ptr = (char *)raw_ptr + sizeof(size_t); ptr = (void *)(((uintptr_t)ptr + mask) & ~mask); *((size_t *)ptr - 1) = ptr - raw_ptr; } return ptr; }
/* * write_integrity_table(): * * Writes a WIM integrity table (a list of SHA1 message digests of raw 10 MiB * chunks of the file). * * This function can optionally re-use entries from an older integrity table. * To do this, specify old_lookup_table_end and old_table. * * @wim: * WIMStruct for the WIM file. @wim->out_fd must be a seekable descriptor * to the new WIM file, opened read-write, positioned at the location at * which the integrity table is to be written. Furthermore, * @wim->hdr.integrity is expected to be a resource entry which will be set * to the integrity table information on success. In addition, if * @old_lookup_table_end != 0, @wim->hdr.integrity must initially contain * information about the old integrity table, and @wim->in_fd must be a * seekable descriptor to the original WIM file opened for reading. * * @new_lookup_table_end: * The offset of the byte directly following the lookup table in the WIM * being written. * * @old_lookup_table_end: * If nonzero, the offset of the byte directly following the old lookup * table in the WIM. * * @old_table * Pointer to the old integrity table read into memory, or NULL if not * specified. */ int write_integrity_table(WIMStruct *wim, off_t new_lookup_table_end, off_t old_lookup_table_end, struct integrity_table *old_table) { struct integrity_table *new_table; int ret; u32 new_table_size; DEBUG("Writing integrity table " "(new_lookup_table_end=%"PRIu64", old_lookup_table_end=%"PRIu64")", new_lookup_table_end, old_lookup_table_end); wimlib_assert(old_lookup_table_end <= new_lookup_table_end); ret = calculate_integrity_table(&wim->out_fd, new_lookup_table_end, old_table, old_lookup_table_end, &new_table, wim->progfunc, wim->progctx); if (ret) return ret; new_table_size = new_table->size; new_table->size = cpu_to_le32(new_table->size); new_table->num_entries = cpu_to_le32(new_table->num_entries); new_table->chunk_size = cpu_to_le32(new_table->chunk_size); ret = write_wim_resource_from_buffer(new_table, new_table_size, 0, &wim->out_fd, WIMLIB_COMPRESSION_TYPE_NONE, 0, &wim->hdr.integrity_table_reshdr, NULL, 0); FREE(new_table); DEBUG("ret=%d", ret); return ret; }
void * wimlib_aligned_malloc(size_t size, size_t alignment) { u8 *raw_ptr; u8 *ptr; uintptr_t mask; wimlib_assert(alignment != 0 && is_power_of_2(alignment) && alignment <= 4096); mask = alignment - 1; raw_ptr = MALLOC(size + alignment - 1 + sizeof(size_t)); if (!raw_ptr) return NULL; ptr = (u8 *)raw_ptr + sizeof(size_t); while ((uintptr_t)ptr & mask) ptr++; *((size_t *)ptr - 1) = (ptr - raw_ptr); return ptr; }
static int do_attach_branch(struct wim_dentry *branch, const utf16lechar *target, struct update_command_journal *j, int add_flags, wimlib_progress_func_t progfunc, void *progctx) { struct wim_dentry *parent; struct wim_dentry *existing; const utf16lechar empty_name[1] = {0}; const utf16lechar *cur_component_name; size_t cur_component_nbytes; const utf16lechar *next_component_name; int ret; /* Attempt to create root directory before proceeding to the "real" * first component */ parent = NULL; existing = *j->root_p; cur_component_name = empty_name; cur_component_nbytes = 0; /* Skip leading slashes */ next_component_name = target; while (*next_component_name == cpu_to_le16(WIM_PATH_SEPARATOR)) next_component_name++; while (*next_component_name) { /* While not the last component ... */ const utf16lechar *end; if (existing) { /* Descend into existing directory */ if (!dentry_is_directory(existing)) { ERROR("\"%"TS"\" in the WIM image " "is not a directory!", dentry_full_path(existing)); return WIMLIB_ERR_NOTDIR; } } else { /* A parent directory of the target didn't exist. Make * the way by creating a filler directory. */ struct wim_dentry *filler; ret = new_filler_directory(&filler); if (ret) return ret; ret = dentry_set_name_utf16le(filler, cur_component_name, cur_component_nbytes); if (ret) { free_dentry(filler); return ret; } ret = journaled_link(j, filler, parent); if (ret) { free_dentry(filler); return ret; } existing = filler; } /* Advance to next component */ cur_component_name = next_component_name; end = cur_component_name + 1; while (*end && *end != cpu_to_le16(WIM_PATH_SEPARATOR)) end++; next_component_name = end; if (*end) { /* There will still be more components after this. */ do { } while (*++next_component_name == cpu_to_le16(WIM_PATH_SEPARATOR)); wimlib_assert(*next_component_name); /* No trailing slashes */ } else { /* This will be the last component */ next_component_name = end; } parent = existing; cur_component_nbytes = (end - cur_component_name) * sizeof(utf16lechar); existing = get_dentry_child_with_utf16le_name( parent, cur_component_name, cur_component_nbytes, WIMLIB_CASE_PLATFORM_DEFAULT); } /* Last component */ if (existing) { return handle_conflict(branch, existing, j, add_flags, progfunc, progctx); } else { return journaled_link(j, branch, parent); } }
static int prepare_metadata_resource(WIMStruct *wim, int image, u8 **buf_ret, size_t *len_ret) { u8 *buf; u8 *p; int ret; u64 subdir_offset; struct wim_dentry *root; size_t len; struct wim_security_data *sd; struct wim_image_metadata *imd; ret = select_wim_image(wim, image); if (ret) return ret; imd = wim->image_metadata[image - 1]; root = imd->root_dentry; sd = imd->security_data; if (!root) { /* Empty image; create a dummy root. */ ret = new_filler_directory(&root); if (ret) return ret; imd->root_dentry = root; } /* The offset of the first child of the root dentry is equal to the * total length of the security data, plus the total length of the root * dentry, plus 8 bytes for an end-of-directory entry following the root * dentry (shouldn't really be needed, but just in case...) */ recalculate_security_data_length(sd); subdir_offset = sd->total_length + dentry_out_total_length(root) + 8; /* Calculate the subdirectory offsets for the entire dentry tree. */ calculate_subdir_offsets(root, &subdir_offset); /* Total length of the metadata resource (uncompressed). */ len = subdir_offset; /* Allocate a buffer to contain the uncompressed metadata resource. */ buf = NULL; if (likely(len == subdir_offset)) buf = MALLOC(len); if (!buf) { ERROR("Failed to allocate %"PRIu64" bytes for " "metadata resource", subdir_offset); return WIMLIB_ERR_NOMEM; } /* Write the security data into the resource buffer. */ p = write_wim_security_data(sd, buf); /* Write the dentry tree into the resource buffer. */ p = write_dentry_tree(root, p); /* We MUST have exactly filled the buffer; otherwise we calculated its * size incorrectly or wrote the data incorrectly. */ wimlib_assert(p - buf == len); *buf_ret = buf; *len_ret = len; return 0; }