/* tsk_fs_malloc - init lock after tsk_malloc * This is for fs module and all it's inheritances */ TSK_FS_INFO * tsk_fs_malloc(size_t a_len) { TSK_FS_INFO *fs_info; if ((fs_info = (TSK_FS_INFO *) tsk_malloc(a_len)) == NULL) return NULL; tsk_init_lock(&fs_info->list_inum_named_lock); tsk_init_lock(&fs_info->orphan_dir_lock); fs_info->list_inum_named = NULL; return fs_info; }
/** * \internal * Initializes the data structures used to cache the cluster addresses that * make up FAT chains in an exFAT file system, and the lock used to make the * data structures thread-safe. * * @param [in, out] a_fatfs Generic FAT file system info structure. */ static void exfatfs_init_fat_cache(FATFS_INFO *a_fatfs) { uint32_t i = 0; assert(a_fatfs != NULL); for (i = 0; i < FATFS_FAT_CACHE_N; i++) { a_fatfs->fatc_addr[i] = 0; a_fatfs->fatc_ttl[i] = 0; } tsk_init_lock(&a_fatfs->cache_lock); tsk_init_lock(&a_fatfs->dir_lock); a_fatfs->inum2par = NULL; }
/** * \internal * Initializes the data structure used to map inode addresses to parent inode * addresses in an exFAT file system, and the lock used to make the data * structure thread-safe. * * @param [in, out] a_fatfs Generic FAT file system info structure. */ static void exfatfs_init_inums_map(FATFS_INFO *a_fatfs) { assert(a_fatfs != NULL); tsk_init_lock(&a_fatfs->dir_lock); a_fatfs->inum2par = NULL; }
/* tsk_img_malloc - init lock after tsk_malloc * This is for img module and all its inheritances */ void * tsk_img_malloc(size_t a_len) { TSK_IMG_INFO *imgInfo; if ((imgInfo = (TSK_IMG_INFO *) tsk_malloc(a_len)) == NULL) return NULL; //init lock tsk_init_lock(&(imgInfo->cache_lock)); imgInfo->tag = TSK_IMG_INFO_TAG; return (void *) imgInfo; }
/** * \ingroup hashdblib * \internal * Initializes TSK_HDB_INFO struct with "base class" method pointers and basic * setup of values. * @param hdb_info Allocated struct to initialize. * @param db_path * @return 0 on success, 1 on failure. */ uint8_t hdb_info_base_open(TSK_HDB_INFO *hdb_info, const TSK_TCHAR *db_path) { // copy the database path into the struct size_t path_len = TSTRLEN(db_path); hdb_info->db_fname = (TSK_TCHAR*)tsk_malloc((path_len + 1) * sizeof(TSK_TCHAR)); if (!hdb_info->db_fname) { return 1; } TSTRNCPY(hdb_info->db_fname, db_path, path_len); // set the name based on path hdb_base_db_name_from_path(hdb_info); hdb_info->db_type = TSK_HDB_DBTYPE_INVALID_ID; tsk_init_lock(&hdb_info->lock); hdb_info->transaction_in_progress = 0; hdb_info->get_db_path = hdb_base_get_db_path; hdb_info->get_display_name = hdb_base_get_display_name; hdb_info->uses_external_indexes = hdb_base_uses_external_indexes; hdb_info->get_index_path = hdb_base_get_index_path; hdb_info->has_index = hdb_base_has_index; hdb_info->make_index = hdb_base_make_index; hdb_info->open_index = hdb_base_open_index; hdb_info->lookup_str = hdb_base_lookup_str; hdb_info->lookup_raw = hdb_base_lookup_bin; hdb_info->lookup_verbose_str = hdb_base_lookup_verbose_str; hdb_info->accepts_updates = hdb_base_accepts_updates; hdb_info->add_entry = hdb_base_add_entry; hdb_info->begin_transaction = hdb_base_begin_transaction; hdb_info->commit_transaction = hdb_base_commit_transaction; hdb_info->rollback_transaction = hdb_base_rollback_transaction; hdb_info->close_db = hdb_info_base_close; return 0; }
TSK_IMG_INFO * ewf_open(int a_num_img, const TSK_TCHAR * const a_images[], unsigned int a_ssize) { #if defined( HAVE_LIBEWF_V2_API ) char error_string[TSK_EWF_ERROR_STRING_SIZE]; libewf_error_t *ewf_error = NULL; int result = 0; #elif !defined( LIBEWF_STRING_DIGEST_HASH_LENGTH_MD5 ) uint8_t md5_hash[16]; #endif IMG_EWF_INFO *ewf_info = NULL; TSK_IMG_INFO *img_info = NULL; #if !defined( HAVE_LIBEWF_V2_API) if (tsk_verbose) libewf_set_notify_values(stderr, 1); #endif if ((ewf_info = (IMG_EWF_INFO *) tsk_img_malloc(sizeof(IMG_EWF_INFO))) == NULL) { return NULL; } img_info = (TSK_IMG_INFO *) ewf_info; // See if they specified only the first of the set... ewf_info->used_ewf_glob = 0; if (a_num_img == 1) { #if defined( HAVE_LIBEWF_V2_API) #ifdef TSK_WIN32 if (libewf_glob_wide(a_images[0], TSTRLEN(a_images[0]), LIBEWF_FORMAT_UNKNOWN, &ewf_info->images, &ewf_info->num_imgs, &ewf_error) == -1) { #else if (libewf_glob(a_images[0], TSTRLEN(a_images[0]), LIBEWF_FORMAT_UNKNOWN, &ewf_info->images, &ewf_info->num_imgs, &ewf_error) == -1) { #endif tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_MAGIC); getError(ewf_error, error_string); tsk_error_set_errstr("ewf_open: Not an E01 glob name (%s)", error_string); libewf_error_free(&ewf_error); tsk_img_free(ewf_info); return NULL; } #else //use v1 #ifdef TSK_WIN32 ewf_info->num_imgs = libewf_glob_wide(a_images[0], TSTRLEN(a_images[0]), LIBEWF_FORMAT_UNKNOWN, &ewf_info->images); #else ewf_info->num_imgs = libewf_glob(a_images[0], TSTRLEN(a_images[0]), LIBEWF_FORMAT_UNKNOWN, &ewf_info->images); #endif if (ewf_info->num_imgs <= 0) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_MAGIC); tsk_error_set_errstr("ewf_open: Not an E01 glob name"); tsk_img_free(ewf_info); return NULL; } #endif // end v1 ewf_info->used_ewf_glob = 1; if (tsk_verbose) tsk_fprintf(stderr, "ewf_open: found %d segment files via libewf_glob\n", ewf_info->num_imgs); } else { int i; ewf_info->num_imgs = a_num_img; if ((ewf_info->images = (TSK_TCHAR **) tsk_malloc(a_num_img * sizeof(TSK_TCHAR *))) == NULL) { tsk_img_free(ewf_info); return NULL; } for (i = 0; i < a_num_img; i++) { if ((ewf_info->images[i] = (TSK_TCHAR *) tsk_malloc((TSTRLEN(a_images[i]) + 1) * sizeof(TSK_TCHAR))) == NULL) { tsk_img_free(ewf_info); return NULL; } TSTRNCPY(ewf_info->images[i], a_images[i], TSTRLEN(a_images[i]) + 1); } } #if defined( HAVE_LIBEWF_V2_API ) // Check the file signature before we call the library open #if defined( TSK_WIN32 ) if (libewf_check_file_signature_wide(a_images[0], &ewf_error) != 1) #else if (libewf_check_file_signature(a_images[0], &ewf_error) != 1) #endif { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_MAGIC); getError(ewf_error, error_string); tsk_error_set_errstr("ewf_open: Not an EWF file (%s)", error_string); libewf_error_free(&ewf_error); tsk_img_free(ewf_info); if (tsk_verbose != 0) { tsk_fprintf(stderr, "Not an EWF file\n"); } return (NULL); } if (libewf_handle_initialize(&(ewf_info->handle), &ewf_error) != 1) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_OPEN); getError(ewf_error, error_string); tsk_error_set_errstr("ewf_open file: %" PRIttocTSK ": Error initializing handle (%s)", a_images[0], error_string); libewf_error_free(&ewf_error); tsk_img_free(ewf_info); if (tsk_verbose != 0) { tsk_fprintf(stderr, "Unable to create EWF handle\n"); } return (NULL); } #if defined( TSK_WIN32 ) if (libewf_handle_open_wide(ewf_info->handle, (wchar_t * const *) ewf_info->images, ewf_info->num_imgs, LIBEWF_OPEN_READ, &ewf_error) != 1) #else if (libewf_handle_open(ewf_info->handle, (char *const *) ewf_info->images, ewf_info->num_imgs, LIBEWF_OPEN_READ, &ewf_error) != 1) #endif { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_OPEN); getError(ewf_error, error_string); tsk_error_set_errstr("ewf_open file: %" PRIttocTSK ": Error opening (%s)", a_images[0], error_string); libewf_error_free(&ewf_error); tsk_img_free(ewf_info); if (tsk_verbose != 0) { tsk_fprintf(stderr, "Error opening EWF file\n"); } return (NULL); } if (libewf_handle_get_media_size(ewf_info->handle, (size64_t *) & (img_info->size), &ewf_error) != 1) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_OPEN); getError(ewf_error, error_string); tsk_error_set_errstr("ewf_open file: %" PRIttocTSK ": Error getting size of image (%s)", a_images[0], error_string); libewf_error_free(&ewf_error); tsk_img_free(ewf_info); if (tsk_verbose != 0) { tsk_fprintf(stderr, "Error getting size of EWF file\n"); } return (NULL); } result = libewf_handle_get_utf8_hash_value_md5(ewf_info->handle, (uint8_t *) ewf_info->md5hash, 33, &ewf_error); if (result == -1) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_OPEN); getError(ewf_error, error_string); tsk_error_set_errstr("ewf_open file: %" PRIttocTSK ": Error getting MD5 of image (%s)", a_images[0], error_string); libewf_error_free(&ewf_error); tsk_img_free(ewf_info); if (tsk_verbose != 0) { tsk_fprintf(stderr, "Error getting size of EWF file\n"); } return (NULL); } ewf_info->md5hash_isset = result; #else // V1 API // Check the file signature before we call the library open #if defined( TSK_WIN32 ) if (libewf_check_file_signature_wide(a_images[0]) != 1) #else if (libewf_check_file_signature(a_images[0]) != 1) #endif { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_MAGIC); tsk_error_set_errstr("ewf_open: Not an EWF file"); tsk_img_free(ewf_info); if (tsk_verbose) tsk_fprintf(stderr, "Not an EWF file\n"); return NULL; } #if defined( TSK_WIN32 ) ewf_info->handle = libewf_open_wide( (wchar_t * const *) ewf_info->images, ewf_info->num_imgs, LIBEWF_OPEN_READ); #else ewf_info->handle = libewf_open( (char *const *) ewf_info->images, ewf_info->num_imgs, LIBEWF_OPEN_READ); #endif if (ewf_info->handle == NULL) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_OPEN); tsk_error_set_errstr("ewf_open file: %" PRIttocTSK ": Error opening", ewf_info->images[0]); tsk_img_free(ewf_info); if (tsk_verbose != 0) { tsk_fprintf(stderr, "Error opening EWF file\n"); } return (NULL); } #if defined( LIBEWF_STRING_DIGEST_HASH_LENGTH_MD5 ) // 2007 version img_info->size = libewf_get_media_size(ewf_info->handle); ewf_info->md5hash_isset = libewf_get_stored_md5_hash(ewf_info->handle, ewf_info->md5hash, LIBEWF_STRING_DIGEST_HASH_LENGTH_MD5); #else // libewf-20080322 version if (libewf_get_media_size(ewf_info->handle, (size64_t *) & (img_info->size)) != 1) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_OPEN); tsk_error_set_errstr("ewf_open file: %" PRIttocTSK ": Error getting size of image", ewf_info->images[0]); tsk_img_free(ewf_info); if (tsk_verbose) { tsk_fprintf(stderr, "Error getting size of EWF file\n"); } return (NULL); } if (libewf_get_md5_hash(ewf_info->handle, md5_hash, 16) == 1) { int md5_string_iterator = 0; int md5_hash_iterator = 0; for (md5_hash_iterator = 0; md5_hash_iterator < 16; md5_hash_iterator++) { int digit = md5_hash[md5_hash_iterator] / 16; if (digit <= 9) { ewf_info->md5hash[md5_string_iterator++] = '0' + (char) digit; } else { ewf_info->md5hash[md5_string_iterator++] = 'a' + (char) (digit - 10); } digit = md5_hash[md5_hash_iterator] % 16; if (digit <= 9) { ewf_info->md5hash[md5_string_iterator++] = '0' + (char) digit; } else { ewf_info->md5hash[md5_string_iterator++] = 'a' + (char) (digit - 10); } } ewf_info->md5hash_isset = 1; } #endif /* defined( LIBEWF_STRING_DIGEST_HASH_LENGTH_MD5 ) */ #endif /* defined( HAVE_LIBEWF_V2_API ) */ if (a_ssize != 0) { img_info->sector_size = a_ssize; } else { img_info->sector_size = 512; } img_info->itype = TSK_IMG_TYPE_EWF_EWF; img_info->read = &ewf_image_read; img_info->close = &ewf_image_close; img_info->imgstat = &ewf_image_imgstat; // initialize the read lock tsk_init_lock(&(ewf_info->read_lock)); return (img_info); }
/** Originally we used tsk_img_open_sing(), but that leads to calling ewf_open(), which in turn will fail if the L01 file has an incorrect filename extension. This function is a simpler version of ewf_open() which will not fail if the filename extension is wrong. */ TSK_IMG_INFO * TskL01Extract::openEwfSimple() { const int a_num_img = 1; unsigned int a_ssize = 512; int result = 0; TSK_IMG_INFO *img_info = NULL; ewf::libewf_error_t *ewfError = NULL; ewf::IMG_EWF_INFO *ewf_info = NULL; try { // Make an absolute path (if it's relative) so that libewf doesn't cause // an error when it tries to make it absolute. Poco::Path tempPath(TskUtilities::toUTF8(m_archivePath)); tempPath.makeAbsolute(); // We convert to unicode here because that is what the TSK_IMG_INFO structure requires. std::wstring ewfArchivePath = TskUtilities::toUTF16(tempPath.toString()); if ((ewf_info = (ewf::IMG_EWF_INFO *) tsk_img_malloc(sizeof(ewf::IMG_EWF_INFO))) == NULL) { throw TskException("tsk_img_malloc"); } img_info = (TSK_IMG_INFO *) ewf_info; if (ewf::libewf_handle_initialize(&(ewf_info->handle), &ewfError) != 1) { throw TskException("libewf_handle_initialize"); } //int i; ewf_info->num_imgs = a_num_img; if ((ewf_info->images = (TSK_TCHAR **) tsk_malloc(a_num_img * sizeof(TSK_TCHAR *))) == NULL) { throw TskException("tsk_malloc"); } if ((ewf_info->images[0] = (TSK_TCHAR *) tsk_malloc((TSTRLEN(ewfArchivePath.c_str()) + 1) * sizeof(TSK_TCHAR))) == NULL) { throw TskException("tsk_malloc 2"); } TSTRNCPY(ewf_info->images[0], ewfArchivePath.c_str(), TSTRLEN(ewfArchivePath.c_str()) + 1); ///NOTE: libewf_handle_open_wide() will not open the file if the filename length is < 4 chars long. ewfError = NULL; #if defined( TSK_WIN32 ) if (ewf::libewf_handle_open_wide(ewf_info->handle, (TSK_TCHAR * const *) ewf_info->images, ewf_info->num_imgs, ewf::LIBEWF_ACCESS_FLAG_READ, &ewfError) != 1) #else if (ewf::libewf_handle_open(ewf_info->handle, (char *const *) ewf_info->images, ewf_info->num_imgs, ewf::LIBEWF_OPEN_READ, &ewfError) != 1) #endif { throw TskException("libewf_handle_open_wide"); } ewfError = NULL; if (ewf::libewf_handle_get_media_size(ewf_info->handle, (ewf::size64_t *) & (img_info->size), &ewfError) != 1) { throw TskException("libewf_handle_get_media_size"); } ewfError = NULL; result = ewf::libewf_handle_get_utf8_hash_value_md5(ewf_info->handle, (uint8_t *) ewf_info->md5hash, 33, &ewfError); if (result == -1) { throw TskException("libewf_handle_get_utf8_hash_value_md5"); } ewf_info->md5hash_isset = result; if (a_ssize != 0) { img_info->sector_size = a_ssize; } else { img_info->sector_size = 512; } img_info->itype = TSK_IMG_TYPE_EWF_EWF; img_info->close = ewf_image_close; img_info->read = null_read; img_info->imgstat = null_imgstat; // initialize the read lock tsk_init_lock(&(ewf_info->read_lock)); return img_info; } catch (TskException &ex) { std::ostringstream msg; msg << "openEwfSimple: TskException: " << ex.message(); if (ewfError) { char errorString[512]; errorString[0] = '\0'; ewf::libewf_error_backtrace_sprint(ewfError, errorString, 512); msg << " - libewf error: " << errorString << std::endl; } LOGERROR(msg.str()); free(ewf_info); return NULL; } }
uint8_t fatxxfs_open(FATFS_INFO *fatfs) { const char *func_name = "fatxxfs_open"; TSK_FS_INFO *fs = &(fatfs->fs_info); FATXXFS_SB *fatsb = (FATXXFS_SB*)(&fatfs->boot_sector_buffer); int i = 0; TSK_DADDR_T sectors = 0; TSK_FS_DIR * test_dir1; // Directories used to try opening the root directory // clean up any error messages that are lying around tsk_error_reset(); /* Calculate block sizes and layout info */ // sector size fatfs->ssize = tsk_getu16(fs->endian, fatsb->ssize); if (fatfs->ssize == 512) { fatfs->ssize_sh = 9; } else if (fatfs->ssize == 1024) { fatfs->ssize_sh = 10; } else if (fatfs->ssize == 2048) { fatfs->ssize_sh = 11; } else if (fatfs->ssize == 4096) { fatfs->ssize_sh = 12; } else { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_MAGIC); tsk_error_set_errstr ("Error: sector size (%d) is not a multiple of device size (%d)\nDo you have a disk image instead of a partition image?", fatfs->ssize, fs->dev_bsize); if (tsk_verbose) fprintf(stderr, "%s: Invalid sector size (%d)\n", func_name, fatfs->ssize); return 1; } // cluster size fatfs->csize = fatsb->csize; if ((fatfs->csize != 0x01) && (fatfs->csize != 0x02) && (fatfs->csize != 0x04) && (fatfs->csize != 0x08) && (fatfs->csize != 0x10) && (fatfs->csize != 0x20) && (fatfs->csize != 0x40) && (fatfs->csize != 0x80)) { if (tsk_verbose) fprintf(stderr, "%s: Invalid cluster size (%d)\n", func_name, fatfs->csize); tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_MAGIC); tsk_error_set_errstr("Not a FATXX file system (cluster size)"); return 1; } // number of FAT tables fatfs->numfat = fatsb->numfat; if ((fatfs->numfat == 0) || (fatfs->numfat > 8)) { if (tsk_verbose) fprintf(stderr, "%s: Invalid number of FATS (%d)\n", func_name, fatfs->numfat); tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_MAGIC); tsk_error_set_errstr("Not a FATXX file system (number of FATs)"); return 1; } /* We can't do a sanity check on this b.c. TSK_FS_TYPE_FAT32 has a value of 0 */ /* num of root entries */ fatfs->numroot = tsk_getu16(fs->endian, fatsb->numroot); /* if sectors16 is 0, then the number of sectors is stored in sectors32 */ if (0 == (sectors = tsk_getu16(fs->endian, fatsb->sectors16))) sectors = tsk_getu32(fs->endian, fatsb->sectors32); /* if secperfat16 is 0, then read sectperfat32 */ if (0 == (fatfs->sectperfat = tsk_getu16(fs->endian, fatsb->sectperfat16))) fatfs->sectperfat = tsk_getu32(fs->endian, fatsb->a.f32.sectperfat32); if (fatfs->sectperfat == 0) { if (tsk_verbose) fprintf(stderr, "%s: Invalid number of sectors per FAT (%d)\n", func_name, fatfs->sectperfat); tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_MAGIC); tsk_error_set_errstr ("Not a FATXX file system (invalid sectors per FAT)"); return 1; } fatfs->firstfatsect = tsk_getu16(fs->endian, fatsb->reserved); if ((fatfs->firstfatsect == 0) || (fatfs->firstfatsect > sectors)) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_WALK_RNG); tsk_error_set_errstr ("Not a FATXX file system (invalid first FAT sector %" PRIuDADDR ")", fatfs->firstfatsect); if (tsk_verbose) fprintf(stderr, "%s: Invalid first FAT (%" PRIuDADDR ")\n", func_name, fatfs->firstfatsect); return 1; } /* Calculate the block info * * The sector of the beginning of the data area - which is * after all of the FATs * * For TSK_FS_TYPE_FAT12 and TSK_FS_TYPE_FAT16, the data area starts with the root * directory entries and then the first cluster. For TSK_FS_TYPE_FAT32, * the data area starts with clusters and the root directory * is somewhere in the data area */ fatfs->firstdatasect = fatfs->firstfatsect + fatfs->sectperfat * fatfs->numfat; /* The sector where the first cluster is located. It will be used * to translate cluster addresses to sector addresses * * For TSK_FS_TYPE_FAT32, the first cluster is the start of the data area and * it is after the root directory for TSK_FS_TYPE_FAT12 and TSK_FS_TYPE_FAT16. At this * point in the program, numroot is set to 0 for TSK_FS_TYPE_FAT32 */ fatfs->firstclustsect = fatfs->firstdatasect + ((fatfs->numroot * 32 + fatfs->ssize - 1) / fatfs->ssize); /* total number of clusters */ fatfs->clustcnt = (sectors - fatfs->firstclustsect) / fatfs->csize; /* the first cluster is #2, so the final cluster is: */ fatfs->lastclust = 1 + fatfs->clustcnt; /* identify the FAT type by the total number of data clusters * this calculation is from the MS FAT Overview Doc * * A FAT file system made by another OS could use different values */ if (fatfs->fs_info.ftype == TSK_FS_TYPE_FAT_DETECT) { if (fatfs->clustcnt < 4085) { fatfs->fs_info.ftype = TSK_FS_TYPE_FAT12; } else if (fatfs->clustcnt < 65525) { fatfs->fs_info.ftype = TSK_FS_TYPE_FAT16; } else { fatfs->fs_info.ftype = TSK_FS_TYPE_FAT32; } fatfs->fs_info.ftype = fatfs->fs_info.ftype; } /* Some sanity checks */ else { if ((fatfs->fs_info.ftype == TSK_FS_TYPE_FAT12) && (fatfs->clustcnt >= 4085)) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_MAGIC); tsk_error_set_errstr ("Too many sectors for TSK_FS_TYPE_FAT12: try auto-detect mode"); if (tsk_verbose) fprintf(stderr, "%s: Too many sectors for FAT12\n", func_name); return 1; } } if ((fatfs->fs_info.ftype == TSK_FS_TYPE_FAT32) && (fatfs->numroot != 0)) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_MAGIC); tsk_error_set_errstr ("Invalid TSK_FS_TYPE_FAT32 image (numroot != 0)"); if (tsk_verbose) fprintf(stderr, "%s: numroom != 0 for FAT32\n", func_name); return 1; } if ((fatfs->fs_info.ftype != TSK_FS_TYPE_FAT32) && (fatfs->numroot == 0)) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_MAGIC); tsk_error_set_errstr ("Invalid FAT image (numroot == 0, and not TSK_FS_TYPE_FAT32)"); if (tsk_verbose) fprintf(stderr, "%s: numroom == 0 and not FAT32\n", func_name); return 1; } /* additional sanity checks if we think we are using the backup boot sector. * The scenario to prevent here is if fat_open is called 6 sectors before the real start * of the file system, then we want to detect that it was not a backup that we saw. */ if (fatfs->using_backup_boot_sector) { // only FAT32 has backup boot sectors.. if (fatfs->fs_info.ftype != TSK_FS_TYPE_FAT32) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_MAGIC); tsk_error_set_errstr ("Invalid FAT image (Used what we thought was a backup boot sector, but it is not TSK_FS_TYPE_FAT32)"); if (tsk_verbose) fprintf(stderr, "%s: Had to use backup boot sector, but this isn't FAT32\n", func_name); return 1; } if (fatfs->numroot > 1) { uint8_t buf1[512]; uint8_t buf2[512]; int i2; int numDiffs; ssize_t cnt = 0; cnt = tsk_fs_read(fs, fatfs->firstfatsect * fatfs->ssize, (char *) buf1, 512); if (cnt != 512) { if (cnt >= 0) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); } tsk_error_set_errstr2("%s: FAT1", func_name); fs->tag = 0; return 1; } cnt = tsk_fs_read(fs, (fatfs->firstfatsect + fatfs->sectperfat) * fatfs->ssize, (char *) buf2, 512); if (cnt != 512) { if (cnt >= 0) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_READ); } tsk_error_set_errstr2("%s: FAT2", func_name); fs->tag = 0; return 1; } numDiffs = 0; for (i2 = 0; i2 < 512; i2++) { if (buf1[i2] != buf2[i2]) { numDiffs++; } } if (numDiffs > 25) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_MAGIC); tsk_error_set_errstr ("Invalid FAT image (Too many differences between FATS from guessing (%d diffs))", numDiffs); if (tsk_verbose) fprintf(stderr, "%s: Too many differences in FAT from guessing (%d diffs)\n", func_name, numDiffs); return 1; } } } /* Set the mask to use on the cluster values */ if (fatfs->fs_info.ftype == TSK_FS_TYPE_FAT12) { fatfs->mask = FATFS_12_MASK; } else if (fatfs->fs_info.ftype == TSK_FS_TYPE_FAT16) { fatfs->mask = FATFS_16_MASK; } else if (fatfs->fs_info.ftype == TSK_FS_TYPE_FAT32) { fatfs->mask = FATFS_32_MASK; } else { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_ARG); tsk_error_set_errstr("Unknown FAT type in %s: %d\n", func_name, fatfs->fs_info.ftype); return 1; } fs->duname = "Sector"; /* the root directories are always after the FAT for TSK_FS_TYPE_FAT12 and TSK_FS_TYPE_FAT16, * but are dynamically located for TSK_FS_TYPE_FAT32 */ if (fatfs->fs_info.ftype == TSK_FS_TYPE_FAT32) fatfs->rootsect = FATFS_CLUST_2_SECT(fatfs, tsk_getu32(fs->endian, fatsb->a.f32.rootclust)); else fatfs->rootsect = fatfs->firstdatasect; for (i = 0; i < FATFS_FAT_CACHE_N; i++) { fatfs->fatc_addr[i] = 0; fatfs->fatc_ttl[i] = 0; } /* * block calculations : although there are no blocks in fat, we will * use these fields for sector calculations */ fs->first_block = 0; fs->block_count = sectors; fs->last_block = fs->last_block_act = fs->block_count - 1; fs->block_size = fatfs->ssize; // determine the last block we have in this image if ((TSK_DADDR_T) ((fatfs->fs_info.img_info->size - fatfs->fs_info.offset) / fs->block_size) < fs->block_count) fs->last_block_act = (fatfs->fs_info.img_info->size - fatfs->fs_info.offset) / fs->block_size - 1; /* * inode calculations */ /* maximum number of dentries in a sector & cluster */ fatfs->dentry_cnt_se = fatfs->ssize / sizeof(FATXXFS_DENTRY); fatfs->dentry_cnt_cl = fatfs->dentry_cnt_se * fatfs->csize; fs->root_inum = FATFS_ROOTINO; fs->first_inum = FATFS_FIRSTINO; /* Calculate inode addresses for the virtual files (MBR, one or two FATS) * and the virtual orphan files directory. */ fs->last_inum = (FATFS_SECT_2_INODE(fatfs, fs->last_block_act + 1) - 1) + FATFS_NUM_VIRT_FILES(fatfs); fatfs->mbr_virt_inum = fs->last_inum - FATFS_NUM_VIRT_FILES(fatfs) + 1; fatfs->fat1_virt_inum = fatfs->mbr_virt_inum + 1; if (fatfs->numfat == 2) { fatfs->fat2_virt_inum = fatfs->fat1_virt_inum + 1; } else { fatfs->fat2_virt_inum = fatfs->fat1_virt_inum; } /* Calculate the total number of inodes. */ fs->inum_count = fs->last_inum - fs->first_inum + 1; /* Volume ID */ for (fs->fs_id_used = 0; fs->fs_id_used < 4; fs->fs_id_used++) { if (fatfs->fs_info.ftype == TSK_FS_TYPE_FAT32) fs->fs_id[fs->fs_id_used] = fatsb->a.f32.vol_id[fs->fs_id_used]; else fs->fs_id[fs->fs_id_used] = fatsb->a.f16.vol_id[fs->fs_id_used]; } /* * Set the function pointers */ fs->block_walk = fatfs_block_walk; fs->block_getflags = fatfs_block_getflags; fs->inode_walk = fatfs_inode_walk; fs->istat = fatfs_istat; fs->file_add_meta = fatfs_inode_lookup; fs->get_default_attr_type = fatfs_get_default_attr_type; fs->load_attrs = fatfs_make_data_runs; fs->dir_open_meta = fatfs_dir_open_meta; fs->name_cmp = fatfs_name_cmp; fs->fsstat = fatxxfs_fsstat; fs->fscheck = fatfs_fscheck; fs->close = fatfs_close; fs->jblk_walk = fatfs_jblk_walk; fs->jentry_walk = fatfs_jentry_walk; fs->jopen = fatfs_jopen; fatfs->is_cluster_alloc = fatxxfs_is_cluster_alloc; fatfs->is_dentry = fatxxfs_is_dentry; fatfs->dinode_copy = fatxxfs_dinode_copy; fatfs->inode_lookup = fatxxfs_inode_lookup; fatfs->inode_walk_should_skip_dentry = fatxxfs_inode_walk_should_skip_dentry; fatfs->istat_attr_flags = fatxxfs_istat_attr_flags; fatfs->dent_parse_buf = fatxxfs_dent_parse_buf; // initialize the caches tsk_init_lock(&fatfs->cache_lock); tsk_init_lock(&fatfs->dir_lock); fatfs->inum2par = NULL; // Test to see if this is the odd Android case where the FAT entries have no short name // // If there are no entries found with the normal short name // and we find more entries by removing the short name test for allocated directories, then assume // this is the case where we have no short names fatfs->subtype = TSK_FATFS_SUBTYPE_SPEC; test_dir1 = tsk_fs_dir_open_meta(fs, fs->root_inum); if (test_dir1 != NULL && test_dir1->names_used <= 4){ // At most four automatic directories ($MBR, $FAT1, $FAT1, $OrphanFiles) TSK_FS_DIR * test_dir2; // to see if it's the Android FAT version fatfs->subtype = TSK_FATFS_SUBTYPE_ANDROID_1; test_dir2 = tsk_fs_dir_open_meta(fs, fs->root_inum); if (test_dir2 != NULL && test_dir2->names_used > test_dir1->names_used){ fatfs->subtype = TSK_FATFS_SUBTYPE_ANDROID_1; } else{ fatfs->subtype = TSK_FATFS_SUBTYPE_SPEC; } tsk_fs_dir_close(test_dir2); } tsk_fs_dir_close(test_dir1); return 0; }