From 5873df008e648b9646b07c7d4eeda511adf92e28 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 21 Apr 2013 16:57:30 -0500 Subject: [PATCH] Misc. fixes --- src/dentry.c | 29 +++++++++-- src/extract_image.c | 2 +- src/hardlink.c | 5 -- src/lookup_table.c | 28 +++++++++++ src/lookup_table.h | 49 +++++------------- src/mount_image.c | 114 +++++++++++++++++++++++++++--------------- src/ntfs-apply.c | 65 ++++++++++++------------ src/ntfs-capture.c | 59 +++++++++++++--------- src/resource.c | 2 +- src/sha1.h | 2 +- src/wim.c | 2 +- src/wimlib_internal.h | 1 - src/win32.c | 2 +- src/write.c | 34 +++++++------ 14 files changed, 234 insertions(+), 160 deletions(-) diff --git a/src/dentry.c b/src/dentry.c index b0ebf64d..5b19f6f5 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -589,9 +589,6 @@ print_dentry_full_path(struct wim_dentry *dentry, void *_ignore) if (ret) return ret; tprintf(T("%"TS"\n"), dentry->_full_path); - FREE(dentry->_full_path); - dentry->_full_path = NULL; - dentry->full_path_nbytes = 0; return 0; } @@ -1211,6 +1208,29 @@ inode_set_unix_data(struct wim_inode *inode, uid_t uid, gid_t gid, mode_t mode, } #endif /* !__WIN32__ */ +static void +replace_forbidden_characters(utf16lechar *name) +{ + utf16lechar *p; + + for (p = name; *p; p++) { + #ifdef __WIN32__ + if (wcschr(L"<>:\"/\\|?*", (wchar_t)*p)) + #else + if (*p == '/') { + #endif + if (name) { + WARNING("File, directory, or stream name \"%"WS"\"\n" + " contains forbidden characters; " + "replacing them with Unicode codepoint U+001A", + name); + name = NULL; + } + *p = 0x1a; + } + } +} + /* * Reads the alternate data stream entries of a WIM dentry. * @@ -1338,6 +1358,7 @@ read_ads_entries(const u8 *p, struct wim_inode *inode, u64 remaining_size) get_bytes(p, cur_entry->stream_name_nbytes, cur_entry->stream_name); cur_entry->stream_name[cur_entry->stream_name_nbytes / 2] = 0; + replace_forbidden_characters(cur_entry->stream_name); } /* It's expected that the size of every ADS entry is a multiple * of 8. However, to be safe, I'm allowing the possibility of @@ -1511,6 +1532,7 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, WARNING("File name in WIM dentry \"%"WS"\" is not " "null-terminated!", file_name); } + replace_forbidden_characters(file_name); } /* Align the calculated size */ @@ -1561,6 +1583,7 @@ read_dentry(const u8 metadata_resource[], u64 metadata_resource_len, WARNING("Short name in WIM dentry \"%"WS"\" is not " "null-terminated!", file_name); } + replace_forbidden_characters(short_name); } /* diff --git a/src/extract_image.c b/src/extract_image.c index 8941b0e7..fffdcfd1 100644 --- a/src/extract_image.c +++ b/src/extract_image.c @@ -898,7 +898,7 @@ out: return ret; } -static const tchar *filename_forbidden_chars = +static const tchar * const filename_forbidden_chars = T( #ifdef __WIN32__ "<>:\"/\\|?*" diff --git a/src/hardlink.c b/src/hardlink.c index b2d33093..f806c7fe 100644 --- a/src/hardlink.c +++ b/src/hardlink.c @@ -159,11 +159,6 @@ inode_ref_streams(struct wim_inode *inode) } } -void -inode_add_link(struct wim_inode *inode, struct wim_dentry *dentry) -{ -} - /* Given a directory entry with the name @name for the file with the inode * number @ino and device number @devno, create a new WIM dentry with an * associated inode, where the inode is shared if an inode with the same @ino diff --git a/src/lookup_table.c b/src/lookup_table.c index f22bfaf7..c6b45fed 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -865,6 +865,34 @@ inode_stream_lte(const struct wim_inode *inode, unsigned stream_idx, return inode_stream_lte_unresolved(inode, stream_idx, table); } +struct wim_lookup_table_entry * +inode_unnamed_lte_resolved(const struct wim_inode *inode) +{ + wimlib_assert(inode->i_resolved); + for (unsigned i = 0; i <= inode->i_num_ads; i++) { + if (inode_stream_name_nbytes(inode, i) == 0 && + !is_zero_hash(inode_stream_hash_resolved(inode, i))) + { + return inode_stream_lte_resolved(inode, i); + } + } + return NULL; +} + +struct wim_lookup_table_entry * +inode_unnamed_lte_unresolved(const struct wim_inode *inode, + const struct wim_lookup_table *table) +{ + wimlib_assert(!inode->i_resolved); + for (unsigned i = 0; i <= inode->i_num_ads; i++) { + if (inode_stream_name_nbytes(inode, i) == 0 && + !is_zero_hash(inode_stream_hash_unresolved(inode, i))) + { + return inode_stream_lte_unresolved(inode, i, table); + } + } + return NULL; +} /* Return the lookup table entry for the unnamed data stream of an inode, or * NULL if there is none. diff --git a/src/lookup_table.h b/src/lookup_table.h index 2a6bf89b..d9d8959c 100644 --- a/src/lookup_table.h +++ b/src/lookup_table.h @@ -63,11 +63,9 @@ enum resource_location { * WIM file will be pointed to by the @wim member. */ RESOURCE_IN_WIM, - /* The stream resource is located in an external file. The name of the - * file will be provided by @file_on_disk member. In addition, if - * @file_on_disk_fp is not NULL, it will be an open FILE * to the file. - * */ #ifndef __WIN32__ + /* The stream resource is located in an external file. The name of the + * file will be provided by @file_on_disk member. */ RESOURCE_IN_FILE_ON_DISK, #endif @@ -143,9 +141,10 @@ struct wim_lookup_table_entry { /* 1 if this stream is a unique size (only set while writing streams). */ u8 unique_size : 1; - /* 1 if this stream had a SHA1-message digest calculated for it yet? */ + /* 1 if this stream has not had a SHA1 message digest calculated for it + * yet */ u8 unhashed : 1; - + u8 deferred : 1; u8 no_progress : 1; @@ -222,10 +221,10 @@ struct wim_lookup_table_entry { union { /* When a WIM file is written, @output_resource_entry is filled * in with the resource entry for the output WIM. This will not - * necessarily be the same as the @resource_entry since: - The - * stream may have a different offset in the new WIM - The - * stream may have a different compressed size in the new WIM if - * the compression type changed + * necessarily be the same as the @resource_entry since: + * - The stream may have a different offset in the new WIM + * - The stream may have a different compressed size in the new + * WIM if the compression type changed */ struct resource_entry output_resource_entry; @@ -464,34 +463,12 @@ inode_stream_name_nbytes(const struct wim_inode *inode, unsigned stream_idx) return inode->i_ads_entries[stream_idx - 1].stream_name_nbytes; } -static inline struct wim_lookup_table_entry * -inode_unnamed_lte_resolved(const struct wim_inode *inode) -{ - wimlib_assert(inode->i_resolved); - for (unsigned i = 0; i <= inode->i_num_ads; i++) { - if (inode_stream_name_nbytes(inode, i) == 0 && - !is_zero_hash(inode_stream_hash_resolved(inode, i))) - { - return inode_stream_lte_resolved(inode, i); - } - } - return NULL; -} +extern struct wim_lookup_table_entry * +inode_unnamed_lte_resolved(const struct wim_inode *inode); -static inline struct wim_lookup_table_entry * +extern struct wim_lookup_table_entry * inode_unnamed_lte_unresolved(const struct wim_inode *inode, - const struct wim_lookup_table *table) -{ - wimlib_assert(!inode->i_resolved); - for (unsigned i = 0; i <= inode->i_num_ads; i++) { - if (inode_stream_name_nbytes(inode, i) == 0 && - !is_zero_hash(inode_stream_hash_unresolved(inode, i))) - { - return inode_stream_lte_unresolved(inode, i, table); - } - } - return NULL; -} + const struct wim_lookup_table *table); extern struct wim_lookup_table_entry * inode_unnamed_lte(const struct wim_inode *inode, const struct wim_lookup_table *table); diff --git a/src/mount_image.c b/src/mount_image.c index a83c6ba2..78562019 100644 --- a/src/mount_image.c +++ b/src/mount_image.c @@ -160,6 +160,54 @@ flags_writable(int open_flags) return open_flags & (O_RDWR | O_WRONLY); } +/* Like pread(), but keep trying until everything has been read or we know for + * sure that there was an error. */ +static ssize_t +full_pread(int fd, void *buf, size_t count, off_t offset) +{ + ssize_t bytes_remaining = count; + ssize_t bytes_read; + + while (bytes_remaining > 0) { + bytes_read = pread(fd, buf, bytes_remaining, offset); + if (bytes_read <= 0) { + if (bytes_read < 0) { + if (errno == EINTR) + continue; + } else { + errno = EIO; + } + break; + } + bytes_remaining -= bytes_read; + buf += bytes_read; + offset += bytes_read; + } + return count - bytes_remaining; +} + +/* Like pwrite(), but keep trying until everything has been written or we know + * for sure that there was an error. */ +static ssize_t +full_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + ssize_t bytes_remaining = count; + ssize_t bytes_written; + + while (bytes_remaining > 0) { + bytes_written = pwrite(fd, buf, bytes_remaining, offset); + if (bytes_written < 0) { + if (errno == EINTR) + continue; + break; + } + bytes_remaining -= bytes_written; + buf += bytes_written; + offset += bytes_written; + } + return count - bytes_remaining; +} + /* * Allocate a file descriptor for a stream. * @@ -649,6 +697,7 @@ extract_resource_to_staging_dir(struct wim_inode *inode, lookup_table_insert_unhashed(ctx->wim->lookup_table, new_lte, inode, stream_id); + *retrieve_lte_pointer(new_lte) = new_lte; *lte = new_lte; return 0; out_revert_fd_changes: @@ -804,7 +853,6 @@ rebuild_wim(struct wimfs_context *ctx, int write_flags, image_for_each_unhashed_stream_safe(lte, tmp, imd) { wimlib_assert(lte->unhashed); if (wim_resource_size(lte) == 0) { - print_lookup_table_entry(lte, stderr); struct wim_lookup_table_entry **back_ptr; back_ptr = retrieve_lte_pointer(lte); *back_ptr = NULL; @@ -1493,13 +1541,6 @@ execute_fusermount(const char *dir) return 0; } -#if 0 -static int wimfs_access(const char *path, int mask) -{ - return -ENOSYS; -} -#endif - static int wimfs_chmod(const char *path, mode_t mask) { @@ -1561,17 +1602,6 @@ wimfs_destroy(void *p) } } -#if 0 -static int wimfs_fallocate(const char *path, int mode, - off_t offset, off_t len, struct fuse_file_info *fi) -{ - struct wimfs_fd *fd = (struct wimfs_fd*)(uintptr_t)fi->fh; - wimlib_assert(fd->staging_fd != -1); - return fallocate(fd->staging_fd, mode, offset, len); -} - -#endif - static int wimfs_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) @@ -1809,7 +1839,7 @@ wimfs_open(const char *path, struct fuse_file_info *fi) ret = lookup_resource(ctx->wim, path, get_lookup_flags(ctx), &dentry, <e, &stream_idx); - if (ret != 0) + if (ret) return ret; inode = dentry->d_inode; @@ -1834,15 +1864,14 @@ wimfs_open(const char *path, struct fuse_file_info *fi) u64 size = (lte) ? wim_resource_size(lte) : 0; ret = extract_resource_to_staging_dir(inode, stream_id, <e, size, ctx); - if (ret != 0) + if (ret) return ret; *back_ptr = lte; } - print_lookup_table_entry(lte, stderr); ret = alloc_wimfs_fd(inode, stream_id, lte, &fd, wimfs_ctx_readonly(ctx)); - if (ret != 0) + if (ret) return ret; if (lte && lte->resource_location == RESOURCE_IN_STAGING_FILE) { @@ -1892,26 +1921,33 @@ wimfs_read(const char *path, char *buf, size_t size, if (!fd) return -EBADF; - if (!fd->f_lte) /* Empty stream with no lookup table entry */ + if (size == 0) return 0; - res_size = wim_resource_size(fd->f_lte); + if (fd->f_lte) + res_size = wim_resource_size(fd->f_lte); + else + res_size = 0; + if (offset > res_size) return -EOVERFLOW; - size = min(size, INT_MAX); + size = min(size, res_size - offset); + if (size == 0) + return 0; switch (fd->f_lte->resource_location) { case RESOURCE_IN_STAGING_FILE: - ret = pread(fd->staging_fd, buf, size, offset); - if (ret < 0) + ret = full_pread(fd->staging_fd, buf, size, offset); + if (ret != size) ret = -errno; break; case RESOURCE_IN_WIM: if (read_partial_wim_resource_into_buf(fd->f_lte, size, offset, buf, true)) ret = -errno; - ret = size; + else + ret = size; break; case RESOURCE_IN_ATTACHED_BUFFER: memcpy(buf, fd->f_lte->attached_buffer + offset, size); @@ -2216,13 +2252,19 @@ wimfs_truncate(const char *path, off_t size) } else { /* File in WIM. Extract it to the staging directory, but only * the first @size bytes of it. */ + struct wim_lookup_table_entry **back_ptr; + inode = dentry->d_inode; - if (stream_idx == 0) + if (stream_idx == 0) { stream_id = 0; - else + back_ptr = &inode->i_lte; + } else { stream_id = inode->i_ads_entries[stream_idx - 1].stream_id; + back_ptr = &inode->i_ads_entries[stream_idx - 1].lte; + } ret = extract_resource_to_staging_dir(inode, stream_id, <e, size, ctx); + *back_ptr = lte; } return ret; } @@ -2321,8 +2363,8 @@ wimfs_write(const char *path, const char *buf, size_t size, wimlib_assert(fd->f_inode != NULL); /* Write the data. */ - ret = pwrite(fd->staging_fd, buf, size, offset); - if (ret == -1) + ret = full_pwrite(fd->staging_fd, buf, size, offset); + if (ret != size) return -errno; /* Update file size */ @@ -2339,15 +2381,9 @@ wimfs_write(const char *path, const char *buf, size_t size, } static struct fuse_operations wimfs_operations = { -#if 0 - .access = wimfs_access, -#endif .chmod = wimfs_chmod, .chown = wimfs_chown, .destroy = wimfs_destroy, -#if 0 - .fallocate = wimfs_fallocate, -#endif .fgetattr = wimfs_fgetattr, .ftruncate = wimfs_ftruncate, .getattr = wimfs_getattr, diff --git a/src/ntfs-apply.c b/src/ntfs-apply.c index 1e3ec48c..b9f6bf29 100644 --- a/src/ntfs-apply.c +++ b/src/ntfs-apply.c @@ -102,13 +102,19 @@ write_ntfs_data_streams(ntfs_inode *ni, struct wim_dentry *dentry, const struct wim_inode *inode = dentry->d_inode; struct wim_lookup_table_entry *lte; + lte = inode->i_lte; + + /* For directories, skip unnamed streams; just extract alternate data + * streams. */ + if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) + goto cont; + DEBUG("Writing %u NTFS data stream%s for `%s'", inode->i_num_ads + 1, (inode->i_num_ads == 0 ? "" : "s"), dentry->_full_path); - lte = inode->i_lte; - while (1) { + for (;;) { if (stream_name_nbytes) { /* Skip special UNIX data entries (see documentation for * WIMLIB_ADD_IMAGE_FLAG_UNIX_DATA) */ @@ -121,7 +127,7 @@ write_ntfs_data_streams(ntfs_inode *ni, struct wim_dentry *dentry, /* Create an empty named stream. */ ret = ntfs_attr_add(ni, AT_DATA, stream_name, stream_name_nbytes / 2, NULL, 0); - if (ret != 0) { + if (ret) { ERROR_WITH_ERRNO("Failed to create named data " "stream for extracted file " "`%s'", @@ -151,7 +157,7 @@ write_ntfs_data_streams(ntfs_inode *ni, struct wim_dentry *dentry, * length, so the NTFS attribute should be resized to * this length before starting to extract the data. */ ret = ntfs_attr_truncate_solid(na, wim_resource_size(lte)); - if (ret != 0) { + if (ret) { ntfs_attr_close(na); break; } @@ -161,7 +167,7 @@ write_ntfs_data_streams(ntfs_inode *ni, struct wim_dentry *dentry, /* Close the attribute */ ntfs_attr_close(na); - if (ret != 0) + if (ret) break; /* Record the number of bytes of uncompressed data that @@ -304,13 +310,12 @@ apply_file_attributes_and_security_data(ntfs_inode *ni, ni, dir_ni, (const char*)&attributes_le32, sizeof(u32), 0); - if (ret != 0) { + if (ret) { ERROR("Failed to set NTFS file attributes on `%s'", dentry->_full_path); - return WIMLIB_ERR_NTFS_3G; - } - if (inode->i_security_id != -1 && - !(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS)) + ret = WIMLIB_ERR_NTFS_3G; + } else if (inode->i_security_id != -1 && + !(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS)) { const char *desc; const struct wim_security_data *sd; @@ -325,13 +330,13 @@ apply_file_attributes_and_security_data(ntfs_inode *ni, ni, dir_ni, desc, sd->sizes[inode->i_security_id], 0); - if (ret != 0) { + if (ret) { ERROR_WITH_ERRNO("Failed to set security data on `%s'", dentry->_full_path); - return WIMLIB_ERR_NTFS_3G; + ret = WIMLIB_ERR_NTFS_3G; } } - return 0; + return ret; } /* @@ -343,7 +348,7 @@ apply_reparse_data(ntfs_inode *ni, struct wim_dentry *dentry, union wimlib_progress_info *progress_info) { struct wim_lookup_table_entry *lte; - int ret = 0; + int ret; lte = inode_unnamed_lte_resolved(dentry->d_inode); @@ -355,7 +360,9 @@ apply_reparse_data(ntfs_inode *ni, struct wim_dentry *dentry, return WIMLIB_ERR_INVALID_DENTRY; } - if (wim_resource_size(lte) >= 0xffff) { + /* "Reparse point data, including the tag and optional GUID, cannot + * exceed 16 kilobytes." - MSDN */ + if (wim_resource_size(lte) > (16 * 1024 - 8)) { ERROR("Reparse data of `%s' is too long (%"PRIu64" bytes)", dentry->_full_path, wim_resource_size(lte)); return WIMLIB_ERR_INVALID_DENTRY; @@ -378,9 +385,10 @@ apply_reparse_data(ntfs_inode *ni, struct wim_dentry *dentry, ERROR_WITH_ERRNO("Failed to set NTFS reparse data on `%s'", dentry->_full_path); return WIMLIB_ERR_NTFS_3G; + } else { + progress_info->extract.completed_bytes += wim_resource_size(lte); } - progress_info->extract.completed_bytes += wim_resource_size(lte); - return 0; + return ret; } /* @@ -395,7 +403,7 @@ static int do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni, struct apply_args *args) { - int ret = 0; + int ret; mode_t type; ntfs_inode *ni = NULL; struct wim_inode *inode = dentry->d_inode; @@ -419,10 +427,7 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni, * extracted yet, so go ahead and extract the * first one. */ FREE(inode->i_extracted_file); - const tchar *full_path = dentry->_full_path; - - if (!full_path || - !(inode->i_extracted_file = STRDUP(full_path))) + if (!(inode->i_extracted_file = STRDUP(dentry->_full_path))) { ret = WIMLIB_ERR_NOMEM; goto out_close_dir_ni; @@ -446,24 +451,22 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni, goto out_close_dir_ni; } - /* Write the data streams, unless this is a directory or reparse point - * */ - if (!(inode->i_attributes & (FILE_ATTRIBUTE_REPARSE_POINT | - FILE_ATTRIBUTE_DIRECTORY))) { + /* Write the data streams, unless this is reparse point. */ + if (!(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT)) { ret = write_ntfs_data_streams(ni, dentry, &args->progress); - if (ret != 0) + if (ret) goto out_close_dir_ni; } ret = apply_file_attributes_and_security_data(ni, dir_ni, dentry, args->w, args->extract_flags); - if (ret != 0) + if (ret) goto out_close_dir_ni; if (inode->i_attributes & FILE_ATTR_REPARSE_POINT) { ret = apply_reparse_data(ni, dentry, &args->progress); - if (ret != 0) + if (ret) goto out_close_dir_ni; } @@ -475,7 +478,7 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni, dentry->short_name_nbytes, &short_name_mbs, &short_name_mbs_nbytes); - if (ret != 0) + if (ret) goto out_close_dir_ni; DEBUG("Setting short (DOS) name of `%s' to %s", @@ -484,7 +487,7 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni, ret = ntfs_set_ntfs_dos_name(ni, dir_ni, short_name_mbs, short_name_mbs_nbytes, 0); FREE(short_name_mbs); - if (ret != 0) { + if (ret) { ERROR_WITH_ERRNO("Could not set DOS (short) name for `%s'", dentry->_full_path); ret = WIMLIB_ERR_NTFS_3G; diff --git a/src/ntfs-capture.c b/src/ntfs-capture.c index 2656d1dd..9d501aa3 100644 --- a/src/ntfs-capture.c +++ b/src/ntfs-capture.c @@ -176,8 +176,8 @@ capture_ntfs_streams(struct wim_inode *inode, ATTR_TYPES type) { ntfs_attr_search_ctx *actx; - struct ntfs_location *ntfs_loc = NULL; - int ret = 0; + struct ntfs_location *ntfs_loc; + int ret; struct wim_lookup_table_entry *lte; DEBUG2("Capturing NTFS data streams from `%s'", path); @@ -199,14 +199,9 @@ capture_ntfs_streams(struct wim_inode *inode, u32 stream_id; if (data_size == 0) { - if (errno != 0) { - ERROR_WITH_ERRNO("Failed to get size of attribute of " - "`%s'", path); - ret = WIMLIB_ERR_NTFS_3G; - goto out_put_actx; - } /* Empty stream. No lookup table entry is needed. */ lte = NULL; + ntfs_loc = NULL; } else { ntfs_loc = CALLOC(1, sizeof(*ntfs_loc)); if (!ntfs_loc) @@ -280,7 +275,13 @@ capture_ntfs_streams(struct wim_inode *inode, inode, stream_id); } } - ret = 0; + if (errno == ENOENT) { + ret = 0; + } else { + ERROR_WITH_ERRNO("Error listing NTFS attributes from `%s'", + path); + ret = WIMLIB_ERR_NTFS_3G; + } goto out_put_actx; out_free_lte: free_lookup_table_entry(lte); @@ -295,7 +296,7 @@ out_put_actx: if (ret == 0) DEBUG2("Successfully captured NTFS streams from `%s'", path); else - ERROR("Failed to capture NTFS streams from `%s", path); + ERROR("Failed to capture NTFS streams from `%s'", path); return ret; } @@ -550,6 +551,7 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret, int ret; struct wim_dentry *root; struct wim_inode *inode; + ATTR_TYPES stream_type; if (exclude_path(path, path_len, config, false)) { /* Exclude a file or directory tree based on the capture @@ -603,7 +605,7 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret, if (inode->i_nlink > 1) /* Shared inode; nothing more to do */ goto out; - if (name_type & FILE_NAME_WIN32) /* Win32 or Win32+DOS name */ + if (name_type & FILE_NAME_WIN32) /* Win32 or Win32+DOS name (rather than POSIX) */ root->is_win32_name = 1; inode->i_creation_time = le64_to_cpu(ni->creation_time); inode->i_last_write_time = le64_to_cpu(ni->last_data_change_time); @@ -611,14 +613,26 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret, inode->i_attributes = le32_to_cpu(attributes); inode->i_resolved = 1; - if (attributes & FILE_ATTR_REPARSE_POINT) { - /* Junction point, symbolic link, or other reparse point */ - ret = capture_ntfs_streams(inode, ni, path, - path_len, lookup_table, - vol, AT_REPARSE_POINT); - } else if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { + if (attributes & FILE_ATTR_REPARSE_POINT) + stream_type = AT_REPARSE_POINT; + else + stream_type = AT_DATA; + + /* Capture the file's streams; more specifically, this is supposed to: + * + * - Regular files: capture unnamed data stream and any named data + * streams + * - Directories: capture any named data streams + * - Reparse points: capture reparse data only + */ + ret = capture_ntfs_streams(inode, ni, path, path_len, lookup_table, + vol, stream_type); + if (ret) + goto out; + + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { - /* Normal directory */ + /* Recurse to directory children */ s64 pos = 0; struct dos_name_map dos_name_map = { .rb_root = {.rb_node = NULL} }; struct readdir_ctx ctx = { @@ -644,14 +658,9 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret, &dos_name_map); } destroy_dos_name_map(&dos_name_map); - } else { - /* Normal file */ - ret = capture_ntfs_streams(inode, ni, path, - path_len, lookup_table, - vol, AT_DATA); + if (ret) + goto out; } - if (ret) - goto out; if (!(add_image_flags & WIMLIB_ADD_IMAGE_FLAG_NO_ACLS)) { /* Get security descriptor */ diff --git a/src/resource.c b/src/resource.c index ea62b592..8c881296 100644 --- a/src/resource.c +++ b/src/resource.c @@ -812,8 +812,8 @@ extract_wim_resource(const struct wim_lookup_table_entry *lte, print_lookup_table_entry(lte, stderr); if (lte->resource_location == RESOURCE_IN_WIM) ERROR("The WIM file appears to be corrupt!"); - ret = WIMLIB_ERR_INVALID_RESOURCE_HASH; #endif + ret = WIMLIB_ERR_INVALID_RESOURCE_HASH; } } } else { diff --git a/src/sha1.h b/src/sha1.h index 7a3b3129..3f500b23 100644 --- a/src/sha1.h +++ b/src/sha1.h @@ -47,7 +47,7 @@ is_zero_hash(const u8 hash[SHA1_HASH_SIZE]) { if (hash) for (u8 i = 0; i < SHA1_HASH_SIZE / 4; i++) - if (((u32*)hash)[i]) + if (((const u32*)hash)[i]) return false; return true; } diff --git a/src/wim.c b/src/wim.c index 9bc02556..61e910a8 100644 --- a/src/wim.c +++ b/src/wim.c @@ -536,7 +536,7 @@ destroy_image_metadata(struct wim_image_metadata *imd, INIT_LIST_HEAD(&imd->inode_list); #ifdef WITH_NTFS_3G if (imd->ntfs_vol) { - do_ntfs_umount(imd->ntfs_vol); + do_ntfs_umount(imd->ntfs_vol); imd->ntfs_vol = NULL; } #endif diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h index c66d826b..34d43fdc 100644 --- a/src/wimlib_internal.h +++ b/src/wimlib_internal.h @@ -541,7 +541,6 @@ libntfs3g_global_init(); /* ntfs-capture.c */ -/* The types of these two callbacks are intentionally the same. */ typedef int (*consume_data_callback_t)(const void *buf, size_t len, void *ctx); extern int diff --git a/src/win32.c b/src/win32.c index 0836acaa..35026a56 100644 --- a/src/win32.c +++ b/src/win32.c @@ -1329,7 +1329,7 @@ static int do_win32_extract_encrypted_stream(const wchar_t *path, const struct wim_lookup_table_entry *lte) { - ERROR("Extrat encryted streams not implemented"); + ERROR("Extracting encryted streams not implemented"); return WIMLIB_ERR_INVALID_PARAM; } diff --git a/src/write.c b/src/write.c index 6956b488..311eff9c 100644 --- a/src/write.c +++ b/src/write.c @@ -65,10 +65,6 @@ #include -#if defined(__WIN32__) && !defined(INVALID_HANDLE_VALUE) -# define INVALID_HANDLE_VALUE ((HANDLE)(-1)) -#endif - /* Chunk table that's located at the beginning of each compressed resource in * the WIM. (This is not the on-disk format; the on-disk format just has an * array of offsets.) */ @@ -172,16 +168,18 @@ get_compress_func(int out_ctype) * Returns 0 on success; nonzero on failure. */ static int -write_wim_resource_chunk(const void *chunk, unsigned chunk_size, - FILE *out_fp, compress_func_t compress, - struct chunk_table *chunk_tab) +write_wim_resource_chunk(const void * restrict chunk, + unsigned chunk_size, + FILE * restrict out_fp, + compress_func_t compress, + struct chunk_table * restrict chunk_tab) { const void *out_chunk; unsigned out_chunk_size; if (compress) { - u8 *compressed_chunk = alloca(chunk_size); + void *compressed_chunk = alloca(chunk_size); - out_chunk_size = compress(chunk, chunk_size, compressed_chunk); + out_chunk_size = (*compress)(chunk, chunk_size, compressed_chunk); if (out_chunk_size) { /* Write compressed */ out_chunk = compressed_chunk; @@ -212,8 +210,9 @@ write_wim_resource_chunk(const void *chunk, unsigned chunk_size, * @compressed_size_p. */ static int -finish_wim_resource_chunk_tab(struct chunk_table *chunk_tab, - FILE *out_fp, u64 *compressed_size_p) +finish_wim_resource_chunk_tab(struct chunk_table * restrict chunk_tab, + FILE * restrict out_fp, + u64 * restrict compressed_size_p) { size_t bytes_written; if (fseeko(out_fp, chunk_tab->file_offset, SEEK_SET) != 0) { @@ -261,7 +260,8 @@ fflush_and_ftruncate(FILE *out_fp, off_t offset) } static int -finalize_and_check_sha1(SHA_CTX *sha_ctx, struct wim_lookup_table_entry *lte) +finalize_and_check_sha1(SHA_CTX * restrict sha_ctx, + struct wim_lookup_table_entry * restrict lte) { u8 md[SHA1_HASH_SIZE]; sha1_final(md, sha_ctx); @@ -289,7 +289,8 @@ struct write_resource_ctx { }; static int -write_resource_cb(const void *chunk, size_t chunk_size, void *_ctx) +write_resource_cb(const void *restrict chunk, size_t chunk_size, + void *restrict _ctx) { struct write_resource_ctx *ctx = _ctx; @@ -734,8 +735,11 @@ do_write_stream_list_serial(struct list_head *stream_list, static inline int write_flags_to_resource_flags(int write_flags) { - return (write_flags & WIMLIB_WRITE_FLAG_RECOMPRESS) ? - WIMLIB_RESOURCE_FLAG_RECOMPRESS : 0; + int resource_flags = 0; + + if (write_flags & WIMLIB_WRITE_FLAG_RECOMPRESS) + resource_flags |= WIMLIB_RESOURCE_FLAG_RECOMPRESS; + return resource_flags; } static int -- 2.43.0