From: Eric Biggers Date: Fri, 16 Aug 2013 19:16:24 +0000 (-0500) Subject: NTFS-3g apply: Open extracted files by MFT reference X-Git-Tag: v1.5.0~65 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=962cca1a6f9e45827006a745be086b7af3b725aa NTFS-3g apply: Open extracted files by MFT reference --- diff --git a/include/wimlib/apply.h b/include/wimlib/apply.h index a7fe179a..8a556263 100644 --- a/include/wimlib/apply.h +++ b/include/wimlib/apply.h @@ -10,6 +10,13 @@ struct wimlib_unix_data; struct wim_dentry; struct apply_ctx; +/* Path to extracted file, or "cookie" identifying the file (e.g. inode number). + * */ +typedef union { + const char *path; + u64 cookie; +} file_spec_t; + /* * struct apply_operations - Callback functions for a specific extraction * mode/backend. These are lower-level functions that are called by the generic @@ -43,11 +50,11 @@ struct apply_operations { /* REQUIRED: Create a file. */ int (*create_file) - (const tchar *path, struct apply_ctx *ctx); + (const tchar *path, struct apply_ctx *ctx, u64 *cookie_ret); /* REQUIRED: Create a directory. */ int (*create_directory) - (const tchar *path, struct apply_ctx *ctx); + (const tchar *path, struct apply_ctx *ctx, u64 *cookie_ret); /* OPTIONAL: Create a hard link. In start_extract(), set * ctx->supported_features.hard_links if supported. */ @@ -63,20 +70,20 @@ struct apply_operations { /* REQUIRED: Extract unnamed data stream. */ int (*extract_unnamed_stream) - (const tchar *path, struct wim_lookup_table_entry *lte, + (file_spec_t file, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx); /* OPTIONAL: Extracted named data stream. In start_extract(), set * ctx->supported_features.alternate_data_streams if supported. */ int (*extract_named_stream) - (const tchar *path, const utf16lechar *stream_name, + (file_spec_t file, const utf16lechar *stream_name, size_t stream_name_nchars, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx); /* OPTIONAL: Extracted encrypted stream. In start_extract(), set * ctx->supported_features.encrypted_files if supported. */ int (*extract_encrypted_stream) - (const tchar *path, struct wim_lookup_table_entry *lte, + (file_spec_t file, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx); /* OPTIONAL: Set file attributes. Calling code calls this if non-NULL. @@ -154,6 +161,12 @@ struct apply_operations { /* OPTIONAL: Set to 1 if the root directory of the volume (see * target_is_root() callback) should not be explicitly extracted. */ unsigned root_directory_is_special : 1; + + /* OPTIONAL: Set to 1 if extraction cookie, or inode number, is stored + * in create_file() and create_directory() callbacks. This cookie will + * then be passed to callbacks taking a 'file_spec_t', rather than the + * path. */ + unsigned uses_cookies : 1; }; struct wim_features { diff --git a/include/wimlib/dentry.h b/include/wimlib/dentry.h index 09de869a..8676e8e0 100644 --- a/include/wimlib/dentry.h +++ b/include/wimlib/dentry.h @@ -363,11 +363,20 @@ struct wim_inode { * to 0 otherwise. */ u64 i_devno; - /* Used only during image extraction: pointer to the first path - * (malloc()ed buffer) at which this inode has been extracted. - * Freed and set to NULL after the extraction is done (either - * success or failure). */ - tchar *i_extracted_file; + struct { + + /* Used only during image extraction: pointer to the first path + * (malloc()ed buffer) at which this inode has been extracted. + * Freed and set to NULL after the extraction is done (either + * success or failure). */ + tchar *i_extracted_file; + + /** Used only during image extraction: "cookie" that + * identifies this extracted file (inode), for example + * an inode number. Only used if supported by the + * extraction mode. */ + u64 extract_cookie; + }; #ifdef WITH_FUSE /* Used only during image mount: Table of file descriptors that diff --git a/src/extract.c b/src/extract.c index d4efc24e..9c460e96 100644 --- a/src/extract.c +++ b/src/extract.c @@ -333,13 +333,13 @@ extract_inode(const tchar *path, struct apply_ctx *ctx, struct wim_inode *inode) } else #endif /* !__WIN32__ */ if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) { - ret = ctx->ops->create_directory(path, ctx); + ret = ctx->ops->create_directory(path, ctx, &inode->extract_cookie); if (ret) { ERROR_WITH_ERRNO("Failed to create the directory " "\"%"TS"\"", path); } } else { - ret = ctx->ops->create_file(path, ctx); + ret = ctx->ops->create_file(path, ctx, &inode->extract_cookie); if (ret) { ERROR_WITH_ERRNO("Failed to create the file " "\"%"TS"\"", path); @@ -553,6 +553,7 @@ extract_streams(const tchar *path, struct apply_ctx *ctx, { struct wim_inode *inode = dentry->d_inode; struct wim_lookup_table_entry *lte; + file_spec_t file_spec; int ret; if (dentry->was_hardlinked) @@ -571,6 +572,11 @@ extract_streams(const tchar *path, struct apply_ctx *ctx, } #endif + if (ctx->ops->uses_cookies) + file_spec.cookie = inode->extract_cookie; + else + file_spec.path = path; + /* Unnamed data stream. */ lte = inode_unnamed_lte_resolved(inode); if (lte && (!lte_spec || lte == lte_spec)) { @@ -581,9 +587,9 @@ extract_streams(const tchar *path, struct apply_ctx *ctx, { if ((inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) && ctx->supported_features.encrypted_files) - ret = ctx->ops->extract_encrypted_stream(path, lte, ctx); + ret = ctx->ops->extract_encrypted_stream(file_spec, lte, ctx); else - ret = ctx->ops->extract_unnamed_stream(path, lte, ctx); + ret = ctx->ops->extract_unnamed_stream(file_spec, lte, ctx); if (ret) goto error; update_extract_progress(ctx, lte); @@ -617,7 +623,7 @@ extract_streams(const tchar *path, struct apply_ctx *ctx, continue; if (lte_spec) lte = lte_override; - ret = ctx->ops->extract_named_stream(path, entry->stream_name, + ret = ctx->ops->extract_named_stream(file_spec, entry->stream_name, entry->stream_name_nbytes / 2, lte, ctx); if (ret) @@ -997,13 +1003,18 @@ do_dentry_extract_skeleton(tchar path[], struct wim_dentry *dentry, /* Create empty named data streams. */ if (can_extract_named_data_streams(ctx)) { for (u16 i = 0; i < inode->i_num_ads; i++) { + file_spec_t file_spec; struct wim_ads_entry *entry = &inode->i_ads_entries[i]; if (!ads_entry_is_named_stream(entry)) continue; if (entry->lte) continue; - ret = ctx->ops->extract_named_stream(path, + if (ctx->ops->uses_cookies) + file_spec.cookie = inode->extract_cookie; + else + file_spec.path = path; + ret = ctx->ops->extract_named_stream(file_spec, entry->stream_name, entry->stream_name_nbytes / 2, entry->lte, ctx); diff --git a/src/ntfs-3g_apply.c b/src/ntfs-3g_apply.c index fe2f24e2..c40661b8 100644 --- a/src/ntfs-3g_apply.c +++ b/src/ntfs-3g_apply.c @@ -103,7 +103,8 @@ ntfs_3g_open_parent_inode(const char *path, ntfs_volume *vol) } static int -ntfs_3g_create(const char *path, struct apply_ctx *ctx, mode_t mode) +ntfs_3g_create(const char *path, struct apply_ctx *ctx, u64 *cookie_ret, + mode_t mode) { ntfs_volume *vol; ntfs_inode *dir_ni, *ni; @@ -125,11 +126,16 @@ ntfs_3g_create(const char *path, struct apply_ctx *ctx, mode_t mode) if (ret) goto out_close_dir_ni; - ret = 0; + ret = WIMLIB_ERR_NTFS_3G; ni = ntfs_create(dir_ni, 0, name_utf16le, name_utf16le_nbytes / 2, mode); - if (!ni || ntfs_inode_close_in_dir(ni, dir_ni)) - ret = WIMLIB_ERR_NTFS_3G; + if (!ni) + goto out_free_name_utf16le; + *cookie_ret = MK_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number)); + if (ntfs_inode_close_in_dir(ni, dir_ni)) + goto out_free_name_utf16le; + ret = 0; +out_free_name_utf16le: FREE(name_utf16le); out_close_dir_ni: if (ntfs_inode_close(dir_ni)) @@ -139,15 +145,17 @@ out: } static int -ntfs_3g_create_file(const char *path, struct apply_ctx *ctx) +ntfs_3g_create_file(const char *path, struct apply_ctx *ctx, + u64 *cookie_ret) { - return ntfs_3g_create(path, ctx, S_IFREG); + return ntfs_3g_create(path, ctx, cookie_ret, S_IFREG); } static int -ntfs_3g_create_directory(const char *path, struct apply_ctx *ctx) +ntfs_3g_create_directory(const char *path, struct apply_ctx *ctx, + u64 *cookie_ret) { - return ntfs_3g_create(path, ctx, S_IFDIR); + return ntfs_3g_create(path, ctx, cookie_ret, S_IFDIR); } static int @@ -196,7 +204,7 @@ out: * Extract a stream (default or alternate data) to an attribute of a NTFS file. */ static int -ntfs_3g_extract_stream(const char *path, const utf16lechar *raw_stream_name, +ntfs_3g_extract_stream(file_spec_t file, const utf16lechar *raw_stream_name, size_t stream_name_nchars, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx) { @@ -219,9 +227,9 @@ ntfs_3g_extract_stream(const char *path, const utf16lechar *raw_stream_name, if (!stream_name_nchars && !lte) goto out; - /* Look up NTFS inode to which to extract the stream. */ + /* Open NTFS inode to which to extract the stream. */ ret = WIMLIB_ERR_NTFS_3G; - ni = ntfs_3g_apply_pathname_to_inode(path, ctx); + ni = ntfs_inode_open(ntfs_3g_apply_ctx_get_volume(ctx), file.cookie); if (!ni) goto out; @@ -266,19 +274,19 @@ out: } static int -ntfs_3g_extract_unnamed_stream(const char *path, +ntfs_3g_extract_unnamed_stream(file_spec_t file, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx) { - return ntfs_3g_extract_stream(path, NULL, 0, lte, ctx); + return ntfs_3g_extract_stream(file, NULL, 0, lte, ctx); } static int -ntfs_3g_extract_named_stream(const char *path, const utf16lechar *stream_name, +ntfs_3g_extract_named_stream(file_spec_t file, const utf16lechar *stream_name, size_t stream_name_nchars, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx) { - return ntfs_3g_extract_stream(path, stream_name, + return ntfs_3g_extract_stream(file, stream_name, stream_name_nchars, lte, ctx); } @@ -495,6 +503,7 @@ const struct apply_operations ntfs_3g_apply_ops = { .supports_case_sensitive_filenames = 1, .root_directory_is_special = 1, + .uses_cookies = 1, }; #endif /* WITH_NTFS_3G */ diff --git a/src/unix_apply.c b/src/unix_apply.c index bd576ef0..026042bc 100644 --- a/src/unix_apply.c +++ b/src/unix_apply.c @@ -54,7 +54,7 @@ unix_start_extract(const char *target, struct apply_ctx *ctx) } static int -unix_create_file(const char *path, struct apply_ctx *ctx) +unix_create_file(const char *path, struct apply_ctx *ctx, u64 *cookie_ret) { int fd = open(path, O_TRUNC | O_CREAT | O_WRONLY, 0644); if (fd < 0) @@ -64,7 +64,7 @@ unix_create_file(const char *path, struct apply_ctx *ctx) } static int -unix_create_directory(const tchar *path, struct apply_ctx *ctx) +unix_create_directory(const tchar *path, struct apply_ctx *ctx, u64 *cookie_ret) { struct stat stbuf; @@ -111,10 +111,11 @@ unix_create_symlink(const tchar *oldpath, const tchar *newpath, } static int -unix_extract_unnamed_stream(const tchar *path, +unix_extract_unnamed_stream(file_spec_t file, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx) { + const char *path = file.path; struct filedes fd; int raw_fd; int ret; diff --git a/src/win32_apply.c b/src/win32_apply.c index bce897a4..00ace99e 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -162,19 +162,19 @@ error: } static int -win32_extract_unnamed_stream(const wchar_t *path, +win32_extract_unnamed_stream(file_spec_t file, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx) { - return win32_extract_stream(path, NULL, 0, lte, ctx); + return win32_extract_stream(file.path, NULL, 0, lte, ctx); } static int -win32_extract_named_stream(const wchar_t *path, const wchar_t *stream_name, +win32_extract_named_stream(file_spec_t file, const wchar_t *stream_name, size_t stream_name_nchars, struct wim_lookup_table_entry *lte, struct apply_ctx *ctx) { - return win32_extract_stream(path, stream_name, + return win32_extract_stream(file.path, stream_name, stream_name_nchars, lte, ctx); }