⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs_dir.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -