#endif
#ifndef __WIN32__
-static int extract_regular_file_linked(struct wim_dentry *dentry,
- const char *output_path,
- struct apply_args *args,
- struct wim_lookup_table_entry *lte)
+
+/* Returns the number of components of @path. */
+static unsigned
+get_num_path_components(const char *path)
+{
+ unsigned num_components = 0;
+ while (*path) {
+ while (*path == '/')
+ path++;
+ if (*path)
+ num_components++;
+ while (*path && *path != '/')
+ path++;
+ }
+ return num_components;
+}
+
+static const char *
+path_next_part(const char *path)
+{
+ while (*path && *path != '/')
+ path++;
+ while (*path && *path == '/')
+ path++;
+ return path;
+}
+
+static int
+extract_regular_file_linked(struct wim_dentry *dentry,
+ const char *output_path,
+ struct apply_args *args,
+ struct wim_lookup_table_entry *lte)
{
/* This mode overrides the normal hard-link extraction and
* instead either symlinks or hardlinks *all* identical files in
size_t i;
num_path_components =
- get_num_path_components(dentry->full_path_utf8) - 1;
+ get_num_path_components(dentry->full_path) - 1;
num_output_dir_path_components =
get_num_path_components(args->target);
p2 = lte->extracted_file;
while (*p2 == '/')
p2++;
- while (num_output_dir_path_components--)
- p2 = path_next_part(p2, NULL);
+ while (num_output_dir_path_components > 0) {
+ p2 = path_next_part(p2);
+ num_output_dir_path_components--;
+ }
strcpy(p, p2);
if (symlink(buf, output_path) != 0) {
- ERROR_WITH_ERRNO("Failed to symlink `%s' to "
- "`%s'",
+ ERROR_WITH_ERRNO("Failed to symlink `%s' to `%s'",
buf, lte->extracted_file);
return WIMLIB_ERR_LINK;
}
return 0;
}
-static int symlink_apply_unix_data(const char *link,
- const struct wimlib_unix_data *unix_data)
+static int
+symlink_apply_unix_data(const char *link,
+ const struct wimlib_unix_data *unix_data)
{
if (lchown(link, unix_data->uid, unix_data->gid)) {
if (errno == EPERM) {
return 0;
}
-static int fd_apply_unix_data(int fd, const struct wimlib_unix_data *unix_data)
+static int
+fd_apply_unix_data(int fd, const struct wimlib_unix_data *unix_data)
{
if (fchown(fd, unix_data->uid, unix_data->gid)) {
if (errno == EPERM) {
return 0;
}
-static int dir_apply_unix_data(const char *dir,
- const struct wimlib_unix_data *unix_data)
+static int
+dir_apply_unix_data(const char *dir, const struct wimlib_unix_data *unix_data)
{
int dfd = open(dir, O_RDONLY);
int ret;
return ret;
}
-static int extract_regular_file_unlinked(struct wim_dentry *dentry,
- struct apply_args *args,
- const char *output_path,
- struct wim_lookup_table_entry *lte)
+static int
+extract_regular_file_unlinked(struct wim_dentry *dentry,
+ struct apply_args *args,
+ const char *output_path,
+ struct wim_lookup_table_entry *lte)
{
/* Normal mode of extraction. Regular files and hard links are
* extracted in the way that they appear in the WIM. */
return ret;
}
-static int extract_regular_file(struct wim_dentry *dentry,
- struct apply_args *args,
- const char *output_path)
+static int
+extract_regular_file(struct wim_dentry *dentry,
+ struct apply_args *args,
+ const char *output_path)
{
struct wim_lookup_table_entry *lte;
const struct wim_inode *inode = dentry->d_inode;
return extract_regular_file_unlinked(dentry, args, output_path, lte);
}
-static int extract_symlink(struct wim_dentry *dentry,
- struct apply_args *args,
- const char *output_path)
+static int
+extract_symlink(struct wim_dentry *dentry,
+ struct apply_args *args,
+ const char *output_path)
{
char target[4096];
ssize_t ret = inode_readlink(dentry->d_inode, target,
if (ret <= 0) {
ERROR("Could not read the symbolic link from dentry `%s'",
- dentry->full_path_utf8);
+ dentry->full_path);
return WIMLIB_ERR_INVALID_DENTRY;
}
ret = symlink(target, output_path);
#endif /* !__WIN32__ */
-static int extract_directory(struct wim_dentry *dentry,
- const char *output_path, bool is_root)
+static int
+extract_directory(struct wim_dentry *dentry,
+ const tchar *output_path, bool is_root)
{
int ret;
struct stat stbuf;
- ret = stat(output_path, &stbuf);
+ ret = tstat(output_path, &stbuf);
if (ret == 0) {
if (S_ISDIR(stbuf.st_mode)) {
/*if (!is_root)*/
/*WARNING("`%s' already exists", output_path);*/
goto dir_exists;
} else {
- ERROR("`%s' is not a directory", output_path);
+ ERROR("`%"TS"' is not a directory", output_path);
return WIMLIB_ERR_MKDIR;
}
} else {
if (errno != ENOENT) {
- ERROR_WITH_ERRNO("Failed to stat `%s'", output_path);
+ ERROR_WITH_ERRNO("Failed to stat `%"TS"'", output_path);
return WIMLIB_ERR_STAT;
}
}
- if (mkdir(output_path, S_IRWXU | S_IRGRP | S_IXGRP |
- S_IROTH | S_IXOTH) != 0) {
- ERROR_WITH_ERRNO("Cannot create directory `%s'",
- output_path);
+
+ if (tmkdir(output_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH))
+ {
+ ERROR_WITH_ERRNO("Cannot create directory `%"TS"'", output_path);
return WIMLIB_ERR_MKDIR;
}
dir_exists:
return extract_regular_file(dentry, args, output_path);
}
-static int unix_do_apply_dentry_timestamps(const char *output_path,
- size_t output_path_len,
- const struct wim_dentry *dentry,
- struct apply_args *args)
+static int
+unix_do_apply_dentry_timestamps(const char *output_path,
+ size_t output_path_len,
+ const struct wim_dentry *dentry,
+ struct apply_args *args)
{
int ret;
const struct wim_inode *inode = dentry->d_inode;
#endif /* !__WIN32__ */
/* Extracts a file, directory, or symbolic link from the WIM archive. */
-static int apply_dentry_normal(struct wim_dentry *dentry, void *arg)
+static int
+apply_dentry_normal(struct wim_dentry *dentry, void *arg)
{
struct apply_args *args = arg;
+ tchar *output_path;
size_t len;
- char *output_path;
- len = strlen(args->target);
+ len = tstrlen(args->target);
if (dentry_is_root(dentry)) {
- output_path = (char*)args->target;
+ output_path = (tchar*)args->target;
} else {
- output_path = alloca(len + dentry->full_path_utf8_len + 1);
- memcpy(output_path, args->target, len);
- memcpy(output_path + len, dentry->full_path_utf8, dentry->full_path_utf8_len);
- output_path[len + dentry->full_path_utf8_len] = '\0';
- len += dentry->full_path_utf8_len;
+ output_path = alloca(len * sizeof(tchar) + dentry->full_path_nbytes +
+ sizeof(tchar));
+ memcpy(output_path, args->target, len * sizeof(tchar));
+ memcpy(output_path + len, dentry->full_path, dentry->full_path_nbytes);
+ len += dentry->full_path_nbytes / sizeof(tchar);
+ output_path[len] = T('\0');
}
#ifdef __WIN32__
return win32_do_apply_dentry(output_path, len, dentry, args);
/* Apply timestamps to an extracted file or directory */
-static int apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg)
+static int
+apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg)
{
struct apply_args *args = arg;
size_t len;
- char *output_path;
+ tchar *output_path;
- len = strlen(args->target);
+ len = tstrlen(args->target);
if (dentry_is_root(dentry)) {
- output_path = (char*)args->target;
+ output_path = (tchar*)args->target;
} else {
- output_path = alloca(len + dentry->full_path_utf8_len + 1);
- memcpy(output_path, args->target, len);
- memcpy(output_path + len, dentry->full_path_utf8, dentry->full_path_utf8_len);
- output_path[len + dentry->full_path_utf8_len] = '\0';
- len += dentry->full_path_utf8_len;
+ output_path = alloca(len * sizeof(tchar) + dentry->full_path_nbytes +
+ sizeof(tchar));
+ memcpy(output_path, args->target, len * sizeof(tchar));
+ memcpy(output_path + len, dentry->full_path, dentry->full_path_nbytes);
+ len += dentry->full_path_nbytes / sizeof(tchar);
+ output_path[len] = T('\0');
}
+
+
#ifdef __WIN32__
return win32_do_apply_dentry_timestamps(output_path, len, dentry, args);
#else
/* Extract a dentry if it hasn't already been extracted, and either the dentry
* has no streams or WIMLIB_EXTRACT_FLAG_NO_STREAMS is not specified. */
-static int maybe_apply_dentry(struct wim_dentry *dentry, void *arg)
+static int
+maybe_apply_dentry(struct wim_dentry *dentry, void *arg)
{
struct apply_args *args = arg;
int ret;
if ((args->extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE) &&
args->progress_func) {
- args->progress.extract.cur_path = dentry->full_path_utf8;
+ args->progress.extract.cur_path = dentry->full_path;
args->progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DENTRY,
&args->progress);
}
return ret;
}
-static int cmp_streams_by_wim_position(const void *p1, const void *p2)
+static int
+cmp_streams_by_wim_position(const void *p1, const void *p2)
{
const struct wim_lookup_table_entry *lte1, *lte2;
lte1 = *(const struct wim_lookup_table_entry**)p1;
return 0;
}
-static int sort_stream_list_by_wim_position(struct list_head *stream_list)
+static int
+sort_stream_list_by_wim_position(struct list_head *stream_list)
{
struct list_head *cur;
size_t num_streams;
return 0;
}
-static void calculate_bytes_to_extract(struct list_head *stream_list,
- int extract_flags,
- union wimlib_progress_info *progress)
+static void
+calculate_bytes_to_extract(struct list_head *stream_list,
+ int extract_flags,
+ union wimlib_progress_info *progress)
{
struct wim_lookup_table_entry *lte;
u64 total_bytes = 0;
progress->extract.completed_bytes = 0;
}
-static void maybe_add_stream_for_extraction(struct wim_lookup_table_entry *lte,
- struct list_head *stream_list)
+static void
+maybe_add_stream_for_extraction(struct wim_lookup_table_entry *lte,
+ struct list_head *stream_list)
{
if (++lte->out_refcnt == 1) {
INIT_LIST_HEAD(<e->inode_list);
}
}
-static void inode_find_streams_for_extraction(struct wim_inode *inode,
- struct list_head *stream_list,
- int extract_flags)
+static void
+inode_find_streams_for_extraction(struct wim_inode *inode,
+ struct list_head *stream_list,
+ int extract_flags)
{
struct wim_lookup_table_entry *lte;
bool inode_added = false;
#ifdef WITH_NTFS_3G
if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
for (unsigned i = 0; i < inode->i_num_ads; i++) {
- if (inode->i_ads_entries[i].stream_name_len != 0) {
+ if (inode->i_ads_entries[i].stream_name_nbytes != 0) {
lte = inode->i_ads_entries[i].lte;
if (lte) {
maybe_add_stream_for_extraction(lte,
#endif
}
-static void find_streams_for_extraction(struct hlist_head *inode_list,
- struct list_head *stream_list,
- struct wim_lookup_table *lookup_table,
- int extract_flags)
+static void
+find_streams_for_extraction(struct hlist_head *inode_list,
+ struct list_head *stream_list,
+ struct wim_lookup_table *lookup_table,
+ int extract_flags)
{
struct wim_inode *inode;
struct hlist_node *cur;
};
#endif
-static int apply_stream_list(struct list_head *stream_list,
- struct apply_args *args,
- const struct apply_operations *ops,
- wimlib_progress_func_t progress_func)
+static int
+apply_stream_list(struct list_head *stream_list,
+ struct apply_args *args,
+ const struct apply_operations *ops,
+ wimlib_progress_func_t progress_func)
{
uint64_t bytes_per_progress = args->progress.extract.total_bytes / 100;
uint64_t next_progress = bytes_per_progress;
/* Extracts the image @image from the WIM @w to the directory or NTFS volume
* @target. */
-static int extract_single_image(WIMStruct *w, int image,
- const char *target, int extract_flags,
- wimlib_progress_func_t progress_func)
+static int
+extract_single_image(WIMStruct *w, int image,
+ const tchar *target, int extract_flags,
+ wimlib_progress_func_t progress_func)
{
int ret;
struct list_head stream_list;
if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
args.vol = ntfs_mount(target, 0);
if (!args.vol) {
- ERROR_WITH_ERRNO("Failed to mount NTFS volume `%s'", target);
+ ERROR_WITH_ERRNO("Failed to mount NTFS volume `%"TS"'",
+ target);
return WIMLIB_ERR_NTFS_3G;
}
ops = &ntfs_apply_operations;
/* Unmount the NTFS volume */
if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
if (ntfs_umount(args.vol, FALSE) != 0) {
- ERROR_WITH_ERRNO("Failed to unmount NTFS volume `%s'", args.target);
+ ERROR_WITH_ERRNO("Failed to unmount NTFS volume `%"TS"'",
+ args.target);
if (ret == 0)
ret = WIMLIB_ERR_NTFS_3G;
}
return ret;
}
+static const tchar *filename_forbidden_chars =
+T(
+#ifdef __WIN32__
+"<>:\"/\\|?*"
+#else
+"/"
+#endif
+);
+
+/* This function checks if it is okay to use a WIM image's name as a directory
+ * name. */
+static bool
+image_name_ok_as_dir(const tchar *image_name)
+{
+ return image_name && *image_name &&
+ !tstrpbrk(image_name, filename_forbidden_chars);
+}
/* Extracts all images from the WIM to the directory @target, with the images
* placed in subdirectories named by their image names. */
-static int extract_all_images(WIMStruct *w, const char *target,
- int extract_flags,
- wimlib_progress_func_t progress_func)
+static int
+extract_all_images(WIMStruct *w,
+ const tchar *target,
+ int extract_flags,
+ wimlib_progress_func_t progress_func)
{
size_t image_name_max_len = max(xml_get_max_image_name_len(w), 20);
- size_t output_path_len = strlen(target);
- char buf[output_path_len + 1 + image_name_max_len + 1];
+ size_t output_path_len = tstrlen(target);
+ tchar buf[output_path_len + 1 + image_name_max_len + 1];
int ret;
int image;
- const char *image_name;
+ const tchar *image_name;
ret = extract_directory(NULL, target, true);
- if (ret != 0)
+ if (ret)
return ret;
- memcpy(buf, target, output_path_len);
- buf[output_path_len] = '/';
+ tmemcpy(buf, target, output_path_len);
+ buf[output_path_len] = T('/');
for (image = 1; image <= w->hdr.image_count; image++) {
image_name = wimlib_get_image_name(w, image);
- if (image_name && *image_name) {
- strcpy(buf + output_path_len + 1, image_name);
+ if (image_name_ok_as_dir(image_name)) {
+ tstrcpy(buf + output_path_len + 1, image_name);
} else {
- /* Image name is empty. Use image number instead */
- sprintf(buf + output_path_len + 1, "%d", image);
+ /* Image name is empty, or contains forbidden
+ * characters. */
+ tsprintf(buf + output_path_len + 1, T("%d"), image);
}
ret = extract_single_image(w, image, buf, extract_flags,
progress_func);
/* Extracts a single image or all images from a WIM file to a directory or NTFS
* volume. */
-WIMLIBAPI int wimlib_extract_image(WIMStruct *w,
- int image,
- const char *target,
- int extract_flags,
- WIMStruct **additional_swms,
- unsigned num_additional_swms,
- wimlib_progress_func_t progress_func)
+WIMLIBAPI int
+wimlib_extract_image(WIMStruct *w,
+ int image,
+ const tchar *target,
+ int extract_flags,
+ WIMStruct **additional_swms,
+ unsigned num_additional_swms,
+ wimlib_progress_func_t progress_func)
{
struct wim_lookup_table *joined_tab, *w_tab_save;
int ret;
w->lookup_table = joined_tab;
}
-#ifdef __WIN32__
- win32_acquire_restore_privileges();
-#endif
if (image == WIMLIB_ALL_IMAGES) {
extract_flags |= WIMLIB_EXTRACT_FLAG_MULTI_IMAGE;
ret = extract_all_images(w, target, extract_flags,
ret = extract_single_image(w, image, target, extract_flags,
progress_func);
}
-#ifdef __WIN32__
- win32_release_restore_privileges();
-#endif
if (extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK |
WIMLIB_EXTRACT_FLAG_HARDLINK))