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

📄 fatfs_dent.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** fatfs_dent** The Sleuth Kit **** file name layer support for the FAT file system**** Brian Carrier [carrier <at> sleuthkit [dot] org]** Copyright (c) 2006-2008 Brian Carrier, Basis Technology.  All Rights reserved** Copyright (c) 2003-2005 Brian Carrier.  All rights reserved **** TASK** Copyright (c) 2002 Brian Carrier, @stake Inc.  All rights reserved****** This software is distributed under the Common Public License 1.0**** Unicode added with support from I.D.E.A.L. Technology Corp (Aug '05)***//** * \file fatfs_dent.c * Contains the internal TSK FAT file name processing code. */#include "tsk_fs_i.h"#include "tsk_fatfs.h"/* * DESIGN NOTES * * the basic goal of this code is to parse directory entry structures for * file names.  The main function is fatfs_parse_buf, which parses * a buffer and stores the entries in FS_DIR.  That structure is then * used by dir_get() or dir_walk() to provide the data back to the user.  * * One of the odd aspects of this code is that the 'inode' values are * the 'slot-address'.  Refer to the document on how FAT was implemented * for more details. This means that we need to search for the actual * 'inode' address for the '.' and '..' entries though!  The search * for '..' is quite painful if this code is called from a random  * location.  It does save what the parent is though, so the search * only has to be done once per session. *//* Special data structure allocated for each directory to hold the long * file name entries until all entries have been found */typedef struct {    uint8_t name[FATFS_MAXNAMLEN_UTF8]; /* buffer for lfn - in reverse order */    uint16_t start;             /* current start of name */    uint8_t chk;                /* current checksum */    uint8_t seq;                /* seq of first entry in lfn */} FATFS_LFN;/* * name_walk callback used when finding the parent directory.  It * forces the walking process to stop when we hit a target directory. * A list of directory to parent directory mappings is built up during * the walk and this function is used to stop that building process. */static TSK_WALK_RET_ENUMfind_parent_act(TSK_FS_FILE * fs_file, const char *a_path, void *ptr){    TSK_INUM_T par_inum = *(TSK_INUM_T *) ptr;    if (fs_file->meta == NULL)        return TSK_WALK_CONT;    if (fs_file->meta->addr == par_inum)        //return TSK_WALK_STOP;        return TSK_WALK_CONT;    return TSK_WALK_CONT;}static uint8_tfatfs_dir_buf_add(FATFS_INFO * fatfs, TSK_INUM_T par_inum,    TSK_INUM_T dir_inum){    size_t q;    for (q = 0; q < fatfs->dir_buf_next; q++) {        if (fatfs->dir_buf[q] == dir_inum) {            return 0;        }    }    // make sure we have room    if (fatfs->dir_buf_next == fatfs->dir_buf_size) {        fatfs->dir_buf_size += 256;        if ((fatfs->dir_buf =                (TSK_INUM_T *) tsk_realloc(fatfs->                    dir_buf,                    fatfs->dir_buf_size * sizeof(TSK_INUM_T))) == NULL) {            return 1;        }        if ((fatfs->par_buf =                (TSK_INUM_T *) tsk_realloc(fatfs->                    par_buf,                    fatfs->dir_buf_size * sizeof(TSK_INUM_T))) == NULL) {            return 1;        }    }    //add them    fatfs->dir_buf[fatfs->dir_buf_next] = dir_inum;    fatfs->par_buf[fatfs->dir_buf_next] = par_inum;    fatfs->dir_buf_next++;    return 0;}/*  * Process the contents of a directory and add them to FS_DIR.  *  * @param fatfs File system information structure * @param a_fs_dir Structure to store the files in.  * @param list_seen List of directory inodes that have been seen thus far in * directory walking (can be a pointer to a NULL pointer on first call).  * @param buf Buffer that contains the directory contents.  * @param len Length of buffer in bytes (must be a multiple of sector size) * @param addrs Array where each element is the original address of the  * corresponding block in buf (size of array is number of blocks in directory). * * @return -1 on error, 0 on success, and 1 to stop */static TSK_RETVAL_ENUMfatfs_dent_parse_buf(FATFS_INFO * fatfs, TSK_FS_DIR * a_fs_dir, char *buf,    TSK_OFF_T len, TSK_DADDR_T * addrs){    unsigned int idx, sidx;    int a, b;    TSK_INUM_T inode, ibase;    fatfs_dentry *dep;    TSK_FS_INFO *fs = (TSK_FS_INFO *) & fatfs->fs_info;    int sectalloc;    TSK_FS_NAME *fs_name;    FATFS_LFN lfninfo;    if (buf == NULL) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_ARG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "fatfs_dent_parse_buf: buffer is NULL");        return TSK_ERR;    }    dep = (fatfs_dentry *) buf;    if ((fs_name = tsk_fs_name_alloc(FATFS_MAXNAMLEN_UTF8, 32)) == NULL) {        return TSK_ERR;    }    memset(&lfninfo, 0, sizeof(FATFS_LFN));    lfninfo.start = FATFS_MAXNAMLEN_UTF8 - 1;    for (sidx = 0; sidx < (unsigned int) (len / fatfs->ssize); sidx++) {        /* Get the base inode for this sector */        ibase = FATFS_SECT_2_INODE(fatfs, addrs[sidx]);        if (ibase > fs->last_inum) {            tsk_error_reset();            tsk_errno = TSK_ERR_FS_ARG;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "fatfs_parse: inode address is too large");            tsk_fs_name_free(fs_name);            return TSK_COR;        }        if (tsk_verbose)            tsk_fprintf(stderr,                "fatfs_dent_parse_buf: Parsing sector %" PRIuDADDR                "\n", addrs[sidx]);        if ((sectalloc = fatfs_is_sectalloc(fatfs, addrs[sidx])) == -1) {            if (tsk_verbose) {                tsk_fprintf(stderr,                    "fatfs_dent_parse_buf: Error looking up sector allocation: %"                    PRIuDADDR "\n", addrs[sidx]);                tsk_error_print(stderr);            }            tsk_error_reset();            continue;        }        /* cycle through the directory entries */        for (idx = 0; idx < fatfs->dentry_cnt_se; idx++, dep++) {            fatfs_dentry *dir;            int i;            /* is it a valid dentry? */            if (0 == fatfs_isdentry(fatfs, dep))                continue;            /* Copy the directory entry into the TSK_FS_NAME structure */            dir = (fatfs_dentry *) dep;            inode = ibase + idx;            /* Take care of the name              * Copy a long name to a buffer and take action if it             * is a small name */            if ((dir->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) {                fatfs_dentry_lfn *dirl = (fatfs_dentry_lfn *) dir;                /* Store the name in dinfo until we get the 8.3 name                  * Use the checksum to identify a new sequence                  * */                if (((dirl->seq & FATFS_LFN_SEQ_FIRST)                        && (dirl->seq != FATFS_SLOT_DELETED))                    || (dirl->chksum != lfninfo.chk)) {                    // @@@ Do a partial output here                    /* Reset the values */                    lfninfo.seq = dirl->seq & FATFS_LFN_SEQ_MASK;                    lfninfo.chk = dirl->chksum;                    lfninfo.start = FATFS_MAXNAMLEN_UTF8 - 1;                }                else if (dirl->seq != lfninfo.seq - 1) {                    // @@@ Check the sequence number - the checksum is correct though...                }                /* Copy the UTF16 values starting at end of buffer */                for (a = 3; a >= 0; a--) {                    if ((lfninfo.start > 0))                        lfninfo.name[lfninfo.start--] = dirl->part3[a];                }                for (a = 11; a >= 0; a--) {                    if ((lfninfo.start > 0))                        lfninfo.name[lfninfo.start--] = dirl->part2[a];                }                for (a = 9; a >= 0; a--) {                    if ((lfninfo.start > 0))                        lfninfo.name[lfninfo.start--] = dirl->part1[a];                }                // Skip ahead until we get a new sequence num or the 8.3 name                continue;            }            /* Special case for volume label: name does not have an             * extension and we add a note at the end that it is a label */            else if ((dir->attrib & FATFS_ATTR_VOLUME) ==                FATFS_ATTR_VOLUME) {                a = 0;                for (b = 0; b < 8; b++) {                    if ((dir->name[b] >= 0x20) && (dir->name[b] != 0xff)) {                        fs_name->name[a++] = dir->name[b];                    }                    else {                        fs_name->name[a++] = '^';                    }                }                for (b = 0; b < 3; b++) {                    if ((dir->ext[b] >= 0x20) && (dir->ext[b] != 0xff)) {                        fs_name->name[a++] = dir->ext[b];                    }                    else {                        fs_name->name[a++] = '^';                    }                }                fs_name->name[a] = '\0';                /* Append a string to show it is a label */                if (a + 22 < FATFS_MAXNAMLEN_UTF8) {                    char *volstr = " (Volume Label Entry)";                    strncat(fs_name->name, volstr,                        FATFS_MAXNAMLEN_UTF8 - a);                }            }            /* A short (8.3) entry */            else {                char *name_ptr; // The dest location for the short name                /* if we have a lfn, copy it into fs_name->name                 * and put the short name in fs_name->shrt_name */                if (lfninfo.start != FATFS_MAXNAMLEN_UTF8 - 1) {                    int retVal;                    /* @@@ Check the checksum */                    /* Convert the UTF16 to UTF8 */                    UTF16 *name16 =                        (UTF16 *) ((uintptr_t) & lfninfo.                        name[lfninfo.start + 1]);                    UTF8 *name8 = (UTF8 *) fs_name->name;                    retVal =                        tsk_UTF16toUTF8(fs->endian,                        (const UTF16 **) &name16,                        (UTF16 *) & lfninfo.name[FATFS_MAXNAMLEN_UTF8],                        &name8,                        (UTF8 *) ((uintptr_t) name8 +                            FATFS_MAXNAMLEN_UTF8), TSKlenientConversion);                    if (retVal != TSKconversionOK) {                        tsk_error_reset();                        tsk_errno = TSK_ERR_FS_UNICODE;                        snprintf(tsk_errstr, TSK_ERRSTR_L,                            "fatfs_parse: Error converting FAT LFN to UTF8: %d",                            retVal);                        continue;                    }                    /* Make sure it is NULL Terminated */                    if ((uintptr_t) name8 >                        (uintptr_t) fs_name->name + FATFS_MAXNAMLEN_UTF8)                        fs_name->name[FATFS_MAXNAMLEN_UTF8 - 1] = '\0';                    else                        *name8 = '\0';                    /* Clean up name */                    i = 0;                    while (fs_name->name[i] != '\0') {                        if (TSK_IS_CNTRL(fs_name->name[i]))                            fs_name->name[i] = '^';                        i++;                    }                    lfninfo.start = FATFS_MAXNAMLEN_UTF8 - 1;                    name_ptr = fs_name->shrt_name;      // put 8.3 into shrt_name                }                /* We don't have a LFN, so put the short name in                  * fs_name->name */                else {                    fs_name->shrt_name[0] = '\0';                    name_ptr = fs_name->name;   // put 8.3 into normal location                }                /* copy in the short name into the place specified above.                  * Skip spaces and put in the . */                a = 0;                for (b = 0; b < 8; b++) {                    if ((dir->name[b] != 0) && (dir->name[b] != 0xff) &&                        (dir->name[b] != 0x20)) {                        if ((b == 0)                            && (dir->name[0] == FATFS_SLOT_DELETED)) {                            name_ptr[a++] = '_';                        }                        else if ((dir->lowercase & FATFS_CASE_LOWER_BASE)                            && (dir->name[b] >= 'A')                            && (dir->name[b] <= 'Z')) {                            name_ptr[a++] = dir->name[b] + 32;                        }                        else {                            name_ptr[a++] = dir->name[b];                        }                    }                }                for (b = 0; b < 3; b++) {                    if ((dir->ext[b] != 0) && (dir->ext[b] != 0xff) &&                        (dir->ext[b] != 0x20)) {                        if (b == 0)                            name_ptr[a++] = '.';                        if ((dir->lowercase & FATFS_CASE_LOWER_EXT) &&                            (dir->ext[b] >= 'A') && (dir->ext[b] <= 'Z'))                            name_ptr[a++] = dir->ext[b] + 32;                        else                            name_ptr[a++] = dir->ext[b];                    }                }                name_ptr[a] = '\0';            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -