📄 fs_dir.c
字号:
/* * fs_dir * The Sleuth Kit * * Brian Carrier [carrier <at> sleuthkit [dot] org] * Copyright (c) 2008 Brian Carrier. All Rights reserved * * This software is distributed under the Common Public License 1.0 * *//** * \file fs_dir.c * Create, manage, etc. the TSK_FS_DIR structures. */#include "tsk_fs_i.h"/** \internal* Allocate a FS_DIR structure to load names into* * @param a_cnt target number of FS_DENT entries to fit in* @returns NULL on error*/TSK_FS_DIR *tsk_fs_dir_alloc(TSK_FS_INFO * a_fs, size_t a_cnt){ TSK_FS_DIR *fs_dir; // allocate and initialize the structure if ((fs_dir = (TSK_FS_DIR *) tsk_malloc(sizeof(TSK_FS_DIR))) == NULL) { return NULL; } fs_dir->names_alloc = a_cnt; fs_dir->names_used = 0; if ((fs_dir->names = (TSK_FS_NAME *) tsk_malloc(sizeof(TSK_FS_NAME) * fs_dir->names_alloc)) == NULL) { free(fs_dir); return NULL; } fs_dir->fs_info = a_fs; fs_dir->tag = TSK_FS_DIR_TAG; return fs_dir;}/** \internal* Make the buffer in the FS_DIR structure larger.* * @param a_fs_dir Structure to enhance* @param a_cnt target number of FS_DENT entries to fit in* @returns 1 on error and 0 on success*/uint8_ttsk_fs_dir_realloc(TSK_FS_DIR * a_fs_dir, size_t a_cnt){ if ((a_fs_dir == NULL) || (a_fs_dir->tag != TSK_FS_DIR_TAG)) return 1; a_fs_dir->names_alloc = a_cnt; if ((a_fs_dir->names = (TSK_FS_NAME *) tsk_realloc((void *) a_fs_dir->names, sizeof(TSK_FS_NAME) * a_fs_dir->names_alloc)) == NULL) { return 1; } return 0;}/** \internal* Reset the structures in a FS_DIR so that it can be reused.* @param a_fs_dir FS_DIR structure to re-use*/voidtsk_fs_dir_reset(TSK_FS_DIR * a_fs_dir){ if ((a_fs_dir == NULL) || (a_fs_dir->tag != TSK_FS_DIR_TAG)) return; if (a_fs_dir->fs_file) { tsk_fs_file_close(a_fs_dir->fs_file); a_fs_dir->fs_file = NULL; } a_fs_dir->names_used = 0;}/** \internal * Add a FS_DENT structure to a FS_DIR structure by copying its * contents into the internal buffer. Checks for * duplicates and expands buffer as needed. * @param a_fs_dir DIR to add to * @param a_fs_name DENT to add * @returns 1 on error (memory allocation problems) and 0 on success */uint8_ttsk_fs_dir_add(TSK_FS_DIR * a_fs_dir, const TSK_FS_NAME * a_fs_name){ TSK_FS_NAME *fs_name_dest = NULL; size_t i; // see if we already have it in the buffer / queue for (i = 0; i < a_fs_dir->names_used; i++) { if ((a_fs_name->meta_addr == a_fs_dir->names[i].meta_addr) && (strcmp(a_fs_name->name, a_fs_dir->names[i].name) == 0)) { /* We do not check type because then we cannot detect NTFS orphan file * duplicates that are added as "-/r" while a similar entry exists as "r/r" (a_fs_name->type == a_fs_dir->names[i].type)) { */ // if the one in the list is unalloc and we have an alloc, replace it if ((a_fs_dir->names[i].flags & TSK_FS_NAME_FLAG_UNALLOC) && (a_fs_name->flags & TSK_FS_NAME_FLAG_ALLOC)) { fs_name_dest = &a_fs_dir->names[i]; // free the memory - not the most effecient, but prevents // duplicate code. if (fs_name_dest->name) { free(fs_name_dest->name); fs_name_dest->name = NULL; } if (fs_name_dest->shrt_name) { free(fs_name_dest->shrt_name); fs_name_dest->shrt_name = NULL; } break; } else { return 0; } } } if (fs_name_dest == NULL) { // make sure we got the room if (a_fs_dir->names_used >= a_fs_dir->names_alloc) { if (tsk_fs_dir_realloc(a_fs_dir, a_fs_dir->names_used + 256)) return 1; } fs_name_dest = &a_fs_dir->names[a_fs_dir->names_used++]; } fs_name_dest->flags = a_fs_name->flags; fs_name_dest->type = a_fs_name->type; fs_name_dest->meta_addr = a_fs_name->meta_addr; fs_name_dest->tag = a_fs_name->tag; // if there is a name, then copy it in if (a_fs_name->name) { if ((fs_name_dest->name = (char *) tsk_malloc(a_fs_name->name_size)) == NULL) { return 1; } fs_name_dest->name_size = a_fs_name->name_size; strncpy(fs_name_dest->name, a_fs_name->name, fs_name_dest->name_size); } else { fs_name_dest->name = NULL; fs_name_dest->name_size = 0; } // copy in a short name if it exists if (a_fs_name->shrt_name) { if ((fs_name_dest->shrt_name = (char *) tsk_malloc(a_fs_name->shrt_name_size)) == NULL) { return 1; } fs_name_dest->shrt_name_size = a_fs_name->shrt_name_size; strncpy(fs_name_dest->shrt_name, a_fs_name->shrt_name, fs_name_dest->shrt_name_size); } else { fs_name_dest->shrt_name = NULL; fs_name_dest->shrt_name_size = 0; } return 0;}/** \ingroup fslib* Open a directory (using its metadata addr) so that each of the files in it can be accessed.* @param a_fs File system to analyze* @param a_addr Metadata address of the directory to open* @returns NULL on error*/TSK_FS_DIR *tsk_fs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_INUM_T a_addr){ TSK_FS_DIR *fs_dir = NULL; TSK_RETVAL_ENUM retval; if ((a_fs == NULL) || (a_fs->tag != TSK_FS_INFO_TAG) || (a_fs->dir_open_meta == NULL)) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_dir_open_meta: called with NULL or unallocated structures"); return NULL; } retval = a_fs->dir_open_meta(a_fs, &fs_dir, a_addr); return fs_dir;}/** \ingroup fslib* Open a directory (using its path) so that each of the files in it can be accessed.* @param a_fs File system to analyze* @param a_dir Path of the directory to open* @returns NULL on error*/TSK_FS_DIR *tsk_fs_dir_open(TSK_FS_INFO * a_fs, const char *a_dir){ TSK_INUM_T inum; int8_t retval; TSK_FS_DIR *fs_dir; TSK_FS_NAME *fs_name; if ((a_fs == NULL) || (a_fs->tag != TSK_FS_INFO_TAG)) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_dir_open: called with NULL or unallocated structures"); return NULL; } // allocate a structure to store the name in if ((fs_name = tsk_fs_name_alloc(128, 32)) == NULL) { return NULL; } retval = tsk_fs_path2inum(a_fs, a_dir, &inum, fs_name); if (retval == -1) { return NULL; } else if (retval == 1) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_dir_open: path not found: %s", a_dir); return NULL; } fs_dir = tsk_fs_dir_open_meta(a_fs, inum); // add the name structure on to it if ((fs_dir) && (fs_dir->fs_file)) fs_dir->fs_file->name = fs_name; return fs_dir;}/** \ingroup fslib* Close the directory that was opened with tsk_fs_dir_open() * @param a_fs_dir Directory to close */voidtsk_fs_dir_close(TSK_FS_DIR * a_fs_dir){ size_t i; if ((a_fs_dir == NULL) || (a_fs_dir->tag != TSK_FS_DIR_TAG)) { return; } for (i = 0; i < a_fs_dir->names_used; i++) { if (a_fs_dir->names[i].name) { free(a_fs_dir->names[i].name); a_fs_dir->names[i].name = NULL; a_fs_dir->names[i].name_size = 0; } if (a_fs_dir->names[i].shrt_name) { free(a_fs_dir->names[i].shrt_name); a_fs_dir->names[i].shrt_name = NULL; a_fs_dir->names[i].shrt_name_size = 0; } } free(a_fs_dir->names); if (a_fs_dir->fs_file) { tsk_fs_file_close(a_fs_dir->fs_file); a_fs_dir->fs_file = NULL; } a_fs_dir->tag = 0; free(a_fs_dir);}/** \ingroup fslib* Returns the number of files and subdirectories in a directory. * @param a_fs_dir Directory to get information about * @returns Number of files and subdirectories (or 0 on error) */size_ttsk_fs_dir_getsize(const TSK_FS_DIR * a_fs_dir){ if ((a_fs_dir == NULL) || (a_fs_dir->tag != TSK_FS_DIR_TAG)) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_dir_getsize: called with NULL or unallocated structures"); return 0; } return a_fs_dir->names_used;}/** \ingroup fslib* Return a specific file or subdirectory from an open directory. * @param a_fs_dir Directory to analyze * @param a_idx Index of file in directory to open (0-based) * @returns NULL on error */TSK_FS_FILE *tsk_fs_dir_get(const TSK_FS_DIR * a_fs_dir, size_t a_idx){ TSK_FS_NAME *fs_name; TSK_FS_FILE *fs_file; if ((a_fs_dir == NULL) || (a_fs_dir->tag != TSK_FS_DIR_TAG) || (a_fs_dir->fs_info == NULL)) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_dir_get: called with NULL or unallocated structures"); return NULL; } if (a_fs_dir->names_used <= a_idx) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_dir_get: Index (%" PRIuSIZE ") too large (%" PRIuSIZE ")", a_idx, a_fs_dir->names_used); return NULL; } // allocate a structure to return if ((fs_file = tsk_fs_file_alloc(a_fs_dir->fs_info)) == NULL) return NULL; fs_name = &(a_fs_dir->names[a_idx]); // copy the name into another structure that we can return and later free if ((fs_file->name = tsk_fs_name_alloc(fs_name->name ? strlen(fs_name->name) + 1 : 0, fs_name->shrt_name ? strlen(fs_name->shrt_name) + 1 : 0)) == NULL) { return NULL; } if (tsk_fs_name_copy(fs_file->name, fs_name)) return NULL; /* load the fs_meta structure if possible. * Must have non-zero inode addr or have allocated name (if inode is 0) */ if (((fs_name->meta_addr) || (fs_name->flags & TSK_FS_NAME_FLAG_ALLOC))) { if (a_fs_dir->fs_info->file_add_meta(a_fs_dir->fs_info, fs_file, fs_name->meta_addr)) { if (tsk_verbose) tsk_error_print(stderr); tsk_error_reset(); } } return fs_file;}#define MAX_DEPTH 128#define DIR_STRSZ 4096/** \internal*/typedef struct { /* Recursive path stuff */ /* how deep in the directory tree are we */ unsigned int depth; /* pointer in dirs string to where '/' is for given depth */ char *didx[MAX_DEPTH]; /* The current directory name string */ char dirs[DIR_STRSZ]; TSK_STACK *stack_seen; /* Set to one to collect inode info that can be used for orphan listing */ uint8_t save_inum_named;} DENT_DINFO;static uint8_ttsk_fs_dir_walk_lcl(TSK_FS_INFO * a_fs, DENT_DINFO * a_dinfo, TSK_INUM_T a_addr, TSK_FS_DIR_WALK_FLAG_ENUM a_flags, TSK_FS_DIR_WALK_CB a_action, void *a_ptr){ TSK_FS_DIR *fs_dir; TSK_FS_FILE *fs_file; size_t i; // get the list of entries in the directory if ((fs_dir = tsk_fs_dir_open_meta(a_fs, a_addr)) == NULL) { return 1; } /* Allocate a file structure for the callbacks. We * will allocate fs_meta structures as needed and * point into the fs_dir structure for the names. */ if ((fs_file = tsk_fs_file_alloc(a_fs)) == NULL) { tsk_fs_dir_close(fs_dir); return 1; } for (i = 0; i < fs_dir->names_used; i++) { int retval; /* Point name to the buffer of names. We need to be * careful about resetting this before we free fs_file */ fs_file->name = (TSK_FS_NAME *) & fs_dir->names[i]; /* load the fs_meta structure if possible. * Must have non-zero inode addr or have allocated name (if inode is 0) */ if (((fs_file->name->meta_addr) || (fs_file->name->flags & TSK_FS_NAME_FLAG_ALLOC))) { if (a_fs->file_add_meta(a_fs, fs_file, fs_file->name->meta_addr)) { if (tsk_verbose) tsk_error_print(stderr); tsk_error_reset(); } } // call the action if we have the right flags. if ((fs_file->name->flags & a_flags) == fs_file->name->flags) { retval = a_action(fs_file, a_dinfo->dirs, a_ptr); if (retval == TSK_WALK_STOP) { tsk_fs_dir_close(fs_dir); fs_file->name = NULL; tsk_fs_file_close(fs_file); /* free the list -- fs_dir_walk has no way * of knowing that we stopped early w/out error. */ if (a_dinfo->save_inum_named) { tsk_list_free(a_fs->list_inum_named);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -