X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fntfs-3g_capture.c;h=af9ebbee05cc5df78ed0f231cdbf97cdf280dd91;hp=1faba226c5d05104dd4fee1b14d9deb17d62ee34;hb=af141a23c4d1540b8a64759bb68c7cd7ff054e72;hpb=4f2e79ad50660aaaf439867a95165ce1426a8a56 diff --git a/src/ntfs-3g_capture.c b/src/ntfs-3g_capture.c index 1faba226..af9ebbee 100644 --- a/src/ntfs-3g_capture.c +++ b/src/ntfs-3g_capture.c @@ -1,7 +1,7 @@ /* * ntfs-3g_capture.c * - * Capture a WIM image directly from a NTFS volume using libntfs-3g. We capture + * Capture a WIM image directly from an NTFS volume using libntfs-3g. We capture * everything we can, including security data and alternate data streams. */ @@ -245,12 +245,19 @@ capture_ntfs_streams(struct wim_inode *inode, * dentry's inode. */ if (inode->i_lte) { if (lte) { - ERROR("Found two un-named data streams for \"%s\" " - "(sizes = %"PRIu64", %"PRIu64")", - path, inode->i_lte->size, - lte->size); - ret = WIMLIB_ERR_NTFS_3G; - goto out_free_lte; + if (!(inode->i_attributes & + FILE_ATTRIBUTE_REPARSE_POINT)) + { + WARNING("Found two un-named " + "data streams for \"%s\" " + "(sizes = %"PRIu64", " + "%"PRIu64")", + path, + inode->i_lte->size, + lte->size); + } + free_lookup_table_entry(lte); + continue; } } else { stream_id = 0; @@ -350,7 +357,7 @@ insert_dos_name(struct dos_name_map *map, const ntfschar *dos_name, if (avl_tree_insert(&map->root, &new_node->index_node, _avl_cmp_by_ntfs_ino)) { - /* This should be impossible since a NTFS inode cannot + /* This should be impossible since an NTFS inode cannot * have multiple DOS names, and we only should get each * DOS name entry once from the ntfs_readdir() calls. */ ERROR("NTFS inode %"PRIu64" has multiple DOS names", @@ -362,7 +369,7 @@ insert_dos_name(struct dos_name_map *map, const ntfschar *dos_name, return 0; } -/* Returns a structure that contains the DOS name and its length for a NTFS +/* Returns a structure that contains the DOS name and its length for an NTFS * inode, or NULL if the inode has no DOS name. */ static struct dos_name_node * lookup_dos_name(const struct dos_name_map *map, u64 ntfs_ino) @@ -387,12 +394,10 @@ set_dentry_dos_name(struct wim_dentry *dentry, const struct dos_name_map *map) if (dentry->is_win32_name) { node = lookup_dos_name(map, dentry->d_inode->i_ino); if (node) { - dentry->short_name = MALLOC(node->name_nbytes + 2); + dentry->short_name = utf16le_dupz((const utf16lechar *)node->dos_name, + node->name_nbytes); if (!dentry->short_name) return WIMLIB_ERR_NOMEM; - memcpy(dentry->short_name, node->dos_name, - node->name_nbytes); - dentry->short_name[node->name_nbytes / 2] = 0; dentry->short_name_nbytes = node->name_nbytes; DEBUG("Assigned DOS name to ino %"PRIu64, dentry->d_inode->i_ino); @@ -511,7 +516,7 @@ out: return ret; } -/* Recursively build a WIM dentry tree corresponding to a NTFS volume. +/* Recursively build a WIM dentry tree corresponding to an 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. */ @@ -528,12 +533,10 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret, int ret; struct wim_dentry *root = NULL; struct wim_inode *inode = NULL; - ATTR_TYPES stream_type; - if (exclude_path(path, path_len, params->config, false)) { + if (should_exclude_path(path, path_len, params->config)) { /* Exclude a file or directory tree based on the capture * configuration file. */ - ret = 0; goto out_progress; } @@ -555,13 +558,12 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret, goto out; } params->progress.scan.cur_path = path; - do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL); - ret = 0; + ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL); goto out; } /* Create a WIM dentry with an associated inode, which may be shared */ - ret = inode_table_new_dentry(¶ms->inode_table, + ret = inode_table_new_dentry(params->inode_table, path_basename_with_len(path, path_len), ni->mft_no, 0, false, &root); if (ret) @@ -574,7 +576,6 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret, if (inode->i_nlink > 1) { /* Shared inode; nothing more to do */ - ret = 0; goto out_progress; } @@ -584,20 +585,30 @@ 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) - stream_type = AT_REPARSE_POINT; - else - stream_type = AT_DATA; + /* Capture streams. */ - /* Capture the file's streams; more specifically, this is supposed to: + if (attributes & FILE_ATTR_REPARSE_POINT) { + /* Capture reparse data stream. */ + ret = capture_ntfs_streams(inode, ni, path, path_len, + params->unhashed_streams, + vol, AT_REPARSE_POINT); + if (ret) + goto out; + } + + /* Capture data streams. + * + * Directories should not have an unnamed data stream, but they may have + * named data streams. + * + * Reparse points may have an unnamed data stream (which will be ignored + * in favor of the reparse data stream), and they also may have named + * data streams. * - * - Regular files: capture unnamed data stream and any named data - * streams - * - Directories: capture any named data streams - * - Reparse points: capture reparse data only - */ + * Regular files can have an unnamed data stream as well as named data + * streams. */ ret = capture_ntfs_streams(inode, ni, path, path_len, - params->unhashed_streams, vol, stream_type); + params->unhashed_streams, vol, AT_DATA); if (ret) goto out; @@ -657,7 +668,7 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret, ret = ntfs_get_ntfs_acl(&sec_ctx, ni, sd, ret); } if (ret > 0) { - inode->i_security_id = sd_set_add_sd(¶ms->sd_set, + inode->i_security_id = sd_set_add_sd(params->sd_set, sd, ret); if (inode->i_security_id == -1) { ERROR("Out of memory"); @@ -682,9 +693,9 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret, out_progress: params->progress.scan.cur_path = path; if (root == NULL) - do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL); + ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL); else - do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode); + ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode); out: if (ret == 0) *root_ret = root;