📄 fs_attr.c
字号:
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 + -