1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
/*
** blkcalc
** The Sleuth Kit
**
** Calculates the corresponding block number between 'blkls' and 'dd' images
** when given an 'blkls' block number, it determines the block number it
** had in a 'dd' image. When given a 'dd' image, it determines the
** value it would have in a 'blkls' image (if the block is unallocated)
**
** Brian Carrier [carrier <at> sleuthkit [dot] org]
** Copyright (c) 2006-2011 Brian Carrier, Basis Technology. All Rights reserved
** Copyright (c) 2003-2005 Brian Carrier. All Rights reserved
**
** TASK
** Copyright (c) 2002 Brian Carrier, @stake Inc. All Rights reserved
**
** TCTUTILs
** Copyright (c) 2001 Brian Carrier. All rights reserved
**
**
** This software is distributed under the Common Public License 1.0
**
*/
/**
* \file dcalc_lib.c
* Contains the library API functions used by the TSK blkcalc command
* line tool.
*/
#include "tsk_fs_i.h"
/** \internal
* Structure to store data for callbacks.
*/
typedef struct {
TSK_DADDR_T count;
TSK_DADDR_T uncnt;
uint8_t found;
TSK_OFF_T flen;
} BLKCALC_DATA;
/* function used when -d is given
**
** keeps a count of unallocated blocks seen thus far
**
** If the specified block is allocated, an error is given, else the
** count of unalloc blocks is given
**
** This is called for all blocks (alloc and unalloc)
*/
static TSK_WALK_RET_ENUM
count_dd_act(const TSK_FS_BLOCK * fs_block, void *ptr)
{
BLKCALC_DATA *data = (BLKCALC_DATA *) ptr;
if (fs_block->flags & TSK_FS_BLOCK_FLAG_UNALLOC)
data->uncnt++;
if (data->count-- == 0) {
if (fs_block->flags & TSK_FS_BLOCK_FLAG_UNALLOC)
tsk_printf("%" PRIuDADDR "\n", data->uncnt);
else
printf
("ERROR: unit is allocated, it will not be in an blkls image\n");
data->found = 1;
return TSK_WALK_STOP;
}
return TSK_WALK_CONT;
}
/*
** count how many unalloc blocks there are.
**
** This is called for unalloc blocks only
*/
static TSK_WALK_RET_ENUM
count_blkls_act(const TSK_FS_BLOCK * fs_block, void *ptr)
{
BLKCALC_DATA *data = (BLKCALC_DATA *) ptr;
if (data->count-- == 0) {
tsk_printf("%" PRIuDADDR "\n", fs_block->addr);
data->found = 1;
return TSK_WALK_STOP;
}
return TSK_WALK_CONT;
}
/* SLACK SPACE call backs */
static TSK_WALK_RET_ENUM
count_slack_file_act(TSK_FS_FILE * fs_file, TSK_OFF_T a_off,
TSK_DADDR_T addr, char *buf, size_t size, TSK_FS_BLOCK_FLAG_ENUM flags,
void *ptr)
{
BLKCALC_DATA *data = (BLKCALC_DATA *) ptr;
if (tsk_verbose)
tsk_fprintf(stderr,
"count_slack_file_act: Remaining File: %" PRIdOFF
" Buffer: %" PRIuSIZE "\n", data->flen, size);
/* This is not the last data unit, or the file has no slack */
if (data->flen >= (TSK_OFF_T)size) {
data->flen -= size;
}
else {
/* We have passed the end of the allocated space */
if (data->count-- == 0) {
tsk_printf("%" PRIuDADDR "\n", addr);
data->found = 1;
return TSK_WALK_STOP;
}
data->flen = 0; // for scenarios where last buffer had some unalloc
}
return TSK_WALK_CONT;
}
static TSK_WALK_RET_ENUM
count_slack_inode_act(TSK_FS_FILE * fs_file, void *ptr)
{
BLKCALC_DATA *data = (BLKCALC_DATA *) ptr;
if (tsk_verbose)
tsk_fprintf(stderr,
"count_slack_inode_act: Processing meta data: %" PRIuINUM
"\n", fs_file->meta->addr);
/* We will now do a file walk on the content */
if (TSK_FS_TYPE_ISNTFS(fs_file->fs_info->ftype) == 0) {
data->flen = fs_file->meta->size;
if (tsk_fs_file_walk(fs_file,
TSK_FS_FILE_WALK_FLAG_SLACK, count_slack_file_act, ptr)) {
/* ignore any errors */
if (tsk_verbose)
tsk_fprintf(stderr, "Error walking file %" PRIuINUM,
fs_file->meta->addr);
tsk_error_reset();
}
}
/* For NTFS we go through each non-resident attribute */
else {
int i, cnt;
cnt = tsk_fs_file_attr_getsize(fs_file);
for (i = 0; i < cnt; i++) {
const TSK_FS_ATTR *fs_attr =
tsk_fs_file_attr_get_idx(fs_file, i);
if (!fs_attr)
continue;
if (fs_attr->flags & TSK_FS_ATTR_NONRES) {
data->flen = fs_attr->size;
if (tsk_fs_file_walk_type(fs_file, fs_attr->type,
fs_attr->id, TSK_FS_FILE_WALK_FLAG_SLACK,
count_slack_file_act, ptr)) {
/* ignore any errors */
if (tsk_verbose)
tsk_fprintf(stderr,
"Error walking file %" PRIuINUM,
fs_file->meta->addr);
tsk_error_reset();
}
}
}
}
return TSK_WALK_CONT;
}
/* Return 1 if block is not found, 0 if it was found, and -1 on error */
int8_t
tsk_fs_blkcalc(TSK_FS_INFO * fs, TSK_FS_BLKCALC_FLAG_ENUM a_lclflags,
TSK_DADDR_T a_cnt)
{
BLKCALC_DATA data;
data.count = a_cnt;
data.uncnt = 0;
data.found = 0;
if (a_lclflags == TSK_FS_BLKCALC_BLKLS) {
if (tsk_fs_block_walk(fs, fs->first_block, fs->last_block,
(TSK_FS_BLOCK_WALK_FLAG_UNALLOC |
TSK_FS_BLOCK_WALK_FLAG_META |
TSK_FS_BLOCK_WALK_FLAG_CONT |
TSK_FS_BLOCK_WALK_FLAG_AONLY), count_blkls_act, &data))
return -1;
}
else if (a_lclflags == TSK_FS_BLKCALC_DD) {
if (tsk_fs_block_walk(fs, fs->first_block, fs->last_block,
(TSK_FS_BLOCK_WALK_FLAG_ALLOC |
TSK_FS_BLOCK_WALK_FLAG_UNALLOC |
TSK_FS_BLOCK_WALK_FLAG_META |
TSK_FS_BLOCK_WALK_FLAG_CONT |
TSK_FS_BLOCK_WALK_FLAG_AONLY), count_dd_act, &data))
return -1;
}
else if (a_lclflags == TSK_FS_BLKCALC_SLACK) {
if (fs->inode_walk(fs, fs->first_inum, fs->last_inum,
TSK_FS_META_FLAG_ALLOC, count_slack_inode_act, &data))
return -1;
}
if (data.found == 0) {
tsk_printf("Block too large\n");
return 1;
}
else {
return 0;
}
}
|