X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fextract_image.c;h=5f311766364f1ae17beee27fc079da8c625fc265;hb=fe6c34ebb7d5adeeceeed22142e080965d85a1eb;hp=963f40c751e84c6a29fe35ca8b12310c335218e2;hpb=541b65d79e0c73238a25e2c2661711d8593d0684;p=wimlib diff --git a/src/extract_image.c b/src/extract_image.c index 963f40c7..5f311766 100644 --- a/src/extract_image.c +++ b/src/extract_image.c @@ -58,9 +58,36 @@ #endif #ifndef __WIN32__ + +/* 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 mbchar *output_path, + const char *output_path, struct apply_args *args, struct wim_lookup_table_entry *lte) { @@ -80,8 +107,8 @@ extract_regular_file_linked(struct wim_dentry *dentry, int num_path_components; int num_output_dir_path_components; size_t extracted_file_len; - mbchar *p; - const mbchar *p2; + char *p; + const char *p2; size_t i; num_path_components = @@ -95,7 +122,7 @@ extract_regular_file_linked(struct wim_dentry *dentry, } extracted_file_len = strlen(lte->extracted_file); - mbchar buf[extracted_file_len + 3 * num_path_components + 1]; + char buf[extracted_file_len + 3 * num_path_components + 1]; p = &buf[0]; for (i = 0; i < num_path_components; i++) { @@ -106,8 +133,10 @@ extract_regular_file_linked(struct wim_dentry *dentry, 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'", @@ -119,7 +148,7 @@ extract_regular_file_linked(struct wim_dentry *dentry, } static int -symlink_apply_unix_data(const mbchar *link, +symlink_apply_unix_data(const char *link, const struct wimlib_unix_data *unix_data) { if (lchown(link, unix_data->uid, unix_data->gid)) { @@ -160,7 +189,7 @@ fd_apply_unix_data(int fd, const struct wimlib_unix_data *unix_data) } static int -dir_apply_unix_data(const mbchar *dir, const struct wimlib_unix_data *unix_data) +dir_apply_unix_data(const char *dir, const struct wimlib_unix_data *unix_data) { int dfd = open(dir, O_RDONLY); int ret; @@ -180,7 +209,7 @@ dir_apply_unix_data(const mbchar *dir, const struct wimlib_unix_data *unix_data) static int extract_regular_file_unlinked(struct wim_dentry *dentry, struct apply_args *args, - const mbchar *output_path, + const char *output_path, struct wim_lookup_table_entry *lte) { /* Normal mode of extraction. Regular files and hard links are @@ -271,7 +300,7 @@ out: static int extract_regular_file(struct wim_dentry *dentry, struct apply_args *args, - const mbchar *output_path) + const char *output_path) { struct wim_lookup_table_entry *lte; const struct wim_inode *inode = dentry->d_inode; @@ -295,9 +324,9 @@ extract_regular_file(struct wim_dentry *dentry, static int extract_symlink(struct wim_dentry *dentry, struct apply_args *args, - const mbchar *output_path) + const char *output_path) { - mbchar target[4096]; + char target[4096]; ssize_t ret = inode_readlink(dentry->d_inode, target, sizeof(target), args->w, 0); struct wim_lookup_table_entry *lte; @@ -335,31 +364,31 @@ extract_symlink(struct wim_dentry *dentry, static int extract_directory(struct wim_dentry *dentry, - const mbchar *output_path, bool is_root) + 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)) + if (tmkdir(output_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) { - ERROR_WITH_ERRNO("Cannot create directory `%s'", output_path); + ERROR_WITH_ERRNO("Cannot create directory `%"TS"'", output_path); return WIMLIB_ERR_MKDIR; } dir_exists: @@ -380,7 +409,7 @@ dir_exists: } #ifndef __WIN32__ -static int unix_do_apply_dentry(const mbchar *output_path, +static int unix_do_apply_dentry(const char *output_path, size_t output_path_len, struct wim_dentry *dentry, struct apply_args *args) @@ -398,7 +427,7 @@ static int unix_do_apply_dentry(const mbchar *output_path, } static int -unix_do_apply_dentry_timestamps(const mbchar *output_path, +unix_do_apply_dentry_timestamps(const char *output_path, size_t output_path_len, const struct wim_dentry *dentry, struct apply_args *args) @@ -463,18 +492,19 @@ static int apply_dentry_normal(struct wim_dentry *dentry, void *arg) { struct apply_args *args = arg; + tchar *output_path; size_t len; - mbchar *output_path; - len = strlen(args->target); + len = tstrlen(args->target); if (dentry_is_root(dentry)) { - output_path = (mbchar*)args->target; + output_path = (tchar*)args->target; } else { - output_path = alloca(len + dentry->full_path_nbytes + 1); - memcpy(output_path, args->target, 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); - output_path[len + dentry->full_path_nbytes] = '\0'; - len += 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); @@ -490,19 +520,21 @@ apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg) { struct apply_args *args = arg; size_t len; - mbchar *output_path; + tchar *output_path; - len = strlen(args->target); + len = tstrlen(args->target); if (dentry_is_root(dentry)) { - output_path = (mbchar*)args->target; + output_path = (tchar*)args->target; } else { - output_path = alloca(len + dentry->full_path_nbytes + 1); - memcpy(output_path, args->target, 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); - output_path[len + dentry->full_path_nbytes] = '\0'; - len += 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 @@ -758,7 +790,7 @@ apply_stream_list(struct list_head *stream_list, * @target. */ static int extract_single_image(WIMStruct *w, int image, - const mbchar *target, int extract_flags, + const tchar *target, int extract_flags, wimlib_progress_func_t progress_func) { int ret; @@ -768,11 +800,11 @@ extract_single_image(WIMStruct *w, int image, struct apply_args args; const struct apply_operations *ops; + memset(&args, 0, sizeof(args)); + args.w = w; args.target = target; args.extract_flags = extract_flags; - args.num_utime_warnings = 0; - args.stream_list = &stream_list; args.progress_func = progress_func; if (progress_func) { @@ -788,7 +820,8 @@ extract_single_image(WIMStruct *w, int image, 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; @@ -869,7 +902,8 @@ out: /* 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; } @@ -878,39 +912,53 @@ out: 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 mbchar *target, +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); - mbchar 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 utf8char *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 && - (wimlib_mbs_is_utf8 || !utf8_str_contains_nonascii_chars(image_name)) - && strchr(image_name, '/') == NULL) - { - 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, or may not be representable in - * the current locale, or contains path separators. Use - * the 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); @@ -925,7 +973,7 @@ extract_all_images(WIMStruct *w, const mbchar *target, WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image, - const mbchar *target, + const tchar *target, int extract_flags, WIMStruct **additional_swms, unsigned num_additional_swms,