TSK_WALK_RET_ENUM part_act( TSK_VS_INFO* pVsInfo, const TSK_VS_PART_INFO* pPartInfo, void* pData) { TSK_FS_INFO* lFsInfo = NULL; OS_FH_TYPE lOut = (OS_FH_TYPE)pData; unsigned long long lCnt = 0; char lBuf[32768] = { 0 }; unsigned long long lOffsetBlock = 0; /* open file system */ if ((lFsInfo = tsk_fs_open_vol( pPartInfo, /* partition to open */ TSK_FS_TYPE_DETECT /* auto-detect mode on */ )) != NULL) { /* known file-system */ /* iterate over unallocated blocks of fs */ tsk_fs_block_walk( lFsInfo, /* file-system info */ 0, /* start */ lFsInfo->block_count - 1, /* end */ TSK_FS_BLOCK_WALK_FLAG_UNALLOC, /* only unallocated blocks */ block_act, /* callback */ pData /* file-handle */ ); /* close fs */ tsk_fs_close(lFsInfo); } else { /* unknown file-system */ /* iterate through all blocks of this volume regardless of their state */ for (lCnt = 0; lCnt < pPartInfo->len; lCnt++) { lOffsetBlock = (pPartInfo->start + lCnt) * pPartInfo->vs->block_size; LOGGING_DEBUG( "Block in unknown partition (Len: %lu blocks). " "Size: %u, Absolute address (Bytes): %lld\n", pPartInfo->len, pPartInfo->vs->block_size, lOffsetBlock); /* use the following function so that forensic images are supported */ /* HINT: this is not the case with fopen/fseek/fread/fclose functions */ tsk_vs_part_read_block( pPartInfo, lCnt, /* start address (blocks) relative to start of volume */ lBuf, /* buffer to store data in */ pPartInfo->vs->block_size /* amount of data to read */ ); data_act(lBuf, pPartInfo->vs->block_size, lOffsetBlock, lOut); } } return TSK_WALK_CONT; }
int main(int argc, char **argv1) { TSK_VS_INFO *vs; TSK_IMG_TYPE_ENUM imgtype = TSK_IMG_TYPE_DETECT; TSK_VS_TYPE_ENUM vstype = TSK_VS_TYPE_DETECT; int ch; TSK_OFF_T imgaddr = 0; TSK_IMG_INFO *img; TSK_PNUM_T pnum; TSK_DADDR_T addr; const TSK_VS_PART_INFO *vs_part; char *buf; 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:o:t:vV"))) > 0) { switch (ch) { 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('o'): if ((imgaddr = tsk_parse_offset(OPTARG)) == -1) { tsk_error_print(stderr); exit(1); } break; case _TSK_T('t'): if (TSTRCMP(OPTARG, _TSK_T("list")) == 0) { tsk_vs_type_print(stderr); exit(1); } vstype = tsk_vs_type_toid(OPTARG); if (vstype == TSK_VS_TYPE_UNSUPP) { TFPRINTF(stderr, _TSK_T("Unsupported volume system type: %s\n"), OPTARG); usage(); } break; case 'v': tsk_verbose++; break; case 'V': tsk_version_print(stdout); exit(0); case '?': default: tsk_fprintf(stderr, "Unknown argument\n"); usage(); } } /* We need at least two more arguments */ if (OPTIND + 1 >= argc) { tsk_fprintf(stderr, "Missing image name and/or partition number\n"); usage(); } /* open the image */ if ((img = tsk_img_open(argc - OPTIND - 1, &argv[OPTIND], imgtype, ssize)) == NULL) { tsk_error_print(stderr); exit(1); } if ((imgaddr * img->sector_size) >= img->size) { tsk_fprintf(stderr, "Sector offset supplied is larger than disk image (maximum: %" PRIu64 ")\n", img->size / img->sector_size); exit(1); } if (tsk_parse_pnum(argv[argc - 1], &pnum)) { tsk_error_print(stderr); exit(1); } /* process the partition tables */ if ((vs = tsk_vs_open(img, imgaddr * img->sector_size, vstype)) == NULL) { tsk_error_print(stderr); if (tsk_error_get_errno() == TSK_ERR_VS_UNSUPTYPE) tsk_vs_type_print(stderr); exit(1); } if (pnum >= vs->part_count) { tsk_fprintf(stderr, "Partition address is too large (maximum: %" PRIuPNUM ")\n", vs->part_count); exit(1); } vs_part = tsk_vs_part_get(vs, pnum); if (vs_part == NULL) { tsk_fprintf(stderr, "Error looking up partition\n"); exit(1); } buf = (char *) malloc(vs->block_size); if (buf == NULL) { tsk_error_print(stderr); exit(1); } #ifdef TSK_WIN32 char strerror_buffer[1024]; if (-1 == _setmode(_fileno(stdout), _O_BINARY)) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_WRITE); tsk_error_set_errstr( "mmcat: error setting stdout to binary: %s", strerror_s(strerror_buffer, 1024, errno)); return 1; } #endif for (addr = 0; addr < vs_part->len; addr++) { ssize_t retval; retval = tsk_vs_part_read_block(vs_part, addr, buf, vs->block_size); if (retval == -1) { tsk_error_print(stderr); exit(1); } if ((size_t) retval != fwrite(buf, 1, retval, stdout)) { tsk_fprintf(stderr, "Error writing data to stdout\n"); exit(1); } } tsk_vs_close(vs); tsk_img_close(img); exit(0); }