/** * Analyze the volume starting at byte offset 'start' and look * for a file system. When found, the files will be analyzed. * * @param img Disk image to be analyzed. * @param start Byte offset of volume starting location. * * @return 1 on error and 0 on success */ static uint8_t proc_fs(TSK_IMG_INFO * img_info, TSK_OFF_T start) { TSK_FS_INFO *fs_info; TSK_STACK *stack; /* Try it as a file system */ if ((fs_info = tsk_fs_open_img(img_info, start, TSK_FS_TYPE_DETECT)) == NULL) { fprintf(stderr, "Error opening file system in partition at offset %" PRIuOFF "\n", start); tsk_error_print(stderr); /* We could do some carving on the volume data at this point */ return 1; } // create a stack to prevent infinite loops stack = tsk_stack_create(); // Process the directories if (proc_dir(fs_info, stack, fs_info->root_inum, "")) { fprintf(stderr, "Error processing file system in partition at offset %" PRIuOFF "\n", start); tsk_fs_close(fs_info); return 1; } tsk_stack_free(stack); /* We could do some analysis of unallocated blocks at this point... */ tsk_fs_close(fs_info); return 0; }
/** \ingroup fslib * Walk the file names in a directory and obtain the details of the files via a callback. * * @param a_fs File system to analyze * @param a_addr Metadata address of the directory to analyze * @param a_flags Flags used during analysis * @param a_action Callback function that is called for each file name * @param a_ptr Pointer to data that is passed to the callback function each time * @returns 1 on error and 0 on success */ uint8_t tsk_fs_dir_walk(TSK_FS_INFO * a_fs, TSK_INUM_T a_addr, TSK_FS_DIR_WALK_FLAG_ENUM a_flags, TSK_FS_DIR_WALK_CB a_action, void *a_ptr) { DENT_DINFO dinfo; TSK_WALK_RET_ENUM retval; if ((a_fs == NULL) || (a_fs->tag != TSK_FS_INFO_TAG)) { tsk_error_set_errno(TSK_ERR_FS_ARG); tsk_error_set_errstr ("tsk_fs_dir_walk: called with NULL or unallocated structures"); return 1; } memset(&dinfo, 0, sizeof(DENT_DINFO)); if ((dinfo.stack_seen = tsk_stack_create()) == NULL) return 1; /* Sanity check on flags -- make sure at least one ALLOC is set */ if (((a_flags & TSK_FS_DIR_WALK_FLAG_ALLOC) == 0) && ((a_flags & TSK_FS_DIR_WALK_FLAG_UNALLOC) == 0)) { a_flags |= (TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC); } /* if the flags are right, we can collect info that may be needed * for an orphan walk. If the walk fails or stops, the code that * calls the action will clear this stuff. */ tsk_take_lock(&a_fs->list_inum_named_lock); if ((a_fs->list_inum_named == NULL) && (a_addr == a_fs->root_inum) && (a_flags & TSK_FS_DIR_WALK_FLAG_RECURSE)) { dinfo.save_inum_named = 1; } tsk_release_lock(&a_fs->list_inum_named_lock); retval = tsk_fs_dir_walk_lcl(a_fs, &dinfo, a_addr, a_flags, a_action, a_ptr); if (dinfo.save_inum_named == 1) { if (retval != TSK_WALK_CONT) { /* There was an error and we stopped early, so we should get * rid of the partial list we were making. */ tsk_list_free(dinfo.list_inum_named); dinfo.list_inum_named = NULL; } else { /* We finished the dir walk successfully, so reassign * ownership of the dinfo's list_inum_named to the shared * list_inum_named in TSK_FS_INFO, under a lock, if * another thread hasn't already done so. */ tsk_take_lock(&a_fs->list_inum_named_lock); if (a_fs->list_inum_named == NULL) { a_fs->list_inum_named = dinfo.list_inum_named; } else { tsk_list_free(dinfo.list_inum_named); } tsk_release_lock(&a_fs->list_inum_named_lock); dinfo.list_inum_named = NULL; } } tsk_stack_free(dinfo.stack_seen); if (retval == TSK_WALK_ERROR) return 1; else return 0; }