/** * \ingroup fslib * Read a file system block into a char* buffer. * This is actually a wrapper around the fs_read_random function, * but it allows the starting location to be specified as a block address. * * @param a_fs The file system structure. * @param a_addr The starting block file system address. * @param a_buf The char * buffer to store the block data in. * @param a_len The number of bytes to read (must be a multiple of the block size) * @return The number of bytes read or -1 on error. */ ssize_t tsk_fs_read_block(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr, char *a_buf, size_t a_len) { if (a_len % a_fs->block_size) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_READ; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_read_block: length %" PRIuSIZE "" " not a multiple of %d", a_len, a_fs->block_size); return -1; } if (a_addr > a_fs->last_block_act) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_READ; if (a_addr <= a_fs->last_block) snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_read_block: Address missing in partial image: %" PRIuDADDR ")", a_addr); else snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_read_block: Address is too large for image: %" PRIuDADDR ")", a_addr); return -1; } return tsk_img_read(a_fs->img_info, a_fs->offset + (TSK_OFF_T) a_addr * a_fs->block_size, a_buf, a_len); }
/** * \ingroup fslib * Read arbitrary data from inside of the file system. * @param a_fs The file system handle. * @param a_off The byte offset to start reading from (relative to start of file system) * @param a_buf The buffer to store the block in. * @param a_len The number of bytes to read * @return The number of bytes read or -1 on error. */ ssize_t tsk_fs_read(TSK_FS_INFO * a_fs, TSK_OFF_T a_off, char *a_buf, size_t a_len) { // do a sanity check on the read bounds, but only if the block // value has been set. // note that this could prevent us from viewing the FS slack... if ((a_fs->last_block_act > 0) && ((TSK_DADDR_T) a_off >= ((a_fs->last_block_act + 1) * a_fs->block_size))) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); if ((TSK_DADDR_T) a_off < ((a_fs->last_block + 1) * a_fs->block_size)) tsk_error_set_errstr ("tsk_fs_read: Offset missing in partial image: %" PRIuDADDR ")", a_off); else tsk_error_set_errstr ("tsk_fs_read: Offset is too large for image: %" PRIuDADDR ")", a_off); return -1; } if (((a_fs->block_pre_size) || (a_fs->block_post_size)) && (a_fs->block_size)) { return fs_prepost_read(a_fs, a_off, a_buf, a_len); } else { return tsk_img_read(a_fs->img_info, a_off + a_fs->offset, a_buf, a_len); } }
/** * \ingroup fslib * Read arbitrary data from inside of the file system. * @param a_fs The file system handle. * @param a_off The byte offset to start reading from (relative to start of file system) * @param a_buf The buffer to store the block in. * @param a_len The number of bytes to read * @return The number of bytes read or -1 on error. */ ssize_t tsk_fs_read(TSK_FS_INFO * a_fs, TSK_OFF_T a_off, char *a_buf, size_t a_len) { TSK_OFF_T off; // do a sanity check on the read bounds, but only if the block // value has been set. // note that this could prevent us from viewing the FS slack... if ((a_fs->last_block_act > 0) && ((TSK_DADDR_T) a_off >= ((a_fs->last_block_act + 1) * a_fs->block_size))) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_READ; if ((TSK_DADDR_T) a_off < ((a_fs->last_block + 1) * a_fs->block_size)) snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_read: Offset missing in partial image: %" PRIuDADDR ")", a_off); else snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_read: Offset is too large for image: %" PRIuDADDR ")", a_off); return -1; } off = a_off + a_fs->offset; return tsk_img_read(a_fs->img_info, off, a_buf, a_len); }
/** * \ingroup fslib * Get the contents and flags of a specific file system block. Note that if the block contains * compressed data, then this function will return the compressed data with the RAW flag set. * The uncompressed data can be obtained only from the file-level functions. * * @param a_fs The file system to read the block from. * @param a_fs_block The structure to write the block data into or NULL to have one created. * @param a_addr The file system address to read. * @param a_flags Flag to assign to the returned TSK_FS_BLOCK (use if you already have it as part of a block_walk-type scenario) * @return The TSK_FS_BLOCK with the data or NULL on error. (If a_fs_block was not NULL, this will * be the same structure). */ TSK_FS_BLOCK * tsk_fs_block_get_flag(TSK_FS_INFO * a_fs, TSK_FS_BLOCK * a_fs_block, TSK_DADDR_T a_addr, TSK_FS_BLOCK_FLAG_ENUM a_flags) { TSK_OFF_T offs; size_t len; if (a_fs == NULL) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); tsk_error_set_errstr("tsk_fs_block_get: fs unallocated"); return NULL; } if (a_fs_block == NULL) { a_fs_block = tsk_fs_block_alloc(a_fs); } else if ((a_fs_block->tag != TSK_FS_BLOCK_TAG) || (a_fs_block->buf == NULL)) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); tsk_error_set_errstr("tsk_fs_block_get: fs_block unallocated"); return NULL; } len = a_fs->block_size; if (a_addr > a_fs->last_block_act) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); if (a_addr <= a_fs->last_block) tsk_error_set_errstr ("tsk_fs_block_get: Address missing in partial image: %" PRIuDADDR ")", a_addr); else tsk_error_set_errstr ("tsk_fs_block_get: Address is too large for image: %" PRIuDADDR ")", a_addr); return NULL; } a_fs_block->fs_info = a_fs; a_fs_block->addr = a_addr; a_fs_block->flags = a_flags; a_fs_block->flags |= TSK_FS_BLOCK_FLAG_RAW; offs = (TSK_OFF_T) a_addr *a_fs->block_size; if ((a_fs_block->flags & TSK_FS_BLOCK_FLAG_AONLY) == 0) { ssize_t cnt; cnt = tsk_img_read(a_fs->img_info, a_fs->offset + offs, a_fs_block->buf, len); if (cnt != (ssize_t)len) { return NULL; } } return a_fs_block; }
size_t StreamPartition::streamRead(char *buf, size_t count) { off_t realoffset=mPartitionOffset+mReadOffset; //Make sure not to read past the end of the partition. size_t realcount=count; off_t dataleft = mSize - mReadOffset; if ((((off_t) count) > dataleft) ) { realcount= (size_t) dataleft; } if (realcount == 0) { return 0; } size_t rdbytes= tsk_img_read(mImage, realoffset,buf,realcount); if (rdbytes == (size_t) -1) { getLogStream(ocfa::misc::LOG_ERR) << "tsk_img_read returned -1 while requesting for " << realcount << " bytes of data at offset " << realoffset << std::endl; return 0; } mReadOffset+= rdbytes; return rdbytes; }
/* * @param byte_start Byte offset to start reading from start of file * @param byte_len Number of bytes to read * @param buffer Buffer to read into (must be of size byte_len or larger) * @returns -1 on error or number of bytes read */ int TskImageFileTsk::getByteData(const uint64_t byte_start, const uint64_t byte_len, char *buffer) { if (m_img_info == NULL) { if (open() != 0) return -1; } int retval = tsk_img_read(m_img_info, byte_start, buffer, (size_t)(byte_len)); if (retval == -1) { std::wstringstream message; message << L"TskImageFileTsk::getByteData - tsk_img_read: " << tsk_error_get() << std::endl; LOGERROR(message.str()); return -1; } return retval; }
ssize_t Image::dump(std::ostream& o) const { ssize_t rlen; char buf[4096]; TSK_OFF_T off = 0; while (off < Img->size) { rlen = tsk_img_read(Img, off, buf, sizeof(buf)); if (rlen == -1) { return -1; } off += rlen; o.write(buf, rlen); if (!o.good()) { return -1; } } return Img->size; }
/* * Inspects a byte address for an XTAF superblock structure. * * @param offset Offset in sectors. * * Returns 0 on finding a sane-looking XTAF superblock. * Returns 1 on finding non-XTAF-superblock data. * Returns <0 on more basic errors (memory, I/O). */ int tsk_vs_xtaf_verifysb(TSK_IMG_INFO * img_info, TSK_DADDR_T offset, unsigned int sector_size){ ssize_t cnt; xtaffs_sb* xtafsb; unsigned int xtafsb_len; xtafsb_len = sizeof(xtaffs_sb); /* Allocate superblock struct. */ xtafsb = (xtaffs_sb*) tsk_malloc(xtafsb_len); if (NULL == xtafsb) { tsk_fprintf(stderr, "tsk_vs_xtaf_verifysb: Failed to allocate superblock for partition %d.\n"); free(xtafsb); return -ENOMEM; } /* Read in superblock. */ /* NOTE: This is read as a char* instead of a xtaffs_sb to keep img_read() happy. */ cnt = tsk_img_read(img_info, offset, (char *) xtafsb, xtafsb_len); /* Check for a failed read. */ if (cnt != xtafsb_len) { tsk_fprintf(stderr, "tsk_vs_xtaf_verifysb: Failed to read at disk offset %" PRIuDADDR " bytes.\n", offset * sector_size); free(xtafsb); return -EIO; } /* Sanity test: Check the magic. */ if(strncmp((char*) xtafsb->magic, "XTAF", 4)){ if (tsk_verbose) tsk_fprintf(stderr, "tsk_vs_xtaf_verifysb: Partition at %" PRIuDADDR " bytes is not an XTAF file system.\n", offset * sector_size); free(xtafsb); return 1; } /* The partition at this point is sane. No further need to check the superblock. */ free(xtafsb); return 0; }
/** \internal * Internal method to deal with calculating correct offset when we have pre and post bytes * in teh file system blocks (i.e. RAW Cds) * @param a_fs File system being analyzed * @param a_off Byte offset into file system (i.e. not offset into image) * @param a_buf Buffer to write data into * @param a_len Number of bytes to read * @retuns Number of bytes read or -1 on error */ static ssize_t fs_prepost_read(TSK_FS_INFO * a_fs, TSK_OFF_T a_off, char *a_buf, size_t a_len) { TSK_OFF_T cur_off = a_off; TSK_OFF_T end_off = a_off + a_len; ssize_t cur_idx = 0; // we need to read block by block so that we can skip the needed pre and post bytes while (cur_off < end_off) { TSK_OFF_T read_off; ssize_t retval2 = 0; TSK_DADDR_T blk = cur_off / a_fs->block_size; size_t read_len = a_fs->block_size - cur_off % a_fs->block_size; if (read_len + cur_off > end_off) read_len = end_off - cur_off; read_off = a_fs->offset + cur_off + blk * (a_fs->block_pre_size + a_fs->block_post_size) + a_fs->block_pre_size; if (tsk_verbose) fprintf(stderr, "fs_prepost_read: Mapped %" PRIuOFF " to %" PRIuOFF "\n", cur_off, read_off); retval2 = tsk_img_read(a_fs->img_info, read_off, &a_buf[cur_idx], read_len); if (retval2 == -1) return -1; else if (retval2 == 0) break; cur_idx += retval2; cur_off += retval2; } return cur_idx; }
/* * Read bytes from the given image * @return array of bytes read from the image * @param env pointer to java environment this was called from * @param obj the java object this was called from * @param a_img_info the pointer to the image object * @param offset the offset in bytes to start at * @param len number of bytes to read */ JNIEXPORT jbyteArray JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_readImgNat(JNIEnv * env, jclass obj, jlong a_img_info, jlong offset, jlong len) { char *buf = (char *) tsk_malloc((size_t) len); if (buf == NULL) { throwTskError(env, tsk_error_get()); return NULL; } TSK_IMG_INFO *img_info = castImgInfo(env, a_img_info); ssize_t retval = tsk_img_read(img_info, (TSK_OFF_T) offset, buf, (size_t) len); if (retval == -1) { throwTskError(env, tsk_error_get()); } // package it up for return jbyteArray return_array = copyBufToByteArray(env, buf, retval); free(buf); return return_array; }
/** * \ingroup fslib * Read a file system block into a char* buffer. * This is actually a wrapper around the fs_read_random function, * but it allows the starting location to be specified as a block address. * * @param a_fs The file system structure. * @param a_addr The starting block file system address. * @param a_buf The char * buffer to store the block data in. * @param a_len The number of bytes to read (must be a multiple of the block size) * @return The number of bytes read or -1 on error. */ ssize_t tsk_fs_read_block(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr, char *a_buf, size_t a_len) { if (a_len % a_fs->block_size) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); tsk_error_set_errstr("tsk_fs_read_block: length %" PRIuSIZE "" " not a multiple of %d", a_len, a_fs->block_size); return -1; } if (a_addr > a_fs->last_block_act) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); if (a_addr <= a_fs->last_block) tsk_error_set_errstr ("tsk_fs_read_block: Address missing in partial image: %" PRIuDADDR ")", a_addr); else tsk_error_set_errstr ("tsk_fs_read_block: Address is too large for image: %" PRIuDADDR ")", a_addr); return -1; } if ((a_fs->block_pre_size == 0) && (a_fs->block_post_size == 0)) { TSK_OFF_T off = a_fs->offset + (TSK_OFF_T) (a_addr) * a_fs->block_size; return tsk_img_read(a_fs->img_info, off, a_buf, a_len); } else { TSK_OFF_T off = (TSK_OFF_T) (a_addr) * a_fs->block_size; return fs_prepost_read(a_fs, off, a_buf, a_len); } }
/* * Given the path to the file, open it and load the internal * partition table structure * * offset is the byte offset to the start of the volume system * * If test is 1 then additional tests are performed to make sure * it isn't a FAT or NTFS file system. This is used when autodetection * is being used to detect the volume system type. */ TSK_VS_INFO * tsk_vs_xtaf_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset, uint8_t test) { TSK_VS_INFO *vs; ssize_t cnt = 0; char* xtaf_buffer[4]; unsigned int sector_size; /* Offsets and lengths are hard-coded, except for the user data partition length. */ /* Offsets are in bytes */ // TSK_DADDR_T known_xtaf_offsets[] = {0x80000, 0x80080000, 0x10C080000, 0x118EB0000, 0x120eb0000, 0x130eb0000}; TSK_DADDR_T known_xtaf_offsets[] = {1024, 4195328, 8782848, 9205120, 9467264, 9991552}; /* Lengths are in sectors */ TSK_DADDR_T known_xtaf_lengths[] = {4194304, 4587520, 422272 , 262144 , 524288 , 0}; /* Partition labels c/o the Free60 Wiki: http://free60.org/FATX */ char* known_xtaf_labels[] = { "XTAF (System Cache)", "XTAF (Game Cache)", "XTAF (System Extended)", "XTAF (System Extended 2)", "XTAF (Compatibility)", "XTAF (System)" }; //AJN: Recall that the label passed to tsk_vs_part_add must be malloc'ed. TSK_VS_PART_INFO* part; TSK_DADDR_T partition_offset; TSK_DADDR_T partition_length; int itor; char *part_label; int rc_verifysb; int partition_tally = 0; /* Clean up any errors that are lying around. */ tsk_error_reset(); /* Zero out buffer before reading */ memset(xtaf_buffer, 0, sizeof(xtaf_buffer)); sector_size = img_info->sector_size; if (0 == sector_size) { tsk_fprintf(stderr, "tsk_vs_xtaf_open: img_info has the sector size of this image as 0 bytes. Guessing 512 instead, but this should be fixed.\n"); sector_size = 512; } vs = (TSK_VS_INFO *) tsk_malloc(sizeof(*vs)); if (vs == NULL) return NULL; vs->vstype = TSK_VS_TYPE_XTAF; vs->tag = TSK_VS_INFO_TAG; vs->img_info = img_info; vs->offset = offset; /* inititialize settings */ vs->part_list = NULL; vs->endian = 0x02; /*AJN TODO Setting this to TSK_BIG_ENDIAN, which is the same value, causes XTAF recognition to immediately fail...why?*/ vs->block_size = 512; /* Assign functions */ vs->close = xtaf_close; vs->part_count = 0; /* Inspect beginning of image for XTAF superblock. If one is present there, assume we're looking at a partition image, and quit early. */ rc_verifysb = tsk_vs_xtaf_verifysb(img_info, 0, sector_size); if (rc_verifysb == 0) { if (tsk_verbose) tsk_fprintf(stderr, "tsk_vs_xtaf_open: Encountered XTAF superblock at beginning of image. Assuming this is a partition image, not a disk image.\n"); xtaf_close(vs); return NULL; } /* check to see if image is a single partition, in which case XTAF would start at the beginning */ memset(xtaf_buffer, 0, sizeof(xtaf_buffer)); cnt = tsk_img_read(img_info, 0x0, (char *) xtaf_buffer, 4); if(strncmp(xtaf_buffer, "XTAF", 4) == 0){ partition_offset = 0; partition_length = img_info->size; rc_verifysb = tsk_vs_xtaf_verifysb(img_info, partition_offset, sector_size); /* Check for XTAF superblock. */ if (rc_verifysb != 0) { if (tsk_verbose) tsk_fprintf(stderr, "Superblock incorrect\n"); xtaf_close(vs); return NULL; } /* Allocate partition label. */ part_label = (char *) tsk_malloc(XTAF_PART_LABEL_MAX_LENGTH * sizeof(char)); for (itor = 0; itor < 6; itor++){ if( (img_info->size/img_info->sector_size) == known_xtaf_lengths[itor]){ /* Allocate partition label. */ part_label = (char *) tsk_malloc(XTAF_PART_LABEL_MAX_LENGTH * sizeof(char)); snprintf(part_label, XTAF_PART_LABEL_MAX_LENGTH, known_xtaf_labels[itor]); break; } } vs->part_count = 1; /* Populate partition struct and append to partition list. */ part = tsk_vs_part_add(vs, partition_offset, partition_length, TSK_VS_PART_FLAG_ALLOC, part_label, 0, 0); if (NULL == part) { tsk_fprintf(stderr, "tsk_vs_xtaf_open: Failed to add partition %d to partition list.\n", itor); xtaf_close(vs); return NULL; } partition_tally = 1; }else{ vs->part_count = 6; /* Loop through the known partition offsets, looking for XTAF file systems only by a sane XTAF superblock being present. */ for (itor = 0; itor < 6; itor++) { /* Reset. */ part = NULL; part_label = NULL; partition_offset = known_xtaf_offsets[itor]*512; /* Check to see if XTAF is at the location it should be */ memset(xtaf_buffer, 0, sizeof(xtaf_buffer)); cnt = tsk_img_read(img_info, partition_offset, (char *) xtaf_buffer, 4); if(strncmp(xtaf_buffer, "XTAF", 4) != 0){ continue; } partition_length = known_xtaf_lengths[itor]; /* Last partition will have variable size depending on the size of drive, this partition will run to the end of the drive */ if( partition_offset == 0x130eb0000){ partition_length = img_info->size - 0x130eb0000; } if (0 == partition_length) { if (tsk_verbose) { tsk_fprintf(stderr, "tsk_vs_xtaf_open: Computing partition length.\n"); tsk_fprintf(stderr, "tsk_vs_xtaf_open: Image size: %" PRIuOFF " bytes.\n", img_info->size); tsk_fprintf(stderr, "tsk_vs_xtaf_open: Sector size: %u bytes.\n", img_info->sector_size); tsk_fprintf(stderr, "tsk_vs_xtaf_open: Partition offset: %" PRIuDADDR " bytes.\n", partition_offset * img_info->sector_size); } /* Compute partition length of the user data partition differently - based on input image's length. */ if ((img_info->size / sector_size) < partition_offset) { if (tsk_verbose) tsk_fprintf(stderr, "tsk_vs_xtaf_open: This image is smaller than the offset of the target partition. Aborting.\n"); xtaf_close(vs); return NULL; } partition_length = (img_info->size / sector_size) - partition_offset; } if (tsk_verbose) { tsk_fprintf(stderr, "tsk_vs_xtaf_open: Testing for partition.\n"); tsk_fprintf(stderr, "tsk_vs_xtaf_open: itor: %d.\n", itor); tsk_fprintf(stderr, "tsk_vs_xtaf_open: offset: %" PRIuDADDR " sectors.\n", partition_offset); tsk_fprintf(stderr, "tsk_vs_xtaf_open: length: %" PRIuDADDR " sectors.\n", partition_length); } /* Check for XTAF superblock. */ rc_verifysb = tsk_vs_xtaf_verifysb(img_info, partition_offset, sector_size); if (rc_verifysb != 0) { continue; } /* Allocate partition label. */ part_label = (char *) tsk_malloc(XTAF_PART_LABEL_MAX_LENGTH * sizeof(char)); snprintf(part_label, XTAF_PART_LABEL_MAX_LENGTH, known_xtaf_labels[itor]); /* Populate partition struct and append to partition list. */ part = tsk_vs_part_add(vs, (partition_offset/(512)), partition_length, TSK_VS_PART_FLAG_ALLOC, part_label, 0, 0); // part->start = (TSK_DADDR_T) partition_offset; if (NULL == part) { tsk_fprintf(stderr, "tsk_vs_xtaf_open: Failed to add partition %d to partition list.\n", itor); break; } partition_tally++; } } /* Don't call this an XTAF volume system if none of the hard-coded partitions were found. */ if (partition_tally == 0) { xtaf_close(vs); return NULL; } /* Denote unallocated space as "Unused" disk area. */ if (tsk_vs_part_unused(vs)) { xtaf_close(vs); return NULL; } return vs; }
int main(int argc, char* argv1[]) { TSK_VS_INFO* lVsInfo = NULL; TSK_OFF_T lCnt = 0; char lBuf[32768] = { 0 }; unsigned lCntRead = 0; TSK_IMG_INFO* lImgInfo = OS_FH_INVALID; OS_FH_TYPE lOut = OS_FH_INVALID; const TSK_TCHAR *const *argv; #ifdef TSK_WIN32 argv = CommandLineToArgvW(GetCommandLineW(), &argc); #else argv = (const TSK_TCHAR *const *) argv1; #endif lOut = OS_FOPEN_WRITE(argv[2]); if (lOut == OS_FH_INVALID) { LOGGING_ERROR("Could not open export image in write mode. \n") exit(1); } lImgInfo = tsk_img_open( 1, /* number of images */ (argv + 1), /* path to images */ TSK_IMG_TYPE_DETECT, /* disk image type */ 0); /* size of device sector in bytes */ if (lImgInfo != NULL) { TSK_OFF_T lSizeSectors = lImgInfo->size / lImgInfo->sector_size + \ (lImgInfo->size % lImgInfo->sector_size ? 1 : 0); LOGGING_INFO("Image size (Bytes): %lu, Image size (sectors): %lu\n", lImgInfo->size, lSizeSectors); lVsInfo = tsk_vs_open(lImgInfo, 0, TSK_VS_TYPE_DETECT); if (lVsInfo != NULL) { if (tsk_vs_part_walk(lVsInfo, 0, /* start */ lVsInfo->part_count - 1, /* end */ TSK_VS_PART_FLAG_ALL, /* all partitions */ part_act, /* callback */ (void*) lOut /* data passed to the callback */ ) != 0) { fprintf(stderr, "Problem when walking partitions. \n"); } } else { LOGGING_DEBUG("Volume system cannot be opened.\n"); for (lCnt = 0; lCnt < lSizeSectors; lCnt++) { lCntRead = lCnt == lSizeSectors - 1 ? lImgInfo->size % lImgInfo->sector_size : lImgInfo->sector_size; LOGGING_DEBUG("Reading %u bytes\n", lCntRead); tsk_img_read( lImgInfo, /* handler */ lCnt * lImgInfo->sector_size, /* start address */ lBuf, /* buffer to store data in */ lCntRead /* amount of data to read */ ); data_act(lBuf, lCntRead, lCnt * lImgInfo->sector_size, lOut); } } } else { LOGGING_ERROR("Problem opening the image. \n"); tsk_error_print(stderr); exit(1); } if (lOut != OS_FH_INVALID) { OS_FCLOSE(lOut); } return EXIT_SUCCESS; }
int main(int argc, char **argv1) { TSK_IMG_INFO *img; TSK_IMG_TYPE_ENUM imgtype = TSK_IMG_TYPE_DETECT; int ch; TSK_OFF_T start_sector = 0; TSK_OFF_T end_sector = 0; ssize_t cnt; TSK_TCHAR **argv; unsigned int ssize = 0; TSK_TCHAR *cp; #ifdef TSK_WIN32 // On Windows, get the wide arguments (mingw doesn't support wmain) argv = CommandLineToArgvW(GetCommandLineW(), &argc); if (argv == NULL) { fprintf(stderr, "Error getting wide arguments\n"); exit(1); } #else argv = (TSK_TCHAR **) argv1; #endif progname = argv[0]; while ((ch = GETOPT(argc, argv, _TSK_T("b:i:vVs:e:"))) > 0) { switch (ch) { case _TSK_T('?'): default: TFPRINTF(stderr, _TSK_T("Invalid argument: %s\n"), argv[OPTIND]); usage(); case _TSK_T('b'): ssize = (unsigned int) TSTRTOUL(OPTARG, &cp, 0); if (*cp || *cp == *OPTARG || ssize < 1) { TFPRINTF(stderr, _TSK_T ("invalid argument: sector size must be positive: %s\n"), OPTARG); usage(); } break; case _TSK_T('i'): if (TSTRCMP(OPTARG, _TSK_T("list")) == 0) { tsk_img_type_print(stderr); exit(1); } imgtype = tsk_img_type_toid(OPTARG); if (imgtype == TSK_IMG_TYPE_UNSUPP) { TFPRINTF(stderr, _TSK_T("Unsupported image type: %s\n"), OPTARG); usage(); } break; case _TSK_T('s'): start_sector = TSTRTOUL(OPTARG, &cp, 0); if (*cp || *cp == *OPTARG || start_sector < 1) { TFPRINTF(stderr, _TSK_T ("invalid argument: start sector must be positive: %s\n"), OPTARG); usage(); } break; case _TSK_T('e'): end_sector = TSTRTOUL(OPTARG, &cp, 0); if (*cp || *cp == *OPTARG || end_sector < 1) { TFPRINTF(stderr, _TSK_T ("invalid argument: end sector must be positive: %s\n"), OPTARG); usage(); } break; case _TSK_T('v'): tsk_verbose++; break; case _TSK_T('V'): tsk_version_print(stdout); exit(0); } } /* We need at least one more argument */ if (OPTIND >= argc) { tsk_fprintf(stderr, "Missing image name\n"); usage(); } if ((img = tsk_img_open(argc - OPTIND, &argv[OPTIND], imgtype, ssize)) == NULL) { tsk_error_print(stderr); exit(1); } #ifdef TSK_WIN32 if (-1 == _setmode(_fileno(stdout), _O_BINARY)) { fprintf(stderr, "error setting stdout to binary: %s", strerror(errno)); exit(1); } #endif TSK_OFF_T start_byte = 0; if (start_sector) start_byte = start_sector * img->sector_size; TSK_OFF_T end_byte = 0; if (end_sector) end_byte = (end_sector + 1) * img->sector_size; else end_byte = img->size; for (TSK_OFF_T done = start_byte; done < end_byte; done += cnt) { char buf[16 * 1024]; size_t len; if (done + (TSK_OFF_T) sizeof(buf) > end_byte) { len = (size_t) (end_byte - done); } else { len = sizeof(buf); } cnt = tsk_img_read(img, done, buf, len); if (cnt != (ssize_t) len) { if (cnt >= 0) { tsk_fprintf(stderr, "img_cat: Error reading image file at offset: %" PRIuOFF ", len: %" PRIuOFF ", return: %" PRIuOFF "\n", done, len, cnt); } else { tsk_error_print(stderr); } tsk_img_close(img); exit(1); } if (fwrite(buf, cnt, 1, stdout) != 1) { fprintf(stderr, "img_cat: Error writing to stdout: %s", strerror(errno)); tsk_img_close(img); exit(1); } } tsk_img_close(img); exit(0); }
static TSK_WALK_RET_ENUM fw_action1(TSK_FS_FILE * a_fs_file, TSK_OFF_T a_off, TSK_DADDR_T a_addr, char *a_buf, size_t a_size, TSK_FS_BLOCK_FLAG_ENUM a_flags, void *a_ptr) { TSK_OFF_T tmp_off; ssize_t cnt; size_t tmp_len; TSK_FS_INFO *fs = a_fs_file->fs_info; // verify teh offset passed is what we expected if (a_off != s_off) { fprintf(stderr, "offset passed in callback (%" PRIuOFF ") diff from internal off (%" PRIuOFF ")\n", a_off, s_off); } /* The first set of tests is for the file_read API. We seek * to a "random" place to move around any caches, adn then read * from the same offset that this call is from. We compare * the buffers. */ // pick a random place and length tmp_off = (s_off * 4 + 1372) % s_file2->meta->size; if (s_file2->meta->size - tmp_off > fs->block_size) tmp_len = fs->block_size; else tmp_len = s_file2->meta->size - tmp_off; cnt = tsk_fs_file_read(s_file2, tmp_off, s_buf, tmp_len, (TSK_FS_FILE_READ_FLAG_ENUM) 0); if (cnt != (ssize_t) tmp_len) { fprintf(stderr, "Error reading random offset %" PRIuOFF " in file sized %" PRIuOFF " (%zd vs %zd)\n", tmp_off, s_file2->meta->size, cnt, tmp_len); tsk_error_print(stderr); return TSK_WALK_ERROR; } // now read from the real offset and compare with what we were passed if (a_size > fs->block_size) tmp_len = fs->block_size; else tmp_len = a_size; cnt = tsk_fs_file_read(s_file2, s_off, s_buf, tmp_len, (TSK_FS_FILE_READ_FLAG_ENUM) 0); if (cnt != (ssize_t) tmp_len) { fprintf(stderr, "Error reading file offset %" PRIuOFF " in file sized %" PRIuOFF "\n", s_off, s_file2->meta->size); tsk_error_print(stderr); return TSK_WALK_ERROR; } if (memcmp(s_buf, a_buf, a_size)) { fprintf(stderr, "Buffers at offset %" PRIuOFF " in file %" PRIuINUM " are different\n", s_off, s_file2->meta->addr); return TSK_WALK_ERROR; } s_off += a_size; /* IF the block we were passed is RAW (not BAD, resident, compressed etc., * then read using the fs_read() API */ if (a_flags & TSK_FS_BLOCK_FLAG_RAW) { tmp_off = (a_addr * 42 + 82) % fs->last_block; cnt = tsk_fs_read_block(fs, tmp_off, s_buf, fs->block_size); if (cnt != (ssize_t) fs->block_size) { fprintf(stderr, "Error reading random block %" PRIuOFF " in file system\n", tmp_off); tsk_error_print(stderr); return TSK_WALK_ERROR; } cnt = tsk_fs_read_block(fs, a_addr, s_buf, fs->block_size); if (cnt != (ssize_t) fs->block_size) { fprintf(stderr, "Error reading block %" PRIuOFF "\n", a_addr); tsk_error_print(stderr); return TSK_WALK_ERROR; } // compare if (memcmp(s_buf, a_buf, a_size)) { fprintf(stderr, "Buffers at block addr %" PRIuOFF " in file %" PRIuINUM " are different\n", a_addr, s_file2->meta->addr); return TSK_WALK_ERROR; } /* Now we also read using the img_read() API, just because we can */ cnt = tsk_fs_read_block(fs, tmp_off, s_buf, fs->block_size); if (cnt != (ssize_t) fs->block_size) { fprintf(stderr, "Error reading random block %" PRIuOFF " in file system\n", tmp_off); tsk_error_print(stderr); return TSK_WALK_ERROR; } // get the offset into the image tmp_off = a_addr * fs->block_size + fs->offset; cnt = tsk_img_read(fs->img_info, tmp_off, s_buf, fs->block_size); if (cnt != (ssize_t) fs->block_size) { fprintf(stderr, "Error reading image offset %" PRIuOFF " in image\n", tmp_off); tsk_error_print(stderr); return TSK_WALK_ERROR; } // compare if (memcmp(s_buf, a_buf, a_size)) { fprintf(stderr, "Buffers at image offset %" PRIuOFF " in file %" PRIuINUM " are different\n", tmp_off, s_file2->meta->addr); return TSK_WALK_ERROR; } } return TSK_WALK_CONT; }