From: Eric Biggers Date: Thu, 30 Aug 2012 22:55:28 +0000 (-0500) Subject: More test cases and DOS names capture/apply fixes X-Git-Tag: v1.0.0~31 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=239e67483b8d6759fa97f25a65011cc3480368bc More test cases and DOS names capture/apply fixes --- diff --git a/src/hardlink.c b/src/hardlink.c index 5e8ae1a9..903d0ccd 100644 --- a/src/hardlink.c +++ b/src/hardlink.c @@ -357,11 +357,22 @@ fix_true_link_group(struct dentry *first_dentry) u64 last_ctime = 0; u64 last_mtime = 0; u64 last_atime = 0; + bool found_short_name = false; dentry = first_dentry; do { if (!ref_dentry || ref_dentry->num_ads == 0) ref_dentry = dentry; + if (dentry->short_name_len) { + if (found_short_name) { + ERROR("Multiple short names in hard link " + "group!"); + inconsistent_link_group(first_dentry); + return WIMLIB_ERR_INVALID_DENTRY; + } else { + found_short_name = true; + } + } if (dentry->creation_time > last_ctime) last_ctime = dentry->creation_time; if (dentry->last_write_time > last_mtime) diff --git a/src/ntfs-apply.c b/src/ntfs-apply.c index 1a4cb7dd..108418b3 100644 --- a/src/ntfs-apply.c +++ b/src/ntfs-apply.c @@ -352,7 +352,9 @@ static int preapply_dentry_with_dos_name(struct dentry *dentry, } } /* If there's a dentry with a DOS name, extract it first */ - if (dentry_with_dos_name && !dentry_with_dos_name->extracted_file) { + if (dentry_with_dos_name + && !dentry_with_dos_name->extracted_file) + { char *p; const char *dir_name; char orig; diff --git a/src/ntfs-capture.c b/src/ntfs-capture.c index 4ea23048..dd55d97e 100644 --- a/src/ntfs-capture.c +++ b/src/ntfs-capture.c @@ -406,8 +406,9 @@ struct readdir_ctx { }; static int -build_dentry_tree_ntfs_recursive(struct dentry **root_p, ntfs_inode *ni, - char path[], size_t path_len, +build_dentry_tree_ntfs_recursive(struct dentry **root_p, ntfs_inode *dir_ni, + ntfs_inode *ni, char path[], size_t path_len, + int name_type, struct lookup_table *lookup_table, struct sd_set *sd_set, const struct capture_config *config, @@ -455,7 +456,8 @@ static int wim_ntfs_capture_filldir(void *dirent, const ntfschar *name, ctx->path[path_len++] = '/'; memcpy(ctx->path + path_len, utf8_name, utf8_name_len + 1); path_len += utf8_name_len; - ret = build_dentry_tree_ntfs_recursive(&child, ni, ctx->path, path_len, + ret = build_dentry_tree_ntfs_recursive(&child, ctx->dir_ni, + ni, ctx->path, path_len, name_type, ctx->lookup_table, ctx->sd_set, ctx->config, ctx->ntfs_vol_p, ctx->flags); @@ -470,14 +472,33 @@ out: return ret; } +static int change_dentry_short_name(struct dentry *dentry, + const char short_name_utf8[], + int short_name_utf8_len) +{ + size_t short_name_utf16_len; + char *short_name_utf16; + short_name_utf16 = utf8_to_utf16(short_name_utf8, short_name_utf8_len, + &short_name_utf16_len); + if (!short_name_utf16) { + ERROR_WITH_ERRNO("Failed to convert short name to UTF-16"); + return WIMLIB_ERR_NOMEM; + } + dentry->short_name = short_name_utf16; + dentry->short_name_len = short_name_utf16_len; + return 0; +} + /* Recursively build a WIM dentry tree corresponding to a NTFS volume. * At the same time, update the WIM lookup table with lookup table entries for * the NTFS streams, and build an array of security descriptors. */ static int build_dentry_tree_ntfs_recursive(struct dentry **root_p, + ntfs_inode *dir_ni, ntfs_inode *ni, char path[], size_t path_len, + int name_type, struct lookup_table *lookup_table, struct sd_set *sd_set, const struct capture_config *config, @@ -487,7 +508,8 @@ static int build_dentry_tree_ntfs_recursive(struct dentry **root_p, u32 attributes; int mrec_flags; u32 sd_size = 0; - int ret = 0; + int ret; + char dos_name_utf8[64]; struct dentry *root; mrec_flags = ni->mrec->flags; @@ -513,8 +535,28 @@ static int build_dentry_tree_ntfs_recursive(struct dentry **root_p, root = new_dentry(path_basename(path)); if (!root) return WIMLIB_ERR_NOMEM; - *root_p = root; + + if (dir_ni && (name_type == FILE_NAME_WIN32_AND_DOS + || name_type == FILE_NAME_WIN32)) + { + ret = ntfs_get_ntfs_dos_name(ni, dir_ni, dos_name_utf8, + sizeof(dos_name_utf8)); + if (ret > 0) { + DEBUG("Changing short name of `%s'", path); + ret = change_dentry_short_name(root, dos_name_utf8, + ret); + if (ret != 0) + return ret; + } else { + if (errno != ENODATA) { + ERROR_WITH_ERRNO("Error getting DOS name " + "of `%s'", path); + return WIMLIB_ERR_NTFS_3G; + } + } + } + root->creation_time = le64_to_cpu(ni->creation_time); root->last_write_time = le64_to_cpu(ni->last_data_change_time); root->last_access_time = le64_to_cpu(ni->last_access_time); @@ -643,9 +685,10 @@ static int build_dentry_tree_ntfs(struct dentry **root_p, path[0] = '/'; path[1] = '\0'; - ret = build_dentry_tree_ntfs_recursive(root_p, root_ni, path, 1, - lookup_table, &sd_set, - config, ntfs_vol_p, flags); + ret = build_dentry_tree_ntfs_recursive(root_p, NULL, root_ni, path, 1, + FILE_NAME_POSIX, lookup_table, + &sd_set, config, ntfs_vol_p, + flags); out_cleanup: FREE(path); ntfs_inode_close(root_ni); diff --git a/tests/test-imagex-ntfs b/tests/test-imagex-ntfs index 7645f211..bbc88b74 100755 --- a/tests/test-imagex-ntfs +++ b/tests/test-imagex-ntfs @@ -11,7 +11,7 @@ cd tests imagex() { #echo "imagex $@" - ../imagex $@ > /dev/null + ../imagex $@ #> /dev/null } do_unmount() { @@ -184,6 +184,30 @@ do_test "dd if=/dev/zero of=file bs=4096 count=10 &> /dev/null" msg "NTFS volume containing file with DOS name" do_test "echo 1 > file; setfattr -v file -n system.ntfs_dos_name file" -msg "NTFS volume containing file with DOS name with hardlink in same directory" -do_test "echo 1 > file; setfattr -v file -n system.ntfs_dos_name file; ln file link" +msg "NTFS volume containing file with DOS name with alphabetically smaller hardlink in same directory" +do_test "echo 1 > file; setfattr -v file -n system.ntfs_dos_name file; ln file aaa_link" + +msg "NTFS volume containing file with DOS name with alphabetically larger hardlink in same directory" +do_test "echo 1 > file; setfattr -v file -n system.ntfs_dos_name file; ln file zzz_link" + +msg "NTFS volume containing file with long name and with DOS name with alphabetically smaller hardlink in same directory" +do_test 'echo 1 > file_with_a_long_name; + setfattr -v "file~1" -n system.ntfs_dos_name file_with_a_long_name; + ln file_with_a_long_name aaa_link' + +msg "NTFS volume containing many nested directories" +do_test 'mkdir dir; mkdir dir/subdir; mkdir dir/subdir/subdir2; mkdir dir/subdir/subdir3' + +msg "NTFS volume containing identical files and symlinks in subdirectory" +do_test 'mkdir dir; + echo 888 > dir/file; + echo 888 > dir/idfile2; + ln -s dir dir/circle; ln -s file dir/filelink' + +msg "NTFS volume containing hard link group and identical files not hard linked" +do_test 'echo 888 > file; + echo 888 > file2; + ln file link; + ln file link2; + echo 888 > file3'