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

📄 fs_attr.c

📁 linux下开发的针对所有磁盘的数据恢复的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    for (fs_attr_run = fs_attr->nrd.run; fs_attr_run;        fs_attr_run = fs_attr_run->next) {        TSK_DADDR_T addr, len_idx;        addr = fs_attr_run->addr;        /* cycle through each block in the run */        for (len_idx = 0; len_idx < fs_attr_run->len; len_idx++) {            TSK_FS_BLOCK_FLAG_ENUM myflags;            /* If the address is too large then give an error */            if (addr + len_idx > fs->last_block) {                if (fs_attr->fs_file->meta->                    flags & TSK_FS_META_FLAG_UNALLOC)                    tsk_errno = TSK_ERR_FS_RECOVER;                else                    tsk_errno = TSK_ERR_FS_BLK_NUM;                snprintf(tsk_errstr, TSK_ERRSTR_L,                    "Invalid address in run (too large): %"                    PRIuDADDR "", addr + len_idx);                return 1;            }            // load the buffer if they want more than just the address            if ((a_flags & TSK_FS_FILE_WALK_FLAG_AONLY) == 0) {                /* sparse files just get 0s */                if (fs_attr_run->flags & TSK_FS_ATTR_RUN_FLAG_SPARSE) {                    memset(buf, 0, fs->block_size);                }                /* FILLER entries exist when the source file system can store run                 * info out of order and we did not get all of the run info.  We                 * return 0s if data is read from this type of run. */                else if (fs_attr_run->flags & TSK_FS_ATTR_RUN_FLAG_FILLER) {                    memset(buf, 0, fs->block_size);                    if (tsk_verbose)                        fprintf(stderr,                            "tsk_fs_attr_walk_nonres: File %" PRIuINUM                            " has FILLER entry, using 0s\n",                            fs_attr->fs_file->meta->addr);                }                // we return 0s for reads past the initsize                else if (off > fs_attr->nrd.initsize) {                    memset(buf, 0, fs->block_size);                }                else {                    ssize_t cnt;                    cnt = tsk_fs_read_block                        (fs, addr + len_idx, buf, fs->block_size);                    if (cnt != fs->block_size) {                        if (cnt >= 0) {                            tsk_error_reset();                            tsk_errno = TSK_ERR_FS_READ;                        }                        snprintf(tsk_errstr2, TSK_ERRSTR_L,                            "tsk_fs_file_walk: Error reading block at %"                            PRIuDADDR, addr + len_idx);                        return 1;                    }                }            }            /* Need to account for the skip length, which is the number of bytes             * in the start of the attribute that are skipped and that are not             * included in the overall length.  We will seek past those and not             * return those in the action.  We just read a block size so check             * if there is data to be returned in this buffer. */            if (skip_remain >= fs->block_size) {                skip_remain -= fs->block_size;            }            else {                size_t ret_len;                /* Do we want to return a full block, or just the end? */                if ((TSK_OFF_T) fs->block_size - skip_remain <                    tot_size - off)                    ret_len = fs->block_size - skip_remain;                else                    ret_len = (size_t) (tot_size - off);                /* Only do sparse or FILLER clusters if NOSPARSE is not set */                if ((fs_attr_run->flags & TSK_FS_ATTR_RUN_FLAG_SPARSE) ||                    (fs_attr_run->flags & TSK_FS_ATTR_RUN_FLAG_FILLER) ||                    (off > fs_attr->nrd.initsize)) {                    myflags = TSK_FS_BLOCK_FLAG_SPARSE;                    if ((a_flags & TSK_FS_FILE_WALK_FLAG_NOSPARSE) == 0) {                        retval =                            a_action(fs_attr->fs_file, off, 0,                            &buf[skip_remain], ret_len, myflags, a_ptr);                    }                }                else {                    myflags = fs->block_getflags(fs, addr + len_idx);                    myflags |= TSK_FS_BLOCK_FLAG_RAW;                    retval =                        a_action(fs_attr->fs_file, off, addr + len_idx,                        &buf[skip_remain], ret_len, myflags, a_ptr);                }                off += ret_len;                skip_remain = 0;                if (retval != TSK_WALK_CONT) {                    stop_loop = 1;                    break;                }                if (off >= tot_size) {                    stop_loop = 1;                    break;                }            }        }        if (stop_loop)            break;    }    if (buf)        free(buf);    if (retval == TSK_WALK_ERROR)        return 1;    else        return 0;}/** * \ingroup fslib * Process an attribute and call a callback function with its contents. The callback will be  * called with chunks of data that are fs->block_size or less.  The address given in the callback * will be correct only for raw files (when the raw file contents were stored in the block).  For * compressed and sparse attributes, the address may be zero. * * @param a_fs_attr Attribute to process * @param a_flags Flags to use while processing attribute * @param a_action Callback action to call with content * @param a_ptr Pointer that will passed to callback * @returns 1 on error and 0 on success. */uint8_ttsk_fs_attr_walk(const TSK_FS_ATTR * a_fs_attr,    TSK_FS_FILE_WALK_FLAG_ENUM a_flags, TSK_FS_FILE_WALK_CB a_action,    void *a_ptr){    TSK_FS_INFO *fs;    // clean up any error messages that are lying around    tsk_error_reset();    // check the FS_INFO, FS_FILE structures    if ((a_fs_attr == NULL) || (a_fs_attr->fs_file == NULL)        || (a_fs_attr->fs_file->meta == NULL)        || (a_fs_attr->fs_file->fs_info == NULL)) {        tsk_errno = TSK_ERR_FS_ARG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "tsk_fs_attr_walk: called with NULL pointers");        return 1;    }    fs = a_fs_attr->fs_file->fs_info;    if (fs->tag != TSK_FS_INFO_TAG) {//        || (a_fs_attr->id != TSK_FS_ATTR_ID)) {        tsk_errno = TSK_ERR_FS_ARG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "tsk_fs_attr_walk: called with unallocated structures");        return 1;    }    if (a_fs_attr->flags & TSK_FS_ATTR_COMP) {        if (a_fs_attr->w == NULL) {            tsk_errno = TSK_ERR_FS_ARG;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "tsk_fs_attr_walk: compressed attribute found, but special function not defined");            return 1;        }        return a_fs_attr->w(a_fs_attr, a_flags, a_action, a_ptr);    }    // resident data    if (a_fs_attr->flags & TSK_FS_ATTR_RES) {        return tsk_fs_attr_walk_res(a_fs_attr, a_flags, a_action, a_ptr);    }    // non-resident data    else if (a_fs_attr->flags & TSK_FS_ATTR_NONRES) {        return tsk_fs_attr_walk_nonres(a_fs_attr, a_flags, a_action,            a_ptr);    }    tsk_errno = TSK_ERR_FS_ARG;    snprintf(tsk_errstr, TSK_ERRSTR_L,        "tsk_fs_attr_walk: called with unknown attribute type: %x",        a_fs_attr->flags);    return 1;}/** * \ingroup fslib * Read the contents of a given attribute using a typical read() type interface. * 0s are returned for missing runs.  *  * @param a_fs_attr The attribute to read. * @param a_offset The byte offset to start reading from. * @param a_buf The buffer to read the data into. * @param a_len The number of bytes to read from the file. * @param a_flags Flags to use while reading * @returns The number of bytes read or -1 on error. */ssize_ttsk_fs_attr_read(const TSK_FS_ATTR * a_fs_attr, TSK_OFF_T a_offset,    char *a_buf, size_t a_len, TSK_FS_FILE_READ_FLAG_ENUM a_flags){    TSK_FS_INFO *fs;    if ((a_fs_attr == NULL) || (a_fs_attr->fs_file == NULL)        || (a_fs_attr->fs_file->fs_info == NULL)) {        tsk_errno = TSK_ERR_FS_ARG;        snprintf(tsk_errstr, TSK_ERRSTR_L,            "tsk_fs_attr_read: Attribute has null pointers.");        return -1;    }    fs = a_fs_attr->fs_file->fs_info;    /* for compressed data, call the specialized function */    if (a_fs_attr->flags & TSK_FS_ATTR_COMP) {        if (a_fs_attr->r == NULL) {            tsk_errno = TSK_ERR_FS_ARG;            snprintf(tsk_errstr, TSK_ERRSTR_L,                "tsk_fs_attr_read: Attribute has compressed type set, but no compressed read function defined");            return -1;        }        return a_fs_attr->r(a_fs_attr, a_offset, a_buf, a_len);    }    /* For resident data, copy data from the local buffer */    else if (a_fs_attr->flags & TSK_FS_ATTR_RES) {        size_t read_len;        if (a_offset > a_fs_attr->rd.buf_size) {            return 0;        }        if (a_len + a_offset > a_fs_attr->rd.buf_size)            read_len = a_fs_attr->rd.buf_size - (size_t) a_offset;        else            read_len = a_len;        memcpy(a_buf, &a_fs_attr->rd.buf[a_offset], read_len);        return (ssize_t) read_len;    }    /* For non-resident data, load the needed block and copy the data */    else if (a_fs_attr->flags & TSK_FS_ATTR_NONRES) {        TSK_FS_ATTR_RUN *data_run_cur;        TSK_DADDR_T blkoffset;  // block offset of where we want to start reading from        size_t byteoffset;      // byte offset in blkoffset of where we want to start reading from        size_t size_remain;     // length remaining to copy        size_t size_tocopy;     // length total to copy        if (a_offset > a_fs_attr->nrd.allocsize) {            return 0;        }        // we return 0s for reads past the initsize        if (a_offset >= a_fs_attr->nrd.initsize) {            ssize_t len;            if (tsk_verbose)                fprintf(stderr,                    "tsk_fs_attr_read: Returning 0s for read past end of initsize (%"                    PRIuINUM ")\n", ((a_fs_attr->fs_file)                        && (a_fs_attr->fs_file->meta)) ? a_fs_attr->                    fs_file->meta->addr : 0);            if (a_offset + a_len > a_fs_attr->nrd.allocsize)                len = (ssize_t) (a_fs_attr->nrd.allocsize - a_offset);            else                len = (ssize_t) a_len;            memset(a_buf, 0, a_len);            return len;        }        blkoffset = a_offset / fs->block_size;        byteoffset = (size_t) (a_offset % fs->block_size);        // determine how many bytes we can copy        if (a_flags & TSK_FS_FILE_READ_FLAG_SLACK) {            if (a_offset + a_len > a_fs_attr->nrd.allocsize)                size_tocopy =                    (size_t) (a_fs_attr->nrd.allocsize - a_offset);            else                size_tocopy = a_len;        }        else {            if (a_offset + a_len > a_fs_attr->size)                size_tocopy = (size_t) (a_fs_attr->size - a_offset);            else                size_tocopy = a_len;        }        size_remain = size_tocopy;        // cycle through the run until we find where we can start to process the clusters        for (data_run_cur = a_fs_attr->nrd.run; data_run_cur;            data_run_cur = data_run_cur->next) {            TSK_DADDR_T run_offset;            size_t run_len;            if (size_remain <= 0)                break;            // See if this run contains the starting offset they requested            if (data_run_cur->offset + data_run_cur->len < blkoffset)                continue;            // block offset into this run            run_offset = blkoffset - data_run_cur->offset;            // see if we need to read the rest of this run and into the next or if it is all here            if (fs->block_size * (data_run_cur->len - run_offset) >=                size_remain) {                run_len = size_remain;            }            else {                run_len =                    (size_t) (fs->block_size * (data_run_cur->len -                        run_offset));            }            /* sparse files just get 0s */            if (data_run_cur->flags & TSK_FS_ATTR_RUN_FLAG_SPARSE) {                memset(&a_buf[size_tocopy - size_remain], 0, run_len);            }            /* FILLER entries exist when the source file system can store run             * info out of order and we did not get all of the run info.  We             * return 0s if data is read from this type of run. */            else if (data_run_cur->flags & TSK_FS_ATTR_RUN_FLAG_FILLER) {                memset(&a_buf[size_tocopy - size_remain], 0, run_len);                if (tsk_verbose)                    fprintf(stderr,                        "tsk_fs_attr_read_type: File %" PRIuINUM                        " has FILLER entry, using 0s\n",                        (a_fs_attr->fs_file->meta) ? a_fs_attr->fs_file->                        meta->addr : 0);            }            else {                TSK_OFF_T fs_offset_b;                ssize_t cnt;                // calcuate the byte offset in the file system                fs_offset_b =                    (data_run_cur->addr + run_offset) * fs->block_size;                // add the byte offset in the block                fs_offset_b += byteoffset;                // reset this in case we need to also read from the next run                 byteoffset = 0;                cnt =                    tsk_fs_read(fs, fs_offset_b,                    &a_buf[size_tocopy - size_remain], run_len);                if (cnt != run_len) {                    if (cnt >= 0) {                        tsk_error_reset();                        tsk_errno = TSK_ERR_FS_READ;                    }                    snprintf(tsk_errstr2, TSK_ERRSTR_L,                        "tsk_fs_attr_read_type: offset: %" PRIuOFF                        "  Len: %" PRIuSIZE "", fs_offset_b, run_len);                    return cnt;                }            }            size_remain -= run_len;        }        return (ssize_t) (size_tocopy - size_remain);    }    tsk_errno = TSK_ERR_FS_ARG;    snprintf(tsk_errstr, TSK_ERRSTR_L,        "tsk_fs_attr_read: Unknown attribute type: %x", a_fs_attr->flags);    return -1;}

⌨️ 快捷键说明

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