/* * Parse the UsnJrnl file. * Iterates through the file in blocks. * Returns 0 on success, 1 otherwise */ static uint8_t parse_file(NTFS_INFO * ntfs, unsigned char *buf, TSK_FS_USNJENTRY_WALK_CB action, void *ptr) { ssize_t size = 0; TSK_OFF_T offset = 0, ret = 0; while ((size = tsk_fs_file_read(ntfs->usnjinfo->fs_file, offset, (char*)buf, ntfs->usnjinfo->bsize, TSK_FS_FILE_READ_FLAG_NONE)) > 0) { ret = parse_buffer(buf, size, ntfs->fs_info.endian, action, ptr); if (ret < 0) return 1; else if (ret == 0) return 0; offset += ret; } return 0; }
/* * Class: edu_uw_apl_commons_tsk4j_filesys_File * Method: read * Signature: (JJI[BIIJ)I */ JNIEXPORT jint JNICALL Java_edu_uw_apl_commons_tsk4j_filesys_File_read (JNIEnv *env, jobject thiz, jlong nativePtr, jlong fileOffset, jint flags, jbyteArray buf, jint bufOffset, jint len, jlong nativeHeapPtr ) { TSK_FS_FILE* fsFile = (TSK_FS_FILE*)nativePtr; char* bufC = (char*)nativeHeapPtr; // printf( "%p %lu %u %u\n", fsFile, fileOffset, len, flags ); ssize_t read = tsk_fs_file_read( fsFile, fileOffset, (char*)bufC, len,flags ); if( read != -1 ) (*env)->SetByteArrayRegion( env, buf, bufOffset, read, (const jbyte*)bufC ); /* workaround a (possible?) bug in tsk_fs_file_read where a sparse file which SHOULD populate our buffer with N zeros and return N actually returns 0. Best we can do at this point is assert this is eof, so return -1. Same logic is in attribute.c, tracking tsk_fs_attr_read. */ if( read == 0 ) read = -1; return (jint)read; }
/* * Read bytes from the given file * @return array of bytes read from the file * @param env pointer to java environment this was called from * @param obj the java object this was called from * @param a_file_info the pointer to the file 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_readFileNat(JNIEnv * env, jclass obj, jlong a_file_info, jlong offset, jlong len) { char *buf = (char *) tsk_malloc((size_t) len); if (buf == NULL) { throwTskError(env); return NULL; } TSK_FS_FILE *file_info = castFsFile(env, a_file_info); ssize_t retval = tsk_fs_file_read(file_info, (TSK_OFF_T) offset, buf, (size_t) len, TSK_FS_FILE_READ_FLAG_NONE); 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; }
static TSK_WALK_RET_ENUM proc_dir(TSK_FS_FILE* fs_file, const char* path, void* stuff) { FILE* log = (FILE*)stuff; fprintf(log, "%s%s: flags: %d, addr: %d", path, fs_file->name->name, fs_file->meta->flags, (int)fs_file->meta->addr); // hmm, not sure if the ntfs sid stuff is working at all, but at // least call it to detect possible hangs if (fs_file->fs_info->fread_owner_sid) { char* sid_str = 0; if (tsk_fs_file_get_owner_sid(fs_file, &sid_str)) { if (tsk_verbose) { tsk_error_print(stderr); } } else { fprintf(log, ", sid_str: %s\n", sid_str); free(sid_str); } } fputc('\n', log); if (fs_file->meta->type == TSK_FS_META_TYPE_REG) { char buf[2048]; size_t len = 0; for (TSK_OFF_T off = 0; off < fs_file->meta->size; off += len) { if (fs_file->meta->size - off < (TSK_OFF_T)sizeof(buf)) { len = (size_t) (fs_file->meta->size - off); } else { len = sizeof(buf); } int myflags = 0; ssize_t cnt = tsk_fs_file_read(fs_file, off, buf, len, (TSK_FS_FILE_READ_FLAG_ENUM)myflags); if (cnt == -1) { if (tsk_verbose) { fprintf(stderr, "Error reading %s file: %s\n", ((fs_file->name-> flags & TSK_FS_NAME_FLAG_UNALLOC) || (fs_file->meta-> flags & TSK_FS_META_FLAG_UNALLOC)) ? "unallocated" : "allocated", fs_file->name->name); tsk_error_print(stderr); } break; } else if (cnt != (ssize_t) len) { if (tsk_verbose) { fprintf(stderr, "Warning: %" PRIuSIZE " of %" PRIuSIZE " bytes read from %s file %s\n", cnt, len, ((fs_file->name-> flags & TSK_FS_NAME_FLAG_UNALLOC) || (fs_file->meta-> flags & TSK_FS_META_FLAG_UNALLOC)) ? "unallocated" : "allocated", fs_file->name->name); } } // data is in buf[0..len); could be binary, not null terminated // might consider printing it out if all ascii or looks like text // or print hexdump, just for thread comparison } } return TSK_WALK_CONT; }
/** * Open a directory and cycle through its contents. Read each file and recurse * into each directory. * * @param fs_info File system to process * @param stack Stack to prevent infinite recursion loops * @param dir_inum Metadata address of directory to open * @param path Path of directory being opened * @returns 1 on error */ static uint8_t proc_dir(TSK_FS_INFO * fs_info, TSK_STACK * stack, TSK_INUM_T dir_inum, const char *path) { TSK_FS_DIR *fs_dir; size_t i; char *path2 = NULL; char *buf = NULL; // open the directory if ((fs_dir = tsk_fs_dir_open_meta(fs_info, dir_inum)) == NULL) { fprintf(stderr, "Error opening directory: %" PRIuINUM "\n", dir_inum); tsk_error_print(stderr); return 1; } /* These should be dynamic lengths, but this is just a sample program. * Allocate heap space instead of stack to prevent overflow for deep * directories. */ if ((path2 = (char *) malloc(4096)) == NULL) { return 1; } if ((buf = (char *) malloc(2048)) == NULL) { free(path2); return 1; } // cycle through each entry for (i = 0; i < tsk_fs_dir_getsize(fs_dir); i++) { TSK_FS_FILE *fs_file; TSK_OFF_T off = 0; size_t len = 0; // get the entry if ((fs_file = tsk_fs_dir_get(fs_dir, i)) == NULL) { fprintf(stderr, "Error getting directory entry %" PRIuSIZE " in directory %" PRIuINUM "\n", i, dir_inum); tsk_error_print(stderr); free(path2); free(buf); return 1; } /* Ignore NTFS System files */ if ((TSK_FS_TYPE_ISNTFS(fs_file->fs_info->ftype)) && (fs_file->name->name[0] == '$')) { tsk_fs_file_close(fs_file); continue; } //printf("Processing %s/%s\n", path, fs_file->name->name); // make sure it's got metadata and not only a name if (fs_file->meta) { ssize_t cnt; /* Note that we could also cycle through all of the attributes in the * file by using one of the tsk_fs_attr_get() functions and reading it * with tsk_fs_attr_read(). See the File Systems section of the Library * User's Guide for more details: * http://www.sleuthkit.org/sleuthkit/docs/api-docs/ */ // read file contents if (fs_file->meta->type == TSK_FS_META_TYPE_REG) { int myflags = 0; for (off = 0; off < fs_file->meta->size; off += len) { if (fs_file->meta->size - off < 2048) len = (size_t) (fs_file->meta->size - off); else len = 2048; cnt = tsk_fs_file_read(fs_file, off, buf, len, (TSK_FS_FILE_READ_FLAG_ENUM) myflags); if (cnt == -1) { // could check tsk_errno here for a recovery error (TSK_ERR_FS_RECOVER) fprintf(stderr, "Error reading %s file: %s\n", ((fs_file->name-> flags & TSK_FS_NAME_FLAG_UNALLOC) || (fs_file->meta-> flags & TSK_FS_META_FLAG_UNALLOC)) ? "unallocated" : "allocated", fs_file->name->name); tsk_error_print(stderr); break; } else if (cnt != (ssize_t) len) { fprintf(stderr, "Warning: %" PRIuSIZE " of %" PRIuSIZE " bytes read from %s file %s\n", cnt, len, ((fs_file->name-> flags & TSK_FS_NAME_FLAG_UNALLOC) || (fs_file->meta-> flags & TSK_FS_META_FLAG_UNALLOC)) ? "unallocated" : "allocated", fs_file->name->name); } // do something with the data... } } // recurse into another directory (unless it is a '.' or '..') else if (fs_file->meta->type == TSK_FS_META_TYPE_DIR) { if (TSK_FS_ISDOT(fs_file->name->name) == 0) { // only go in if it is not on our stack if (tsk_stack_find(stack, fs_file->meta->addr) == 0) { // add the address to the top of the stack tsk_stack_push(stack, fs_file->meta->addr); snprintf(path2, 4096, "%s/%s", path, fs_file->name->name); if (proc_dir(fs_info, stack, fs_file->meta->addr, path2)) { tsk_fs_file_close(fs_file); tsk_fs_dir_close(fs_dir); free(path2); free(buf); return 1; } // pop the address tsk_stack_pop(stack); } } } } tsk_fs_file_close(fs_file); } tsk_fs_dir_close(fs_dir); free(path2); free(buf); return 0; }
/** \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_ENUM iso9660_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir, TSK_INUM_T a_addr) { TSK_RETVAL_ENUM retval; TSK_FS_DIR *fs_dir; ssize_t cnt; char *buf; size_t length; if (a_addr < a_fs->first_inum || a_addr > a_fs->last_inum) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_WALK_RNG); tsk_error_set_errstr ("iso9660_dir_open_meta: Invalid inode value: %" PRIuINUM, a_addr); return TSK_ERR; } else if (a_fs_dir == NULL) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_ARG); tsk_error_set_errstr ("iso9660_dir_open_meta: NULL fs_attr argument given"); return TSK_ERR; } if (tsk_verbose) tsk_fprintf(stderr, "iso9660_dir_open_meta: Processing directory %" PRIuINUM "\n", a_addr); 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, a_addr, 128)) == NULL) { return TSK_ERR; } } // handle the orphan directory if its contents were requested if (a_addr == TSK_FS_ORPHANDIR_INUM(a_fs)) { return tsk_fs_dir_find_orphans(a_fs, fs_dir); } fs_dir->fs_file = tsk_fs_file_open_meta(a_fs, NULL, a_addr); if (fs_dir->fs_file == NULL) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_INODE_NUM); tsk_error_set_errstr("iso9660_dir_open_meta: %" PRIuINUM " is not a valid inode", a_addr); return TSK_COR; } /* read directory extent into memory */ length = (size_t) fs_dir->fs_file->meta->size; if ((buf = tsk_malloc(length)) == NULL) return TSK_ERR; cnt = tsk_fs_file_read(fs_dir->fs_file, 0, buf, length, 0); if (cnt != length) { if (cnt >= 0) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); } tsk_error_set_errstr2("iso9660_dir_open_meta"); return TSK_ERR; } // process the contents retval = iso9660_proc_dir(a_fs, fs_dir, buf, length, a_addr, fs_dir->fs_file->meta->attr->head->nrd.run->addr); // if we are listing the root directory, add the Orphan directory entry 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; 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; }
void tsk_get_file(const char* imgname,uint64_t haddr_img_offset, const char* file_path, const char* destination, uint64_t start_offset, int read_file_len ) { TSK_IMG_INFO *img; TSK_VS_INFO *vs; TSK_FS_INFO *fs; uint8_t id_used = 0, type_used = 0; TSK_DADDR_T partition_offset = 0; TSK_DADDR_T block_img_offset = 0; TSK_DADDR_T part_byte_offset = 0; TSK_DADDR_T part_block_offset = 0; MBA_IFIND_DATA_DATA* ifind_data; TSK_IMG_TYPE_ENUM imgtype; MBA_FFIND_DATA* ffind_data; TSK_FS_FILE *file; FILE* writeHive; char *temp; //open image imgtype = tsk_img_type_toid(QCOW_IMG_TYPE); img = tsk_img_open_sing(imgname, imgtype, 0); if(img == NULL) { printf("Image Open Failed!!\n"); return; } if(haddr_img_offset >= img->size) { printf("Request haddr is larger than image size\n"); return; } //open volume vs = tsk_vs_open(img, 0 , TSK_VS_TYPE_DETECT); if(vs==NULL) { printf("Volume Open Failed!!\n"); return; } //calculate block address block_img_offset = haddr_img_offset/img->sector_size; //search the partition contain the target block partition_offset = search_partition(vs, block_img_offset); if(partition_offset == 0) { printf("Cannot found partition contains the target haddr\n"); return; } //open the partition's file system fs = tsk_fs_open_img(img, partition_offset * img->sector_size, TSK_FS_TYPE_DETECT); if(fs==NULL) { printf("Cannot open file system\n"); return; } //calculate offset to the current partition part_byte_offset = haddr_img_offset - (partition_offset * img->sector_size); part_block_offset = part_byte_offset/fs->block_size; file = tsk_fs_file_open( fs, NULL, file_path); if ( OPEN_FAIL(file) ) printf("open file fail\n\n"); temp = calloc( read_file_len, sizeof(char)); int size = tsk_fs_file_read( file, start_offset, temp, read_file_len, TSK_FS_FILE_READ_FLAG_NONE ); tsk_fs_file_close(file); writeHive = fopen( destination, "w" ); if ( writeHive == NULL ) printf("Open fail"); else { fwrite( temp, size, sizeof(char), writeHive ); fclose(writeHive); } // else free(temp); //find the inode of this block ifind_data = fs_ifind_data(fs, (TSK_FS_IFIND_FLAG_ENUM) 0, part_block_offset); if(ifind_data == NULL) { return; } if(ifind_data->found!=1) { printf("Inode not found\n"); return; } //Find the inode's filename //Note: Do Not Know what to fill in variable type_used and id_used ffind_data = fs_ffind(fs, 0, ifind_data->curinode, ifind_data->curtype , type_used, ifind_data->curid , id_used, (TSK_FS_DIR_WALK_FLAG_RECURSE | TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC)); if(ffind_data==NULL){ printf("Cannot found fdata associate with inode\n"); return; } free(ifind_data); return; }
/* This test checks the SLACK flags and verifies * that we read data from the slack space */ int test_ntfs_slack_ads() { TSK_FS_INFO *fs; TSK_IMG_INFO *img; const char *tname = "ntfs-img-kw"; char fname[512]; TSK_FS_FILE *file1; char buf[512]; ssize_t retval; snprintf(fname, 512, "%s/ntfs-img-kw-1.dd", s_root); if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) { fprintf(stderr, "Error opening %s image\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } if ((fs = tsk_fs_open_img(img, 0, (TSK_FS_TYPE_ENUM) 0)) == NULL) { fprintf(stderr, "Error opening %s image\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } // file-n-44.dat file1 = tsk_fs_file_open_meta(fs, NULL, 36); if (file1 == NULL) { fprintf(stderr, "Error opening file-n-4.dat (%s)\n", tname); return 1; } // verify expected size if (file1->meta->size != 2000) { fprintf(stderr, "Error: file-n-4.dat not expected size (%" PRIuOFF ") (%s)\n", file1->meta->size, tname); return 1; } // try to read all of last sector with/out Slack set retval = tsk_fs_file_read(file1, 1536, buf, 512, (TSK_FS_FILE_READ_FLAG_ENUM) 0); if (retval == -1) { fprintf(stderr, "Error reading file-n-4.dat to end w/out slack flag (%s)\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } if (retval != 464) { fprintf(stderr, "Unexpected return value from reading file-n-4.dat to end w/out slack flag (%s).\n", tname); fprintf(stderr, "Expected: 464. Got: %zd\n", retval); return 1; } retval = tsk_fs_file_read(file1, 1536, buf, 512, TSK_FS_FILE_READ_FLAG_SLACK); if (retval == -1) { fprintf(stderr, "Error reading file-n-4.dat to end w/slack flag (%s)\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } if (retval != 512) { fprintf(stderr, "Unexpected return value from reading file-n-4.dat w/slack flag. (%s)\n", tname); fprintf(stderr, "Expected: 512. Got: %zd\n", retval); return 1; } // verify the term in the slack space if (memcmp("n-slack", &buf[485], 7) != 0) { fprintf(stderr, "slack string not found in file-n-4.dat slack space: %c %c %c %c %c %c %c (%s)\n", buf[485], buf[486], buf[487], buf[488], buf[489], buf[490], buf[491], tname); return 1; } // try to read past end of file retval = tsk_fs_file_read(file1, 2001, buf, 32, (TSK_FS_FILE_READ_FLAG_ENUM) 0); if (retval != -1) { fprintf(stderr, "Unexpected return value from reading file-n-4.dat after end of file (%s).\n", tname); fprintf(stderr, "Expected: -1. Got: %zd\n", retval); return 1; } tsk_fs_file_close(file1); // file-n-5.dat file1 = tsk_fs_file_open_meta(fs, NULL, 37); if (file1 == NULL) { fprintf(stderr, "Error opening file-n-5.dat (%s)\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } // check the default size to make sure it is the default $Data if (file1->meta->size != 1300) { fprintf(stderr, "file-n-5.dat size is not 1300 (%" PRIuOFF ") (%s)", file1->meta->size, tname); return 1; } // test the getsize API for both attributes const TSK_FS_ATTR *fs_attr = tsk_fs_file_attr_get_type(file1, TSK_FS_ATTR_TYPE_NTFS_DATA, 3, 1); if (!fs_attr) { fprintf(stderr, "Error getting data attribute 3 in file-n-5.dat (%s)", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } if (fs_attr->size != 1300) { fprintf(stderr, "file-n-5.dat size (via getsize) is not 1300 (%" PRIuOFF ") (%s)", fs_attr->size, tname); return 1; } fs_attr = tsk_fs_file_attr_get_type(file1, TSK_FS_ATTR_TYPE_NTFS_DATA, 5, 1); if (!fs_attr) { fprintf(stderr, "Error getting size of attribute 5 in file-n-5.dat (%s)", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } if (fs_attr->size != 2000) { fprintf(stderr, "file-n-5.dat:here size (via getsize) is not 2000 (%" PRIuOFF ") (%s)", fs_attr->size, tname); return 1; } tsk_fs_file_close(file1); tsk_fs_close(fs); tsk_img_close(img); return 0; }
/* This test checks the RECOVER flags */ int test_fat_recover() { TSK_FS_INFO *fs; TSK_IMG_INFO *img; const char *tname = "fe_test_1.img-FAT"; char fname[512]; TSK_FS_FILE *file1; TSK_FS_FILE *file2; char buf[512]; ssize_t retval; snprintf(fname, 512, "%s/fe_test_1.img", s_root); if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) { fprintf(stderr, "Error opening %s image\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } if ((fs = tsk_fs_open_img(img, 41126400, (TSK_FS_TYPE_ENUM) 0)) == NULL) { fprintf(stderr, "Error opening %s image\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } // fragmented.html const char *fname2 = "fragmented.html"; file1 = tsk_fs_file_open_meta(fs, NULL, 1162); if (file1 == NULL) { fprintf(stderr, "Error opening %s (%s)\n", fname2, tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } // verify expected size if (file1->meta->size != 5905) { fprintf(stderr, "Error: %s not expected size (%" PRIuOFF ") (%s)\n", fname2, file1->meta->size, tname); return 1; } // verify we can open it via name as well file2 = tsk_fs_file_open(fs, NULL, "/deleted/fragmented.html"); if (file2 == NULL) { fprintf(stderr, "Error opening /deleted/fragmented.html via path name (%s)\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } if (file2->name == NULL) { fprintf(stderr, "Opening /deleted/fragmented.html via path name did not have name set(%s)\n", tname); return 1; } if (strcmp(file2->name->name, fname2) != 0) { fprintf(stderr, "Opening /deleted/fragmented.html via path had incorrect name set (%s) (%s)\n", file2->name->name, tname); return 1; } if ((file2->name->meta_addr != file2->meta->addr) || (file2->meta->addr != file1->meta->addr)) { fprintf(stderr, "Opening /deleted/fragmented.html via path had incorrect meta addresses (%" PRIuINUM " %" PRIuINUM " %" PRIuINUM " (%s)\n", file2->name->meta_addr, file2->meta->addr, file1->meta->addr, tname); return 1; } tsk_fs_file_close(file2); file2 = NULL; // try to read past end of first 2048-byte cluster retval = tsk_fs_file_read(file1, 2048, buf, 512, (TSK_FS_FILE_READ_FLAG_ENUM) 0); if (retval == -1) { fprintf(stderr, "Error reading %s past end w/out Recover flag\n", fname2); tsk_error_print(stderr); tsk_error_reset(); return 1; } // current behavior is to return 0s in "unitialized" space //if (retval != 0) { if (retval != 512) { fprintf(stderr, "Unexpected return value from reading %s past end w/out Recover flag.\n", fname2); fprintf(stderr, "Expected: 0. Got: %zd\n", retval); return 1; } retval = tsk_fs_file_read(file1, 2048, buf, 512, (TSK_FS_FILE_READ_FLAG_ENUM) 0); if (retval == -1) { fprintf(stderr, "Error reading %s past end w/Recover flag\n", fname2); tsk_error_print(stderr); tsk_error_reset(); return 1; } if (retval != 512) { fprintf(stderr, "Unexpected return value from %s past end w/Recover flag.\n", fname2); fprintf(stderr, "Expected: 512. Got: %zd\n", retval); return 1; } // verify the term in the slack space if (memcmp("appear", buf, 6) != 0) { fprintf(stderr, "expected string not found in %s recovery: %c %c %c %c %c %c\n", fname2, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); return 1; } tsk_fs_file_close(file1); tsk_fs_close(fs); tsk_img_close(img); return 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; }
/* This test checks the SLACK flags and verifies * that we read data from the slack space */ int test_fat_slack() { TSK_FS_INFO *fs; TSK_IMG_INFO *img; const char *tname = "fat-img-kw"; char fname[512]; TSK_FS_FILE *file1; char buf[512]; ssize_t retval; snprintf(fname, 512, "%s/fat-img-kw.dd", s_root); if ((img = tsk_img_open_sing(fname, (TSK_IMG_TYPE_ENUM) 0, 0)) == NULL) { fprintf(stderr, "Error opening %s image\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } if ((fs = tsk_fs_open_img(img, 0, (TSK_FS_TYPE_ENUM) 0)) == NULL) { fprintf(stderr, "Error opening %s image\n", tname); tsk_error_print(stderr); tsk_error_reset(); return 1; } // file4.dat file1 = tsk_fs_file_open_meta(fs, NULL, 10); if (file1 == NULL) { fprintf(stderr, "Error opening file4.dat (%s)\n", tname); return 1; } // verify expected size if (file1->meta->size != 631) { fprintf(stderr, "Error: file4.dat not expected size (%" PRIuOFF ") (%s)\n", file1->meta->size, tname); return 1; } // try to read all of last sector with/out Slack set retval = tsk_fs_file_read(file1, 512, buf, 512, (TSK_FS_FILE_READ_FLAG_ENUM) 0); if (retval == -1) { fprintf(stderr, "Error reading file4.dat to end w/out slack flag\n"); tsk_error_print(stderr); tsk_error_reset(); return 1; } if (retval != 119) { fprintf(stderr, "Unexpected return value from reading file4.dat to end w/out slack flag.\n"); fprintf(stderr, "Expected: 119. Got: %zd\n", retval); return 1; } retval = tsk_fs_file_read(file1, 512, buf, 512, TSK_FS_FILE_READ_FLAG_SLACK); if (retval == -1) { fprintf(stderr, "Error reading file4.dat to end w/slack flag\n"); tsk_error_print(stderr); tsk_error_reset(); return 1; } if (retval != 512) { fprintf(stderr, "Unexpected return value from reading file4.dat w/slack flag.\n"); fprintf(stderr, "Expected: 512. Got: %zd\n", retval); return 1; } // verify the term in the slack space if (memcmp("3slack3", &buf[385], 7) != 0) { fprintf(stderr, "slack string not found in file4.dat slack space: %x %x %x %x %x %x %x\n", buf[385], buf[386], buf[387], buf[388], buf[389], buf[390], buf[391]); return 1; } tsk_fs_close(fs); tsk_img_close(img); return 0; }