From ecbe65ac6bff458bf9bb51631e516dd2cbbbae02 Mon Sep 17 00:00:00 2001 From: "flatcap.org!ntfs" Date: Sat, 11 Oct 2003 15:31:25 +0000 Subject: [PATCH] first draft of mft search contexts (Logical change 1.199) --- ntfsprogs/utils.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++ ntfsprogs/utils.h | 29 +++++++++ 2 files changed, 178 insertions(+) diff --git a/ntfsprogs/utils.c b/ntfsprogs/utils.c index 295ba72c..869e86be 100644 --- a/ntfsprogs/utils.c +++ b/ntfsprogs/utils.c @@ -833,6 +833,155 @@ int utils_is_metadata (ntfs_inode *inode) } +/** + * mft_get_search_ctx + */ +struct mft_search_ctx * mft_get_search_ctx (ntfs_volume *vol) +{ + struct mft_search_ctx *ctx; + + ctx = calloc (1, sizeof *ctx); + + ctx->mft_num = -1; + ctx->vol = vol; + + return ctx; +} + +/** + * mft_put_search_ctx + */ +void mft_put_search_ctx (struct mft_search_ctx *ctx) +{ + if (!ctx) + return; + if (ctx->inode) + ntfs_inode_close (ctx->inode); + free (ctx); +} + +/** + * mft_next_record + */ +int mft_next_record (struct mft_search_ctx *ctx) +{ + ATTR_RECORD *attr10 = NULL; + ATTR_RECORD *attr20 = NULL; + ATTR_RECORD *attr80 = NULL; + ntfs_attr_search_ctx *attr_ctx; + + if (!ctx) + return -1; + + if (ctx->inode) { + ntfs_inode_close (ctx->inode); + ctx->inode = NULL; + } + + for (ctx->mft_num++; ctx->mft_num < ctx->vol->nr_mft_records; ctx->mft_num++) { + ctx->flags_match = 0; + int in_use = utils_mftrec_in_use (ctx->vol, (MFT_REF) ctx->mft_num); + if (in_use == -1) { + Eprintf ("Error reading inode %lld. Aborting.", ctx->mft_num); + return -1; + } + + if (in_use) { + ctx->flags_match |= FEMR_IN_USE; + + ctx->inode = ntfs_inode_open (ctx->vol, (MFT_REF) ctx->mft_num); + if (ctx->inode == NULL) { + Eprintf ("Error reading inode %lld.", ctx->mft_num); + return -1; + } + + attr10 = find_first_attribute (AT_STANDARD_INFORMATION, ctx->inode->mrec); + attr20 = find_first_attribute (AT_ATTRIBUTE_LIST, ctx->inode->mrec); + attr80 = find_first_attribute (AT_DATA, ctx->inode->mrec); + + if (attr10) + ctx->flags_match |= FEMR_BASE_RECORD; + else + ctx->flags_match |= FEMR_NOT_BASE_RECORD; + + if (attr20) + ctx->flags_match |= FEMR_BASE_RECORD; + + if (attr80) + ctx->flags_match |= FEMR_FILE; + + if (ctx->flags_search & FEMR_DIR) { + attr_ctx = ntfs_attr_get_search_ctx (NULL, ctx->inode->mrec); + if (attr_ctx) { + if (ntfs_attr_lookup (AT_INDEX_ROOT, I30, 4, 0, 0, NULL, 0, attr_ctx) == 0) + ctx->flags_match |= FEMR_DIR; + + ntfs_attr_put_search_ctx (attr_ctx); + } else { + Eprintf ("Couldn't create a search context.\n"); + return -1; + } + } + + switch (utils_is_metadata (ctx->inode)) { + case 1: ctx->flags_match |= FEMR_METADATA; break; + case 0: ctx->flags_match |= FEMR_NOT_METADATA; break; + default: + ctx->flags_match |= FEMR_NOT_METADATA; break; + //Eprintf ("Error reading inode %lld.", ctx->mft_num); + //return -1; + } + + } else { // !in_use + ntfs_attr *mft; + + ctx->flags_match |= FEMR_NOT_IN_USE; + + ctx->inode = calloc (1, sizeof (*ctx->inode)); + if (!ctx->inode) { + Eprintf ("Out of memory. Aborting."); + return -1; + } + + ctx->inode->mft_no = ctx->mft_num; + ctx->inode->vol = ctx->vol; + ctx->inode->mrec = malloc (ctx->vol->mft_record_size); + if (!ctx->inode->mrec) { + free (ctx->inode); // == ntfs_inode_close + Eprintf ("Out of memory. Aborting."); + return -1; + } + + mft = ntfs_attr_open (ctx->vol->mft_ni, AT_DATA, NULL, 0); + if (!mft) { + Eprintf ("Couldn't open $MFT/$DATA: %s\n", strerror (errno)); + // free / close + return -1; + } + + if (ntfs_attr_pread (mft, ctx->vol->mft_record_size * ctx->mft_num, ctx->vol->mft_record_size, ctx->inode->mrec) < ctx->vol->mft_record_size) { + Eprintf ("Couldn't read MFT Record %lld: %s.\n", ctx->mft_num, strerror (errno)); + // free / close + return -1; + } + } + + if (ctx->flags_match & ctx->flags_search) { + break; + } + + if (ntfs_inode_close (ctx->inode)) { + Eprintf ("Error closing inode %lld.", ctx->mft_num); + return -errno; + } + + ctx->inode = NULL; + } + + return (ctx->inode == NULL); +} + + #if 0 hamming weight inline unsigned int hweight32(unsigned int w) diff --git a/ntfsprogs/utils.h b/ntfsprogs/utils.h index 733c2892..66864154 100644 --- a/ntfsprogs/utils.h +++ b/ntfsprogs/utils.h @@ -81,4 +81,33 @@ s64 utc2ntfs (time_t time); ATTR_RECORD * find_attribute (const ATTR_TYPES type, ntfs_attr_search_ctx *ctx); ATTR_RECORD * find_first_attribute (const ATTR_TYPES type, MFT_RECORD *mft); +/** + * defines... + * if *not in use* then the other flags are ignored? + */ +#define FEMR_IN_USE 1 << 0 +#define FEMR_NOT_IN_USE 1 << 1 +#define FEMR_FILE 1 << 2 // $DATA +#define FEMR_DIR 1 << 3 // $INDEX_ROOT, "$I30" +#define FEMR_METADATA 1 << 4 +#define FEMR_NOT_METADATA 1 << 5 +#define FEMR_BASE_RECORD 1 << 6 +#define FEMR_NOT_BASE_RECORD 1 << 7 +#define FEMR_ALL_RECORDS 0xFF + +/** + * struct mft_search_ctx + */ +struct mft_search_ctx { + int flags_search; + int flags_match; + ntfs_inode *inode; + u64 mft_num; + ntfs_volume *vol; +}; + +struct mft_search_ctx * mft_get_search_ctx (ntfs_volume *vol); +void mft_put_search_ctx (struct mft_search_ctx *ctx); +int mft_next_record (struct mft_search_ctx *ctx); + #endif /* _NTFS_UTILS_H_ */