예제 #1
0
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);
	}
}
예제 #2
0
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;
}