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

📄 fatfs_dent.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
            /* Clean up name to remove control chars */            i = 0;            while (fs_name->name[i] != '\0') {                if (TSK_IS_CNTRL(fs_name->name[i]))                    fs_name->name[i] = '^';                i++;            }            /* file type: FAT only knows DIR and FILE */            if ((dir->attrib & FATFS_ATTR_DIRECTORY) ==                FATFS_ATTR_DIRECTORY)                fs_name->type = TSK_FS_NAME_TYPE_DIR;            else                fs_name->type = TSK_FS_NAME_TYPE_REG;            /* Get inode */            fs_name->meta_addr = inode;            /* Handle the . and .. entries specially             * The current inode 'address' they have is for the current             * slot in the cluster, but it needs to refer to the original             * slot              */            if (TSK_FS_ISDOT(fs_name->name)) {                if (fs_name->name[1] == '\0') {                    inode = fs_name->meta_addr =                        a_fs_dir->fs_file->meta->addr;                }                /* for the parent directory, look up in the list that                  * is maintained in fafs_info */                else if (fs_name->name[1] == '.') {                    size_t q;                    uint8_t dir_found = 0;                    for (q = 0; q < fatfs->dir_buf_next; q++) {                        if (fatfs->dir_buf[q] ==                            a_fs_dir->fs_file->meta->addr) {                            inode = fs_name->meta_addr = fatfs->par_buf[q];                            dir_found = 1;                            break;                        }                    }                    if ((dir_found == 0) && (fs->isOrphanHunting)) {                        /* if we are currently scanning the fs to determine the orphan files,                         * then we do not care about the value of '..' and this can only cause                         * infinite loop problems */                        inode = fs_name->meta_addr = 0;                    }                    if (dir_found == 0) {                        /* The parent directory is not in the list.  We are going to walk                         * the directory until we hit this directory. This process will                         * populate the buffer table and we will then rescan it */                        if (tsk_fs_dir_walk(fs, fs->root_inum,                                TSK_FS_DIR_WALK_FLAG_ALLOC |                                TSK_FS_DIR_WALK_FLAG_RECURSE,                                find_parent_act,                                (void *) &a_fs_dir->fs_file->meta->addr)) {                            return 0;                        }                        for (q = 0; q < fatfs->dir_buf_next; q++) {                            if (fatfs->dir_buf[q] ==                                a_fs_dir->fs_file->meta->addr) {                                inode = fs_name->meta_addr =                                    fatfs->par_buf[q];                                dir_found = 1;                                break;                            }                        }                        // if we did not find it, then it was probably                         // from the orphan directory...                        if (dir_found == 0)                            inode = fs_name->meta_addr =                                TSK_FS_ORPHANDIR_INUM(fs);                    }                }            }            else {                /* Save the (non-. or ..) directory to parent directory info to local                 * structures so that we can later fill into the inode                 * info for '..' entries */                if (fs_name->type == TSK_FS_NAME_TYPE_DIR) {                    if (fatfs_dir_buf_add(fatfs,                            a_fs_dir->fs_file->meta->addr, inode))                        return TSK_ERR;                }            }            /* The allocation status of an entry is based on the allocation             * status of the sector it is in and the flag.  Deleted directories             * do not always clear the flags of each entry             */            if (sectalloc == 1) {                fs_name->flags = (dep->name[0] == FATFS_SLOT_DELETED) ?                    TSK_FS_NAME_FLAG_UNALLOC : TSK_FS_NAME_FLAG_ALLOC;            }            else {                fs_name->flags = TSK_FS_NAME_FLAG_UNALLOC;            }            tsk_fs_dir_add(a_fs_dir, fs_name);        }    }    tsk_fs_name_free(fs_name);    return TSK_OK;}/************************************************************************** * * dent_walk * *************************************************************************//* values used to copy the directory contents into a buffer */typedef struct {    /* ptr to the current location in a local buffer */    char *curdirptr;    /* number of bytes left in curdirptr */    size_t dirleft;    /* ptr to a local buffer for the stack of sector addresses */    TSK_DADDR_T *addrbuf;    /* num of entries allocated to addrbuf */    size_t addrsize;    /* The current index in the addrbuf stack */    size_t addridx;} FATFS_LOAD_DIR;/** * file walk callback that is used to load directory contents * into a buffer */static TSK_WALK_RET_ENUMfatfs_dent_action(TSK_FS_FILE * fs_file, TSK_OFF_T a_off, TSK_DADDR_T addr,    char *buf, size_t size, TSK_FS_BLOCK_FLAG_ENUM flags, void *ptr){    FATFS_LOAD_DIR *load = (FATFS_LOAD_DIR *) ptr;    /* how much of the buffer are we copying */    size_t len = (load->dirleft < size) ? load->dirleft : size;    /* Copy the sector into a buffer and increment the pointers */    memcpy(load->curdirptr, buf, len);    load->curdirptr = (char *) ((uintptr_t) load->curdirptr + len);    load->dirleft -= len;    /* fill in the stack of addresses of sectors      *     * if we are at the last entry, then realloc more */    if (load->addridx == load->addrsize) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_ARG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "fatfs_dent_walk: Trying to put more sector address in stack than were allocated (%lu)",            (long) load->addridx);        return TSK_WALK_ERROR;    }    /* Add this sector to the stack */    load->addrbuf[load->addridx++] = addr;    if (load->dirleft)        return TSK_WALK_CONT;    else        return TSK_WALK_STOP;}/** \internal* Process a directory and load up FS_DIR with the entries. If a pointer to* an already allocated FS_DIR struture is given, it will be cleared.  If no existing* FS_DIR structure is passed (i.e. NULL), then a new one will be created. If the return * value is error or corruption, then the FS_DIR structure could  * have entries (depending on when the error occured). ** @param a_fs File system to analyze* @param a_fs_dir Pointer to FS_DIR pointer. Can contain an already allocated* structure or a new structure. * @param a_addr Address of directory to process.* @returns error, corruption, ok etc. */TSK_RETVAL_ENUMfatfs_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,    TSK_INUM_T a_addr){    TSK_OFF_T size, len;    FATFS_INFO *fatfs = (FATFS_INFO *) a_fs;    char *dirbuf;    TSK_DADDR_T *addrbuf;    FATFS_LOAD_DIR load;    int retval;    TSK_FS_DIR *fs_dir;    if ((a_addr < a_fs->first_inum) || (a_addr > a_fs->last_inum)) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_WALK_RNG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "fatfs_dir_open_meta: invalid a_addr value: %" PRIuINUM "\n",            a_addr);        return TSK_ERR;    }    else if (a_fs_dir == NULL) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_ARG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "fatfs_dir_open_meta: NULL fs_attr argument given");        return TSK_ERR;    }    fs_dir = *a_fs_dir;    if (fs_dir) {        tsk_fs_dir_reset(fs_dir);    }    else {        if ((*a_fs_dir = fs_dir = tsk_fs_dir_alloc(a_fs, 128)) == NULL) {            return TSK_ERR;        }    }    //  handle the orphan directory if its contents were requested    if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) {        size_t i;        TSK_RETVAL_ENUM retval2 = tsk_fs_dir_find_orphans(a_fs, fs_dir);        if (retval2 == TSK_ERR)            return retval2;        // update the directory to parent mapping (since we bypassed the code that does this in parse)        for (i = 0; i < fs_dir->names_used; i++) {            if (fs_dir->names[i].type == TSK_FS_NAME_TYPE_DIR) {                if (fatfs_dir_buf_add(fatfs, a_addr,                        fs_dir->names[i].meta_addr))                    return TSK_ERR;            }        }        return retval2;    }    fs_dir->fs_file = tsk_fs_file_open_meta(a_fs, NULL, a_addr);    if (fs_dir->fs_file == NULL) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_INODE_NUM;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "fatfs_dir_open_meta: %" PRIuINUM " is not a valid inode",            a_addr);        return TSK_COR;    }    size = fs_dir->fs_file->meta->size;    len = roundup(size, fatfs->ssize);    if (tsk_verbose)        tsk_fprintf(stderr,            "fatfs_dir_open_meta: Processing directory %" PRIuINUM "\n",            a_addr);    /* Make a copy of the directory contents using file_walk */    if ((dirbuf = tsk_malloc((size_t) len)) == NULL) {        return TSK_ERR;    }    load.curdirptr = dirbuf;    load.dirleft = (size_t) size;    /* We are going to save the address of each sector in the directory     * in a stack - they are needed to determine the inode address.       */    load.addrsize = (size_t) (len / fatfs->ssize);    addrbuf =        (TSK_DADDR_T *) tsk_malloc(load.addrsize * sizeof(TSK_DADDR_T));    if (addrbuf == NULL) {        free(dirbuf);        return TSK_ERR;    }    /* Set the variables that are used during the copy */    load.addridx = 0;    load.addrbuf = addrbuf;    /* save the directory contents into dirbuf */    if (tsk_fs_file_walk(fs_dir->fs_file,            TSK_FS_FILE_WALK_FLAG_SLACK,            fatfs_dent_action, (void *) &load)) {        strncat(tsk_errstr2, " - fatfs_dir_open_meta",            TSK_ERRSTR_L - strlen(tsk_errstr2));        free(dirbuf);        free(addrbuf);        return TSK_COR;    }    /* We did not copy the entire directory, which occurs if an error occured */    if (load.dirleft > 0) {        tsk_error_reset();        tsk_errno = TSK_ERR_FS_FWALK;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "fatfs_dir_open_meta: Error reading directory %" PRIuINUM,            a_addr);        /* Free the local buffers */        free(dirbuf);        free(addrbuf);        return TSK_COR;    }    retval = fatfs_dent_parse_buf(fatfs, fs_dir, dirbuf, len, addrbuf);    free(dirbuf);    free(addrbuf);    // if we are listing the root directory, add the Orphan directory and special FAT file entries    if (a_addr == a_fs->root_inum) {        TSK_FS_NAME *fs_name = tsk_fs_name_alloc(256, 0);        if (fs_name == NULL)            return TSK_ERR;        // MBR Entry         strncpy(fs_name->name, FATFS_MBRNAME, fs_name->name_size);        fs_name->meta_addr = FATFS_MBRINO(a_fs);        fs_name->type = TSK_FS_NAME_TYPE_VIRT;        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;        if (tsk_fs_dir_add(fs_dir, fs_name)) {            tsk_fs_name_free(fs_name);            return TSK_ERR;        }        // FAT1 Entry         strncpy(fs_name->name, FATFS_FAT1NAME, fs_name->name_size);        fs_name->meta_addr = FATFS_FAT1INO(a_fs);        fs_name->type = TSK_FS_NAME_TYPE_VIRT;        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;        if (tsk_fs_dir_add(fs_dir, fs_name)) {            tsk_fs_name_free(fs_name);            return TSK_ERR;        }        // FAT2 Entry         strncpy(fs_name->name, FATFS_FAT2NAME, fs_name->name_size);        fs_name->meta_addr = FATFS_FAT2INO(a_fs);        fs_name->type = TSK_FS_NAME_TYPE_VIRT;        fs_name->flags = TSK_FS_NAME_FLAG_ALLOC;        if (tsk_fs_dir_add(fs_dir, fs_name)) {            tsk_fs_name_free(fs_name);            return TSK_ERR;        }        // orphan directory        if (tsk_fs_dir_make_orphan_dir_name(a_fs, fs_name)) {            tsk_fs_name_free(fs_name);            return TSK_ERR;        }        if (tsk_fs_dir_add(fs_dir, fs_name)) {            tsk_fs_name_free(fs_name);            return TSK_ERR;        }        tsk_fs_name_free(fs_name);    }    return retval;}

⌨️ 快捷键说明

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