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
/* 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. */
/* 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.
/* 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 {
* 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
} 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);
{
struct wim_inode *inode = dentry->d_inode;
struct wim_lookup_table_entry *lte;
+ file_spec_t file_spec;
int ret;
if (dentry->was_hardlinked)
}
#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)) {
{
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);
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)
/* 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);
}
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;
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))
}
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
* 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)
{
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;
}
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);
}
.supports_case_sensitive_filenames = 1,
.root_directory_is_special = 1,
+ .uses_cookies = 1,
};
#endif /* WITH_NTFS_3G */
}
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)
}
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;
}
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;
}
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);
}