/* Pointer to a child of this directory entry. */
struct dentry *children;
- /* Size of directory entry, in bytes. Typical size is around 104 to 120
- * bytes. */
- /* It is possible for the length field to be 0. This situation, which
+ /* Size of directory entry on disk, in bytes. Typical size is around
+ * 104 to 120 bytes.
+ *
+ * It is possible for the length field to be 0. This situation, which
* is undocumented, indicates the end of a list of sibling nodes in a
* directory. It also means the real length is 8, because the dentry
- * included only the length field, but that takes up 8 bytes. */
+ * included only the length field, but that takes up 8 bytes.
+ *
+ * The length here includes the base directory entry on disk as well as
+ * the long and short filenames. It does NOT include any alternate
+ * stream entries that may follow the directory entry, even though the
+ * size of those needs to be considered.
+ */
u64 length;
/* The file attributes associated with this file. */
u32 attributes;
- /* The index of the node in the security table that contains this file's
- * security information. If -1, no security information exists for this
- * file. */
+ /* The index of the security descriptor in the WIM image's table of
+ * security descriptors that contains this file's security information.
+ * If -1, no security information exists for this file. */
int32_t security_id;
- /* The offset, from the start of the metadata section, of this directory
- * entry's child files. 0 if the directory entry has no children. */
+ /* The offset, from the start of the WIM metadata resource for this
+ * image, of this directory entry's child files. 0 if the directory
+ * entry has no children (as in the case of regular files or reparse
+ * points). */
u64 subdir_offset;
/* Timestamps for the dentry. The timestamps are the number of
u64 last_write_time;
/* true if the dentry's lookup table entry has been resolved (i.e. the
- * @lte field is invalid, but the @hash field is not valid) */
+ * @lte field is valid, but the @hash field is not valid) */
bool resolved;
/* A hash of the file's contents, or a pointer to the lookup table entry
* for this dentry if the lookup table entries have been resolved.
*
* More specifically, this is for the un-named default file stream, as
- * opposed to the alternate file streams, which may have their own
- * lookup table entries. */
+ * opposed to the alternate (named) file streams, which may have their
+ * own lookup table entries. */
union {
u8 hash[SHA1_HASH_SIZE];
struct lookup_table_entry *lte;
};
/* If the file is part of a hard link set, all the directory entries in
- * the set will share the same value for this field. */
+ * the set will share the same value for this field.
+ *
+ * Unfortunately, in some WIMs it is NOT the case that all dentries that
+ * share this field are actually in the same hard link set, although the
+ * WIMs that wimlib writes maintain this restriction. */
u64 hard_link;
enum {
char *stream_name_utf16;
u16 stream_name_utf16_num_chars;
ntfs_volume **ntfs_vol_p;
+ bool is_reparse_point;
};
/*
return ret;
}
+static bool in_same_dir(const char *path1, const char *path2)
+{
+ const char *p1 = strrchr(path1, '/');
+ const char *p2 = strrchr(path2, '/');
+ if (p1 - path1 != p2 - path2)
+ return false;
+ return memcmp(path1, path2, p1 - path1) == 0;
+}
+
/*
* Makes a NTFS hard link
*
ntfs_inode **to_ni_ret)
{
int ret;
+ char *p;
+ char orig;
+ const char *dir_name;
+
ntfs_inode *to_ni;
+ ntfs_volume *vol;
wimlib_assert(dentry_is_regular_file(from_dentry)
&& dentry_is_regular_file(to_dentry));
+ if (ntfs_inode_close(dir_ni) != 0) {
+ ERROR_WITH_ERRNO("Error closing directory");
+ return WIMLIB_ERR_NTFS_3G;
+ }
+
+ vol = dir_ni->vol;
+
DEBUG("Extracting NTFS hard link `%s' => `%s'",
from_dentry->full_path_utf8, to_dentry->extracted_file);
- to_ni = ntfs_pathname_to_inode(dir_ni->vol, NULL,
+ to_ni = ntfs_pathname_to_inode(vol, NULL,
to_dentry->extracted_file);
if (!to_ni) {
ERROR_WITH_ERRNO("Could not find NTFS inode for `%s'",
to_dentry->extracted_file);
return WIMLIB_ERR_NTFS_3G;
}
+ p = from_dentry->full_path_utf8 + from_dentry->full_path_utf8_len;
+ do {
+ p--;
+ } while (*p != '/');
+
+ orig = *p;
+ *p = '\0';
+ dir_name = from_dentry->full_path_utf8;
+
+ dir_ni = ntfs_pathname_to_inode(vol, NULL,
+ from_dentry->full_path_utf8);
+ if (!dir_ni) {
+ ERROR_WITH_ERRNO("Could not find NTFS inode for `%s'",
+ from_dentry->full_path_utf8);
+ *p = orig;
+ return WIMLIB_ERR_NTFS_3G;
+ }
+ *p = orig;
+
ret = ntfs_link(to_ni, dir_ni,
(ntfschar*)from_dentry->file_name,
from_dentry->file_name_len / 2);
if (ret != 0)
return ret;
-#if 0
- if (getuid() != 0) {
- ERROR("We are not root, but NTFS-3g requires root privileges to set arbitrary");
- ERROR("security data on the NTFS filesystem. Please run this program as root");
- ERROR("if you want to extract a WIM image while preserving NTFS-specific");
- ERROR("information.");
-
- return WIMLIB_ERR_NOT_ROOT;
- }
-#endif
return do_wim_apply_image_ntfs(w, device, flags);
}
u64 *sizes;
u8 *descr_copy;
struct wim_security_data *sd;
- sha1_buffer(descriptor, size, hash);
+ sha1_buffer(descriptor, size, hash);
security_id = lookup_sd(hash, sd_set->root);
if (security_id >= 0)
return security_id;
} else {
struct ntfs_location *ntfs_loc;
-
ntfs_loc = CALLOC(1, sizeof(*ntfs_loc));
if (!ntfs_loc)
goto out_put_actx;
actx->attr->name_length * 2);
ntfs_loc->stream_name_utf16_num_chars = actx->attr->name_length;
+ ntfs_loc->is_reparse_point = (type == AT_REPARSE_POINT);
lte = new_lookup_table_entry();
if (!lte)
goto out_free_ntfs_loc;
lookup_table_insert(lookup_table, lte);
}
if (actx->attr->name_length == 0) {
- wimlib_assert(!dentry->lte);
+ if (dentry->lte) {
+ ERROR("Found two un-named data streams for "
+ "`%s'", path);
+ ret = WIMLIB_ERR_NTFS_3G;
+ goto out_free_lte;
+ }
dentry->lte = lte;
} else {
struct ads_entry *new_ads_entry;
&stream_name_utf16_len);
if (!stream_name_utf8)
goto out_free_lte;
- FREE(stream_name_utf8);
new_ads_entry = dentry_add_ads(dentry, stream_name_utf8);
+ FREE(stream_name_utf8);
if (!new_ads_entry)
goto out_free_lte;
"identify a WIM file",
[WIMLIB_ERR_NO_FILENAME]
= "The WIM is not identified with a filename",
- [WIMLIB_ERR_NOT_ROOT]
- = "Root privileges are required for this operation",
[WIMLIB_ERR_NTFS_3G]
= "NTFS-3g encountered an error (check errno)",
[WIMLIB_ERR_OPEN]
WIMLIB_ERR_NOMEM,
WIMLIB_ERR_NOTDIR,
WIMLIB_ERR_NOT_A_WIM_FILE,
- WIMLIB_ERR_NOT_ROOT,
WIMLIB_ERR_NO_FILENAME,
WIMLIB_ERR_NTFS_3G,
WIMLIB_ERR_OPEN,