1 /*
2 ** The Sleuth Kit
3 **
4 ** Brian Carrier [carrier <at> sleuthkit [dot] org]
5 ** Copyright (c) 2006-2011 Brian Carrier, Basis Technology. All Rights reserved
6 ** Copyright (c) 2003-2005 Brian Carrier. All rights reserved
7 **
8 ** TASK
9 ** Copyright (c) 2002-2003 Brian Carrier, @stake Inc. All rights reserved
10 **
11 ** Copyright (c) 1997,1998,1999, International Business Machines
12 ** Corporation and others. All Rights Reserved.
13 */
14
15 /* TCT
16 * LICENSE
17 * This software is distributed under the IBM Public License.
18 * AUTHOR(S)
19 * Wietse Venema
20 * IBM T.J. Watson Research
21 * P.O. Box 704
22 * Yorktown Heights, NY 10598, USA
23 --*/
24
25 /**
26 * \file ffs.c
27 * Contains the internal TSK UFS / FFS file system functions
28 */
29
30 #include "tsk_fs_i.h"
31 #include "tsk_ffs.h"
32
33
34
35 /* ffs_group_load - load cylinder group descriptor info into cache
36 *
37 * Note: This routine assumes &ffs->lock is locked by the caller.
38 *
39 * return 1 on error and 0 on success
40 * */
41 static uint8_t
ffs_group_load(FFS_INFO * ffs,FFS_GRPNUM_T grp_num)42 ffs_group_load(FFS_INFO * ffs, FFS_GRPNUM_T grp_num)
43 {
44 TSK_DADDR_T addr;
45 TSK_FS_INFO *fs = (TSK_FS_INFO *) & ffs->fs_info;
46
47 /*
48 * Sanity check
49 */
50 if (grp_num >= ffs->groups_count) {
51 tsk_error_reset();
52 tsk_error_set_errno(TSK_ERR_FS_ARG);
53 tsk_error_set_errstr
54 ("ffs_group_load: invalid cylinder group number: %" PRI_FFSGRP
55 "", grp_num);
56 return 1;
57 }
58
59 /*
60 * Allocate/read cylinder group info on the fly. Trust that a cylinder
61 * group always fits within a logical disk block (as promised in the
62 * 4.4BSD <ufs/ffs/fs.h> include file).
63 */
64 if (ffs->grp_buf == NULL) {
65 if ((ffs->grp_buf = tsk_malloc(ffs->ffsbsize_b)) == NULL) {
66 return 1;
67 }
68 }
69
70 addr = cgtod_lcl(fs, ffs->fs.sb1, grp_num);
71 if (ffs->grp_addr != addr) {
72 ffs_cgd *cg;
73 ssize_t cnt;
74 cnt = tsk_fs_read_block(fs, addr, ffs->grp_buf, ffs->ffsbsize_b);
75 if (cnt != ffs->ffsbsize_b) {
76 if (cnt >= 0) {
77 tsk_error_reset();
78 tsk_error_set_errno(TSK_ERR_FS_READ);
79 }
80 tsk_error_set_errstr2("ffs_group_load: Group %" PRI_FFSGRP
81 " at %" PRIuDADDR, grp_num, addr);
82 return 1;
83 }
84 ffs->grp_addr = addr;
85
86 /* Perform a sanity check on the data to make sure offsets are in range */
87 cg = (ffs_cgd *) ffs->grp_buf;
88 if ((tsk_gets32(fs->endian, cg->cg_iusedoff) > (int)ffs->ffsbsize_b)
89 || (tsk_gets32(fs->endian, cg->cg_freeoff) > (int)ffs->ffsbsize_b)) {
90 tsk_error_reset();
91 tsk_error_set_errno(TSK_ERR_FS_CORRUPT);
92 tsk_error_set_errstr2("ffs_group_load: Group %" PRI_FFSGRP
93 " descriptor offsets too large at %" PRIuDADDR, grp_num,
94 addr);
95 return 1;
96 }
97 }
98
99 ffs->grp_num = grp_num;
100 return 0;
101 }
102
103
104 /*
105 * ffs_dinode_load - read disk inode and load the data into ffs_inode structure
106 *
107 * Return 0 on success and 1 on error
108 */
109 static uint8_t
ffs_dinode_load(FFS_INFO * ffs,TSK_INUM_T inum,ffs_inode * dino_buf)110 ffs_dinode_load(FFS_INFO * ffs, TSK_INUM_T inum, ffs_inode * dino_buf)
111 {
112 TSK_DADDR_T addr;
113 TSK_OFF_T offs;
114 TSK_FS_INFO *fs = (TSK_FS_INFO *) & ffs->fs_info;
115
116 /*
117 * Sanity check.
118 * Use last_num-1 to account for virtual Orphan directory in last_inum.
119 */
120 if (inum < fs->first_inum || inum > fs->last_inum - 1) {
121 tsk_error_reset();
122 tsk_error_set_errno(TSK_ERR_FS_INODE_NUM);
123 tsk_error_set_errstr("ffs_dinode_load: address: %" PRIuINUM, inum);
124 return 1;
125 }
126
127 /*
128 * Allocate/read the inode table buffer on the fly.
129 */
130
131 /* lock access to itbl_buf */
132 tsk_take_lock(&ffs->lock);
133
134 if (ffs->itbl_buf == NULL) {
135 if ((ffs->itbl_buf = tsk_malloc(ffs->ffsbsize_b)) == NULL) {
136 tsk_release_lock(&ffs->lock);
137 return 1;
138 }
139 }
140
141
142 /* UFS2 is different because it does not initialize all inodes
143 * when the file system is created. Therefore we need to check
144 * the group descriptor to find out if this is in the valid
145 * range
146 */
147 if (fs->ftype == TSK_FS_TYPE_FFS2) {
148 ffs_cgd2 *cg2;
149 FFS_GRPNUM_T grp_num;
150
151 if (dino_buf == NULL) {
152 tsk_release_lock(&ffs->lock);
153 return 1;
154 }
155
156 /* Lookup the cylinder group descriptor if it isn't
157 * cached
158 */
159 grp_num = (FFS_GRPNUM_T) itog_lcl(fs, ffs->fs.sb1, inum);
160 if (ffs_group_load(ffs, grp_num)) {
161 tsk_release_lock(&ffs->lock);
162 return 1;
163 }
164
165 cg2 = (ffs_cgd2 *) ffs->grp_buf;
166
167 /* If the inode is not init, then do not worry about it */
168 if ((inum - grp_num * tsk_getu32(fs->endian,
169 ffs->fs.sb2->cg_inode_num)) >= tsk_getu32(fs->endian,
170 cg2->cg_initediblk)) {
171 memset((char *) dino_buf, 0, sizeof(ffs_inode2));
172 }
173
174 else {
175 /* Get the base and offset addr for the inode in the tbl */
176 addr = itod_lcl(fs, ffs->fs.sb1, inum);
177
178 if (ffs->itbl_addr != addr) {
179 ssize_t cnt;
180 cnt = tsk_fs_read_block
181 (fs, addr, ffs->itbl_buf, ffs->ffsbsize_b);
182 if (cnt != ffs->ffsbsize_b) {
183 tsk_release_lock(&ffs->lock);
184 if (cnt >= 0) {
185 tsk_error_reset();
186 tsk_error_set_errno(TSK_ERR_FS_READ);
187 }
188 tsk_error_set_errstr2
189 ("ffs_dinode_load: FFS2 inode table at %"
190 PRIuDADDR, addr);
191 return 1;
192 }
193 ffs->itbl_addr = addr;
194 }
195
196 offs = itoo_lcl(fs, ffs->fs.sb2, inum) * sizeof(ffs_inode2);
197
198 memcpy((char *) dino_buf, ffs->itbl_buf + offs,
199 sizeof(ffs_inode2));
200 }
201 }
202 else {
203 if (dino_buf == NULL) {
204 tsk_release_lock(&ffs->lock);
205 return 1;
206 }
207
208 addr = itod_lcl(fs, ffs->fs.sb1, inum);
209 if (ffs->itbl_addr != addr) {
210 ssize_t cnt;
211 cnt =
212 tsk_fs_read_block(fs, addr, ffs->itbl_buf,
213 ffs->ffsbsize_b);
214 if (cnt != ffs->ffsbsize_b) {
215 tsk_release_lock(&ffs->lock);
216 if (cnt >= 0) {
217 tsk_error_reset();
218 tsk_error_set_errno(TSK_ERR_FS_READ);
219 }
220 tsk_error_set_errstr2
221 ("ffs_dinode_load: FFS1 inode table at %" PRIuDADDR,
222 addr);
223 return 1;
224 }
225 ffs->itbl_addr = addr;
226 }
227
228 offs = itoo_lcl(fs, ffs->fs.sb1, inum) * sizeof(ffs_inode1);
229
230 memcpy((char *) dino_buf, ffs->itbl_buf + offs,
231 sizeof(ffs_inode1));
232 }
233
234 tsk_release_lock(&ffs->lock);
235
236 return 0;
237 }
238
239
240 static TSK_FS_META_TYPE_ENUM
ffsmode2tsktype(uint16_t a_mode)241 ffsmode2tsktype(uint16_t a_mode)
242 {
243 switch (a_mode & FFS_IN_FMT) {
244 case FFS_IN_REG:
245 return TSK_FS_META_TYPE_REG;
246 case FFS_IN_DIR:
247 return TSK_FS_META_TYPE_DIR;
248 case FFS_IN_SOCK:
249 return TSK_FS_META_TYPE_SOCK;
250 case FFS_IN_LNK:
251 return TSK_FS_META_TYPE_LNK;
252 case FFS_IN_BLK:
253 return TSK_FS_META_TYPE_BLK;
254 case FFS_IN_CHR:
255 return TSK_FS_META_TYPE_CHR;
256 case FFS_IN_FIFO:
257 return TSK_FS_META_TYPE_FIFO;
258 case FFS_IN_SHAD:
259 return TSK_FS_META_TYPE_SHAD;
260 case FFS_IN_WHT:
261 return TSK_FS_META_TYPE_WHT;
262 default:
263 return TSK_FS_META_TYPE_UNDEF;
264 }
265 }
266
267 static uint16_t
ffsmode2tskmode(uint16_t a_mode)268 ffsmode2tskmode(uint16_t a_mode)
269 {
270 uint16_t mode = 0;
271
272 if (a_mode & FFS_IN_ISUID)
273 mode |= TSK_FS_META_MODE_ISUID;
274 if (a_mode & FFS_IN_ISGID)
275 mode |= TSK_FS_META_MODE_ISGID;
276 if (a_mode & FFS_IN_ISVTX)
277 mode |= TSK_FS_META_MODE_ISVTX;
278
279 if (a_mode & FFS_IN_IRUSR)
280 mode |= TSK_FS_META_MODE_IRUSR;
281 if (a_mode & FFS_IN_IWUSR)
282 mode |= TSK_FS_META_MODE_IWUSR;
283 if (a_mode & FFS_IN_IXUSR)
284 mode |= TSK_FS_META_MODE_IXUSR;
285
286 if (a_mode & FFS_IN_IRGRP)
287 mode |= TSK_FS_META_MODE_IRGRP;
288 if (a_mode & FFS_IN_IWGRP)
289 mode |= TSK_FS_META_MODE_IWGRP;
290 if (a_mode & FFS_IN_IXGRP)
291 mode |= TSK_FS_META_MODE_IXGRP;
292
293 if (a_mode & FFS_IN_IROTH)
294 mode |= TSK_FS_META_MODE_IROTH;
295 if (a_mode & FFS_IN_IWOTH)
296 mode |= TSK_FS_META_MODE_IWOTH;
297 if (a_mode & FFS_IN_IXOTH)
298 mode |= TSK_FS_META_MODE_IXOTH;
299
300 return mode;
301 }
302
303 /* ffs_dinode_copy - copy cached disk inode to generic inode
304 *
305 * Return 1 on error and 0 on success
306 */
307 static uint8_t
ffs_dinode_copy(FFS_INFO * ffs,TSK_FS_META * fs_meta,TSK_INUM_T dino_inum,const ffs_inode * dino_buf)308 ffs_dinode_copy(FFS_INFO * ffs, TSK_FS_META * fs_meta,
309 TSK_INUM_T dino_inum, const ffs_inode * dino_buf)
310 {
311 int i, j;
312 unsigned int count;
313 TSK_FS_INFO *fs = &(ffs->fs_info);
314 FFS_GRPNUM_T grp_num;
315 ffs_cgd *cg;
316 unsigned char *inosused = NULL;
317 TSK_INUM_T ibase;
318
319 if (dino_buf == NULL) {
320 tsk_error_reset();
321 tsk_error_set_errno(TSK_ERR_FS_ARG);
322 tsk_error_set_errstr("ffs_dinode_copy: dino_buf is NULL");
323 return 1;
324 }
325
326 fs_meta->attr_state = TSK_FS_META_ATTR_EMPTY;
327 if (fs_meta->attr) {
328 tsk_fs_attrlist_markunused(fs_meta->attr);
329 }
330
331 fs_meta->flags = 0;
332 fs_meta->seq = 0;
333
334 /* If the symlink field is set from a previous run, then free it */
335 if (fs_meta->link) {
336 free(fs_meta->link);
337 fs_meta->link = NULL;
338 }
339
340 fs_meta->addr = dino_inum;
341
342 /* OpenBSD and FreeBSD style */
343 if (fs->ftype == TSK_FS_TYPE_FFS1) {
344 ffs_inode1 *in = (ffs_inode1 *) dino_buf;
345 TSK_DADDR_T *addr_ptr;
346
347 fs_meta->mode =
348 ffsmode2tskmode(tsk_getu16(fs->endian, in->di_mode));
349 fs_meta->type =
350 ffsmode2tsktype(tsk_getu16(fs->endian, in->di_mode));
351
352 fs_meta->nlink = tsk_gets16(fs->endian, in->di_nlink);
353 fs_meta->size = tsk_getu64(fs->endian, in->di_size);
354 fs_meta->uid = tsk_getu32(fs->endian, in->di_uid);
355 fs_meta->gid = tsk_getu32(fs->endian, in->di_gid);
356
357 fs_meta->mtime = tsk_gets32(fs->endian, in->di_mtime);
358 fs_meta->atime = tsk_gets32(fs->endian, in->di_atime);
359 fs_meta->ctime = tsk_gets32(fs->endian, in->di_ctime);
360 fs_meta->crtime = 0;
361 fs_meta->mtime_nano = fs_meta->atime_nano = fs_meta->ctime_nano =
362 fs_meta->crtime_nano = 0;
363
364 if (fs_meta->content_len < FFS_FILE_CONTENT_LEN) {
365 if ((fs_meta =
366 tsk_fs_meta_realloc(fs_meta,
367 FFS_FILE_CONTENT_LEN)) == NULL) {
368 return 1;
369 }
370 }
371 addr_ptr = (TSK_DADDR_T *) fs_meta->content_ptr;
372
373 for (i = 0; i < FFS_NDADDR; i++)
374 addr_ptr[i] = tsk_gets32(fs->endian, in->di_db[i]);
375
376 for (i = 0; i < FFS_NIADDR; i++)
377 addr_ptr[FFS_NDADDR + i] =
378 tsk_gets32(fs->endian, in->di_ib[i]);
379
380
381 /* set the link string (if the file is a link)
382 * The size check is a sanity check so that we don't try and allocate
383 * a huge amount of memory for a bad inode value
384 */
385 if ((fs_meta->type == TSK_FS_META_TYPE_LNK)
386 && (fs_meta->size < FFS_MAXPATHLEN)
387 && (fs_meta->size >= 0)) {
388 int i;
389
390 fs_meta->link = tsk_malloc((size_t) fs_meta->size + 1);
391 if (fs_meta->link == NULL) {
392 return 1;
393 }
394
395 count = 0; /* index into the link array */
396
397 /* it is located directly in the pointers */
398 if (fs_meta->size < 4 * (FFS_NDADDR + FFS_NIADDR)) {
399 char *ptr;
400
401 /* Direct block pointer locations */
402 for (i = 0; i < FFS_NDADDR && count < fs_meta->size; i++) {
403 ptr = (char *) &in->di_db[i];
404 for (j = 0; j < 4 && count < fs_meta->size; j++)
405 fs_meta->link[count++] = ptr[j];
406 }
407
408 /* indirect block pointers */
409 for (i = 0; i < FFS_NIADDR && count < fs_meta->size; i++) {
410 ptr = (char *) &in->di_ib[i];
411 for (j = 0; j < 4 && count < fs_meta->size; j++)
412 fs_meta->link[count++] = ptr[j];
413 }
414
415 fs_meta->link[count] = '\0';
416
417 /* clear the values to avoid other code from reading them */
418 memset(fs_meta->content_ptr, 0, fs_meta->content_len);
419 }
420
421 /* it is in blocks (the regular way) */
422 else {
423 char *buf;
424 char *ptr = fs_meta->link;
425
426 if ((buf = (char *)
427 tsk_malloc(fs->block_size)) == NULL) {
428 return 1;
429 }
430
431 /* there is a max link length of 1000, so we should never
432 * need the indirect blocks
433 */
434 for (i = 0; i < FFS_NDADDR && count < fs_meta->size; i++) {
435 ssize_t cnt;
436 TSK_DADDR_T *addr_ptr =
437 (TSK_DADDR_T *) fs_meta->content_ptr;
438
439 /* Do we need the entire block, or just part of it? */
440 int read_count =
441 (fs_meta->size - count <
442 fs->block_size) ? (int) fs_meta->size -
443 count : fs->block_size;
444
445 cnt =
446 tsk_fs_read_block(fs, addr_ptr[i],
447 buf, fs->block_size);
448 if (cnt != fs->block_size) {
449 if (cnt >= 0) {
450 tsk_error_reset();
451 tsk_error_set_errno(TSK_ERR_FS_READ);
452 }
453 tsk_error_set_errstr2
454 ("ffs_dinode_copy: FFS1A symlink dest at %"
455 PRIuDADDR, addr_ptr[i]);
456 free(buf);
457 return 1;
458 }
459
460 memcpy(ptr, buf, read_count);
461 count += read_count;
462 ptr = (char *) ((uintptr_t) ptr + read_count);
463 }
464 /* terminate the string */
465 *ptr = '\0';
466
467 /* Clean up name */
468 i = 0;
469 while (fs_meta->link[i] != '\0') {
470 if (TSK_IS_CNTRL(fs_meta->link[i]))
471 fs_meta->link[i] = '^';
472 i++;
473 }
474
475 free(buf);
476 }
477 } /* end of symlink */
478 }
479 /* TSK_FS_TYPE_FFS1B - Solaris */
480 else if (fs->ftype == TSK_FS_TYPE_FFS1B) {
481 ffs_inode1b *in = (ffs_inode1b *) dino_buf;
482 TSK_DADDR_T *addr_ptr;
483
484 fs_meta->mode =
485 ffsmode2tskmode(tsk_getu16(fs->endian, in->di_mode));
486 fs_meta->type =
487 ffsmode2tsktype(tsk_getu16(fs->endian, in->di_mode));
488
489 fs_meta->nlink = tsk_gets16(fs->endian, in->di_nlink);
490 fs_meta->size = tsk_getu64(fs->endian, in->di_size);
491 fs_meta->uid = tsk_getu32(fs->endian, in->di_uid);
492 fs_meta->gid = tsk_getu32(fs->endian, in->di_gid);
493
494 fs_meta->mtime = tsk_gets32(fs->endian, in->di_mtime);
495 fs_meta->atime = tsk_gets32(fs->endian, in->di_atime);
496 fs_meta->ctime = tsk_gets32(fs->endian, in->di_ctime);
497 fs_meta->crtime = 0;
498 fs_meta->mtime_nano = fs_meta->atime_nano = fs_meta->ctime_nano =
499 fs_meta->crtime_nano = 0;
500
501 if (fs_meta->content_len < FFS_FILE_CONTENT_LEN) {
502 if ((fs_meta =
503 tsk_fs_meta_realloc(fs_meta,
504 FFS_FILE_CONTENT_LEN)) == NULL) {
505 return 1;
506 }
507 }
508 addr_ptr = (TSK_DADDR_T *) fs_meta->content_ptr;
509
510 for (i = 0; i < FFS_NDADDR; i++)
511 addr_ptr[i] = tsk_gets32(fs->endian, in->di_db[i]);
512
513 for (i = 0; i < FFS_NIADDR; i++)
514 addr_ptr[FFS_NDADDR + i] =
515 tsk_gets32(fs->endian, in->di_ib[i]);
516
517 if ((fs_meta->type == TSK_FS_META_TYPE_LNK)
518 && (fs_meta->size < FFS_MAXPATHLEN)
519 && (fs_meta->size >= 0)) {
520
521 count = 0; /* index into the link array */
522
523 /* it is located directly in the pointers */
524 if (fs_meta->size < 4 * (FFS_NDADDR + FFS_NIADDR)) {
525 char *ptr;
526
527 /* Direct block pointer locations */
528 for (i = 0; i < FFS_NDADDR && count < fs_meta->size; i++) {
529 ptr = (char *) &in->di_db[i];
530 for (j = 0; j < 4 && count < fs_meta->size; j++)
531 fs_meta->link[count++] = ptr[j];
532 }
533
534 /* indirect block pointers */
535 for (i = 0; i < FFS_NIADDR && count < fs_meta->size; i++) {
536 ptr = (char *) &in->di_ib[i];
537 for (j = 0; j < 4 && count < fs_meta->size; j++)
538 fs_meta->link[count++] = ptr[j];
539 }
540
541 fs_meta->link[count] = '\0';
542
543 /* clear the values to avoid other code from reading them */
544 memset(fs_meta->content_ptr, 0, fs_meta->content_len);
545 }
546
547 /* it is in blocks (the regular way) */
548 else {
549 char *buf;
550 char *ptr;
551
552 if ((buf = (char *)
553 tsk_malloc(fs->block_size)) == NULL)
554 return 1;
555
556 fs_meta->link = ptr =
557 tsk_malloc((size_t) fs_meta->size + 1);
558 if (fs_meta->link == NULL) {
559 free(buf);
560 return 1;
561 }
562
563 /* there is a max link length of 1000, so we should never
564 * need the indirect blocks
565 */
566 for (i = 0; i < FFS_NDADDR && count < fs_meta->size; i++) {
567 ssize_t cnt;
568 TSK_DADDR_T *addr_ptr =
569 (TSK_DADDR_T *) fs_meta->content_ptr;
570
571 /* Do we need the entire block, or just part of it? */
572 int read_count =
573 (fs_meta->size - count <
574 fs->block_size) ? (int) fs_meta->size -
575 count : fs->block_size;
576
577 cnt =
578 tsk_fs_read_block(fs, addr_ptr[i],
579 buf, fs->block_size);
580 if (cnt != fs->block_size) {
581 if (cnt >= 0) {
582 tsk_error_reset();
583 tsk_error_set_errno(TSK_ERR_FS_READ);
584 }
585 tsk_error_set_errstr2
586 ("ffs_dinode_copy: FFS1B symlink dest at %"
587 PRIuDADDR, addr_ptr[i]);
588 free(buf);
589 return 1;
590 }
591
592 memcpy(ptr, buf, read_count);
593 count += read_count;
594 ptr = (char *) ((uintptr_t) ptr + read_count);
595 }
596
597 /* terminate the string */
598 *ptr = '\0';
599
600 free(buf);
601 }
602 }
603 }
604 else if (fs->ftype == TSK_FS_TYPE_FFS2) {
605 ffs_inode2 *in = (ffs_inode2 *) dino_buf;
606 TSK_DADDR_T *addr_ptr;
607
608 fs_meta->mode =
609 ffsmode2tskmode(tsk_getu16(fs->endian, in->di_mode));
610 fs_meta->type =
611 ffsmode2tsktype(tsk_getu16(fs->endian, in->di_mode));
612
613 fs_meta->nlink = tsk_gets16(fs->endian, in->di_nlink);
614 fs_meta->size = tsk_getu64(fs->endian, in->di_size);
615 fs_meta->uid = tsk_getu32(fs->endian, in->di_uid);
616 fs_meta->gid = tsk_getu32(fs->endian, in->di_gid);
617
618 fs_meta->mtime = (time_t) tsk_gets64(fs->endian, in->di_mtime);
619 fs_meta->atime = (time_t) tsk_gets64(fs->endian, in->di_atime);
620 fs_meta->ctime = (time_t) tsk_gets64(fs->endian, in->di_ctime);
621 fs_meta->crtime = 0;
622 fs_meta->mtime_nano = tsk_getu32(fs->endian, in->di_mtimensec);
623 fs_meta->atime_nano = tsk_getu32(fs->endian, in->di_atimensec);
624 fs_meta->ctime_nano = tsk_getu32(fs->endian, in->di_ctimensec);
625 fs_meta->crtime_nano = tsk_getu32(fs->endian, in->di_crtimensec);
626
627 if (fs_meta->content_len < FFS_FILE_CONTENT_LEN) {
628 if ((fs_meta =
629 tsk_fs_meta_realloc(fs_meta,
630 FFS_FILE_CONTENT_LEN)) == NULL) {
631 return 1;
632 }
633 }
634 addr_ptr = (TSK_DADDR_T *) fs_meta->content_ptr;
635
636 for (i = 0; i < FFS_NDADDR; i++)
637 addr_ptr[i] = tsk_gets64(fs->endian, in->di_db[i]);
638
639 for (i = 0; i < FFS_NIADDR; i++)
640 addr_ptr[FFS_NDADDR + i] =
641 tsk_gets64(fs->endian, in->di_ib[i]);
642
643
644 /* set the link string (if the file is a link)
645 * The size check is a sanity check so that we don't try and allocate
646 * a huge amount of memory for a bad inode value
647 */
648 if ((fs_meta->type == TSK_FS_META_TYPE_LNK)
649 && (fs_meta->size < FFS_MAXPATHLEN)
650 && (fs_meta->size >= 0)) {
651
652 fs_meta->link = tsk_malloc((size_t) fs_meta->size + 1);
653 if (fs_meta->link == NULL) {
654 return 1;
655 }
656
657 count = 0; /* index into the link array */
658
659 /* it is located directly in the pointers
660 * Only the new style inode has this "fast link"
661 */
662 if (fs_meta->size < 8 * (FFS_NDADDR + FFS_NIADDR)) {
663 char *ptr;
664
665 /* Direct block pointer locations */
666 for (i = 0; i < FFS_NDADDR && count < fs_meta->size; i++) {
667 ptr = (char *) &in->di_db[i];
668 for (j = 0; j < 8 && count < fs_meta->size; j++)
669 fs_meta->link[count++] = ptr[j];
670 }
671
672 /* indirect block pointers */
673 for (i = 0; i < FFS_NIADDR && count < fs_meta->size; i++) {
674 ptr = (char *) &in->di_ib[i];
675 for (j = 0; j < 8 && count < fs_meta->size; j++)
676 fs_meta->link[count++] = ptr[j];
677 }
678
679 fs_meta->link[count] = '\0';
680
681 /* clear the values to avoid other code from reading them */
682 memset(fs_meta->content_ptr, 0, fs_meta->content_len);
683 }
684
685 /* it is in blocks (the regular way) */
686 else {
687 char *buf;
688 char *ptr = fs_meta->link;
689
690 if ((buf = (char *)
691 tsk_malloc(fs->block_size)) == NULL) {
692 return 1;
693 }
694
695 /* there is a max link length of 1000, so we should never
696 * need the indirect blocks
697 */
698 for (i = 0; i < FFS_NDADDR && count < fs_meta->size; i++) {
699 ssize_t cnt;
700 TSK_DADDR_T *addr_ptr = fs_meta->content_ptr;
701
702 /* Do we need the entire block, or just part of it? */
703 int read_count =
704 (fs_meta->size - count <
705 fs->block_size) ? (int) fs_meta->size -
706 count : fs->block_size;
707
708 cnt = tsk_fs_read_block(fs,
709 addr_ptr[i], buf, fs->block_size);
710 if (cnt != fs->block_size) {
711 if (cnt >= 0) {
712 tsk_error_reset();
713 tsk_error_set_errno(TSK_ERR_FS_READ);
714 }
715 tsk_error_set_errstr2
716 ("ffs_dinode_copy: FFS2 symlink dest at %"
717 PRIuDADDR, addr_ptr[i]);
718 free(buf);
719 return 1;
720 }
721
722 memcpy(ptr, buf, read_count);
723 count += read_count;
724 ptr = (char *) ((uintptr_t) ptr + read_count);
725 }
726 /* terminate the string */
727 *ptr = '\0';
728
729 free(buf);
730 }
731 } /* end of symlink */
732 }
733 else {
734 tsk_error_reset();
735 tsk_error_set_errno(TSK_ERR_FS_ARG);
736 tsk_error_set_errstr("ffs_dinode_copy: Unknown FFS Type");
737 return 1;
738 }
739
740 /* set the flags */
741 grp_num = (FFS_GRPNUM_T) itog_lcl(fs, ffs->fs.sb1, dino_inum);
742
743 tsk_take_lock(&ffs->lock);
744 if (ffs_group_load(ffs, grp_num)) {
745 tsk_release_lock(&ffs->lock);
746 return 1;
747 }
748
749 cg = (ffs_cgd *) ffs->grp_buf;
750
751 inosused = (unsigned char *) cg_inosused_lcl(fs, cg);
752 ibase = grp_num * tsk_gets32(fs->endian, ffs->fs.sb1->cg_inode_num);
753
754 /* get the alloc flag */
755 fs_meta->flags = (isset(inosused, dino_inum - ibase) ?
756 TSK_FS_META_FLAG_ALLOC : TSK_FS_META_FLAG_UNALLOC);
757
758 tsk_release_lock(&ffs->lock);
759
760 /* used/unused */
761 fs_meta->flags |= (fs_meta->ctime ?
762 TSK_FS_META_FLAG_USED : TSK_FS_META_FLAG_UNUSED);
763
764 return 0;
765 }
766
767
768
769
770 /* ffs_inode_lookup - lookup inode, external interface
771 *
772 * Return 1 on error
773 *
774 * */
775 static uint8_t
ffs_inode_lookup(TSK_FS_INFO * fs,TSK_FS_FILE * a_fs_file,TSK_INUM_T inum)776 ffs_inode_lookup(TSK_FS_INFO * fs, TSK_FS_FILE * a_fs_file,
777 TSK_INUM_T inum)
778 {
779 ffs_inode *dino_buf;
780 FFS_INFO *ffs = (FFS_INFO *) fs;
781
782 if (a_fs_file == NULL) {
783 tsk_error_set_errno(TSK_ERR_FS_ARG);
784 tsk_error_set_errstr("ffs_inode_lookup: fs_file is NULL");
785 return 1;
786 }
787
788 /* copy it to the TSK_FS_META structure */
789 if (a_fs_file->meta == NULL) {
790 a_fs_file->meta = tsk_fs_meta_alloc(FFS_FILE_CONTENT_LEN);
791 if (a_fs_file->meta == NULL)
792 return 1;
793 }
794 else {
795 tsk_fs_meta_reset(a_fs_file->meta);
796 }
797
798 // see if they are looking for the special "orphans" directory
799 if (inum == TSK_FS_ORPHANDIR_INUM(fs)) {
800 if (tsk_fs_dir_make_orphan_dir_meta(fs, a_fs_file->meta))
801 return 1;
802 else
803 return 0;
804 }
805
806 /* Lookup the inode and store it in ffs */
807 if ((dino_buf = (ffs_inode *) tsk_malloc(sizeof(ffs_inode2))) == NULL)
808 return 1;
809
810 if (ffs_dinode_load(ffs, inum, dino_buf)) {
811 free(dino_buf);
812 return 1;
813 }
814
815 if (ffs_dinode_copy(ffs, a_fs_file->meta, inum, dino_buf)) {
816 free(dino_buf);
817 return 1;
818 }
819
820 free(dino_buf);
821
822 return 0;
823 }
824
825
826
827 /**************************************************************************
828 *
829 * INODE WALKING
830 *
831 **************************************************************************/
832
833
834
835 /* ffs_inode_walk - inode iterator
836 *
837 * flags used: TSK_FS_META_FLAG_USED, TSK_FS_META_FLAG_UNUSED,
838 * TSK_FS_META_FLAG_ALLOC, TSK_FS_META_FLAG_UNALLOC, TSK_FS_META_FLAG_ORPHAN
839 *
840 * return 1 on error and 0 on success
841 */
842 uint8_t
ffs_inode_walk(TSK_FS_INFO * fs,TSK_INUM_T start_inum,TSK_INUM_T end_inum,TSK_FS_META_FLAG_ENUM a_flags,TSK_FS_META_WALK_CB action,void * ptr)843 ffs_inode_walk(TSK_FS_INFO * fs, TSK_INUM_T start_inum,
844 TSK_INUM_T end_inum, TSK_FS_META_FLAG_ENUM a_flags,
845 TSK_FS_META_WALK_CB action, void *ptr)
846 {
847 char *myname = "ffs_inode_walk";
848 FFS_INFO *ffs = (FFS_INFO *) fs;
849 ffs_cgd *cg = NULL;
850 TSK_INUM_T inum;
851 unsigned char *inosused = NULL;
852 TSK_FS_FILE *fs_file;
853 unsigned int myflags;
854 TSK_INUM_T ibase = 0;
855 TSK_INUM_T end_inum_tmp;
856 ffs_inode *dino_buf;
857
858 // clean up any error messages that are lying around
859 tsk_error_reset();
860
861 /*
862 * Sanity checks.
863 */
864 if (start_inum < fs->first_inum || start_inum > fs->last_inum) {
865 tsk_error_reset();
866 tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
867 tsk_error_set_errstr("%s: Start inode: %" PRIuINUM "", myname,
868 start_inum);
869 return 1;
870 }
871 else if (end_inum < fs->first_inum || end_inum > fs->last_inum
872 || end_inum < start_inum) {
873 tsk_error_reset();
874 tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
875 tsk_error_set_errstr("%s: End inode: %" PRIuINUM "", myname,
876 end_inum);
877 return 1;
878 }
879
880 /* If ORPHAN is wanted, then make sure that the flags are correct */
881 if (a_flags & TSK_FS_META_FLAG_ORPHAN) {
882 a_flags |= TSK_FS_META_FLAG_UNALLOC;
883 a_flags &= ~TSK_FS_META_FLAG_ALLOC;
884 a_flags |= TSK_FS_META_FLAG_USED;
885 a_flags &= ~TSK_FS_META_FLAG_UNUSED;
886 }
887 else {
888 if (((a_flags & TSK_FS_META_FLAG_ALLOC) == 0) &&
889 ((a_flags & TSK_FS_META_FLAG_UNALLOC) == 0)) {
890 a_flags |= (TSK_FS_META_FLAG_ALLOC | TSK_FS_META_FLAG_UNALLOC);
891 }
892
893 /* If neither of the USED or UNUSED flags are set, then set them
894 * both
895 */
896 if (((a_flags & TSK_FS_META_FLAG_USED) == 0) &&
897 ((a_flags & TSK_FS_META_FLAG_UNUSED) == 0)) {
898 a_flags |= (TSK_FS_META_FLAG_USED | TSK_FS_META_FLAG_UNUSED);
899 }
900 }
901
902
903
904 /* If we are looking for orphan files and have not yet filled
905 * in the list of unalloc inodes that are pointed to, then fill
906 * in the list
907 * */
908 if ((a_flags & TSK_FS_META_FLAG_ORPHAN)) {
909 if (tsk_fs_dir_load_inum_named(fs) != TSK_OK) {
910 tsk_error_errstr2_concat
911 ("- ffs_inode_walk: identifying inodes allocated by file names");
912 return 1;
913 }
914 }
915
916 if ((fs_file = tsk_fs_file_alloc(fs)) == NULL)
917 return 1;
918
919 if ((fs_file->meta = tsk_fs_meta_alloc(FFS_FILE_CONTENT_LEN)) == NULL)
920 return 1;
921
922 // we need to handle fs->last_inum specially because it is for the
923 // virtual ORPHANS directory. Handle it outside of the loop.
924 if (end_inum == TSK_FS_ORPHANDIR_INUM(fs))
925 end_inum_tmp = end_inum - 1;
926 else
927 end_inum_tmp = end_inum;
928
929 if ((dino_buf = (ffs_inode *) tsk_malloc(sizeof(ffs_inode2))) == NULL)
930 return 1;
931
932 /*
933 * Iterate. This is easy because inode numbers are contiguous, unlike
934 * data blocks which are interleaved with cylinder group blocks.
935 */
936 for (inum = start_inum; inum <= end_inum_tmp; inum++) {
937 int retval;
938 FFS_GRPNUM_T grp_num;
939
940 /*
941 * Be sure to use the proper cylinder group data.
942 */
943 grp_num = itog_lcl(fs, ffs->fs.sb1, inum);
944
945 tsk_take_lock(&ffs->lock);
946 if (ffs_group_load(ffs, grp_num)) {
947 tsk_release_lock(&ffs->lock);
948 free(dino_buf);
949 return 1;
950 }
951 cg = (ffs_cgd *) ffs->grp_buf;
952 inosused = (unsigned char *) cg_inosused_lcl(fs, cg);
953 ibase =
954 grp_num * tsk_gets32(fs->endian, ffs->fs.sb1->cg_inode_num);
955
956 /*
957 * Apply the allocated/unallocated restriction.
958 */
959 myflags = (isset(inosused, inum - ibase) ?
960 TSK_FS_META_FLAG_ALLOC : TSK_FS_META_FLAG_UNALLOC);
961
962 tsk_release_lock(&ffs->lock);
963
964 if ((a_flags & myflags) != myflags)
965 continue;
966
967
968 if (ffs_dinode_load(ffs, inum, dino_buf)) {
969 tsk_fs_file_close(fs_file);
970 free(dino_buf);
971 return 1;
972 }
973
974
975 if ((fs->ftype == TSK_FS_TYPE_FFS1)
976 || (fs->ftype == TSK_FS_TYPE_FFS1B)) {
977 /* both inode forms are the same for the required fields */
978 ffs_inode1 *in1 = (ffs_inode1 *) dino_buf;
979
980 /*
981 * Apply the used/unused restriction.
982 */
983 myflags |= (tsk_gets32(fs->endian, in1->di_ctime) ?
984 TSK_FS_META_FLAG_USED : TSK_FS_META_FLAG_UNUSED);
985 if ((a_flags & myflags) != myflags)
986 continue;
987 }
988 else {
989 ffs_inode2 *in2 = (ffs_inode2 *) dino_buf;
990
991 /*
992 * Apply the used/unused restriction.
993 */
994 myflags |= (tsk_gets64(fs->endian, in2->di_ctime) ?
995 TSK_FS_META_FLAG_USED : TSK_FS_META_FLAG_UNUSED);
996 if ((a_flags & myflags) != myflags)
997 continue;
998 }
999
1000 /* If we want only orphans, then check if this
1001 * inode is in the seen list
1002 */
1003 if ((myflags & TSK_FS_META_FLAG_UNALLOC) &&
1004 (a_flags & TSK_FS_META_FLAG_ORPHAN) &&
1005 (tsk_fs_dir_find_inum_named(fs, inum))) {
1006 continue;
1007 }
1008
1009
1010 /*
1011 * Fill in a file system-independent inode structure and pass control
1012 * to the application.
1013 */
1014 if (ffs_dinode_copy(ffs, fs_file->meta, inum, dino_buf)) {
1015 tsk_fs_file_close(fs_file);
1016 free(dino_buf);
1017 return 1;
1018 }
1019
1020 retval = action(fs_file, ptr);
1021 if (retval == TSK_WALK_STOP) {
1022 tsk_fs_file_close(fs_file);
1023 free(dino_buf);
1024 return 0;
1025 }
1026 else if (retval == TSK_WALK_ERROR) {
1027 tsk_fs_file_close(fs_file);
1028 free(dino_buf);
1029 return 1;
1030 }
1031 }
1032
1033 // handle the virtual orphans folder if they asked for it
1034 if ((end_inum == TSK_FS_ORPHANDIR_INUM(fs))
1035 && (a_flags & TSK_FS_META_FLAG_ALLOC)
1036 && (a_flags & TSK_FS_META_FLAG_USED)) {
1037 int retval;
1038
1039 if (tsk_fs_dir_make_orphan_dir_meta(fs, fs_file->meta)) {
1040 tsk_fs_file_close(fs_file);
1041 free(dino_buf);
1042 return 1;
1043 }
1044 /* call action */
1045 retval = action(fs_file, ptr);
1046 if (retval == TSK_WALK_STOP) {
1047 tsk_fs_file_close(fs_file);
1048 free(dino_buf);
1049 return 0;
1050 }
1051 else if (retval == TSK_WALK_ERROR) {
1052 tsk_fs_file_close(fs_file);
1053 free(dino_buf);
1054 return 1;
1055 }
1056 }
1057
1058 /*
1059 * Cleanup.
1060 */
1061 tsk_fs_file_close(fs_file);
1062 free(dino_buf);
1063
1064 return 0;
1065 }
1066
1067
1068 TSK_FS_BLOCK_FLAG_ENUM
ffs_block_getflags(TSK_FS_INFO * a_fs,TSK_DADDR_T a_addr)1069 ffs_block_getflags(TSK_FS_INFO * a_fs, TSK_DADDR_T a_addr)
1070 {
1071 FFS_INFO *ffs = (FFS_INFO *) a_fs;
1072 FFS_GRPNUM_T grp_num;
1073 ffs_cgd *cg = 0;
1074 TSK_DADDR_T frag_base = 0;
1075 TSK_DADDR_T dblock_addr = 0; /* first data block in group */
1076 TSK_DADDR_T sblock_addr = 0; /* super block in group */
1077 unsigned char *freeblocks = NULL;
1078 int flags;
1079
1080 // sparse
1081 if (a_addr == 0)
1082 return TSK_FS_BLOCK_FLAG_CONT | TSK_FS_BLOCK_FLAG_ALLOC;
1083
1084 grp_num = dtog_lcl(a_fs, ffs->fs.sb1, a_addr);
1085
1086 tsk_take_lock(&ffs->lock);
1087 if (ffs_group_load(ffs, grp_num)) {
1088 tsk_release_lock(&ffs->lock);
1089 return 0;
1090 }
1091
1092 cg = (ffs_cgd *) ffs->grp_buf;
1093 freeblocks = (unsigned char *) cg_blksfree_lcl(a_fs, cg);
1094
1095 // get the base fragment for the group
1096 frag_base = cgbase_lcl(a_fs, ffs->fs.sb1, grp_num);
1097
1098 // address of first data block in group
1099 dblock_addr = cgdmin_lcl(a_fs, ffs->fs.sb1, grp_num);
1100
1101 // address of super block in group
1102 sblock_addr = cgsblock_lcl(a_fs, ffs->fs.sb1, grp_num);
1103
1104 /* get the flags for this fragment
1105 *
1106 * Beware: FFS stores file data in the blocks between the start of a
1107 * cylinder group and the start of its super block.
1108 */
1109 flags = (isset(freeblocks, a_addr - frag_base) ?
1110 TSK_FS_BLOCK_FLAG_UNALLOC : TSK_FS_BLOCK_FLAG_ALLOC);
1111
1112 tsk_release_lock(&ffs->lock);
1113
1114 if (a_addr >= sblock_addr && a_addr < dblock_addr)
1115 flags |= TSK_FS_BLOCK_FLAG_META;
1116 else
1117 flags |= TSK_FS_BLOCK_FLAG_CONT;
1118
1119 return flags;
1120 }
1121
1122 /**************************************************************************
1123 *
1124 * BLOCK WALKING
1125 *
1126 **************************************************************************/
1127
1128 /* ffs_block_walk - block iterator
1129 *
1130 * flags: TSK_FS_BLOCK_FLAG_ALLOC, TSK_FS_BLOCK_FLAG_UNALLOC, TSK_FS_BLOCK_FLAG_CONT,
1131 * TSK_FS_BLOCK_FLAG_META
1132 *
1133 * return 1 on error and 0 on success
1134 */
1135
1136 uint8_t
ffs_block_walk(TSK_FS_INFO * fs,TSK_DADDR_T a_start_blk,TSK_DADDR_T a_end_blk,TSK_FS_BLOCK_WALK_FLAG_ENUM a_flags,TSK_FS_BLOCK_WALK_CB action,void * ptr)1137 ffs_block_walk(TSK_FS_INFO * fs, TSK_DADDR_T a_start_blk,
1138 TSK_DADDR_T a_end_blk, TSK_FS_BLOCK_WALK_FLAG_ENUM a_flags,
1139 TSK_FS_BLOCK_WALK_CB action, void *ptr)
1140 {
1141 char *myname = "ffs_block_walk";
1142 FFS_INFO *ffs = (FFS_INFO *) fs;
1143 TSK_FS_BLOCK *fs_block;
1144 TSK_DADDR_T addr;
1145
1146 char *cache_blk_buf; // buffer used for local read cache
1147 TSK_DADDR_T cache_addr; // base address in local cache
1148 int cache_len_f; // amount of data read into cache (in fragments)
1149
1150 // clean up any error messages that are lying around
1151 tsk_error_reset();
1152
1153 /*
1154 * Sanity checks on input bounds
1155 */
1156 if (a_start_blk < fs->first_block || a_start_blk > fs->last_block) {
1157 tsk_error_reset();
1158 tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
1159 tsk_error_set_errstr("%s: Start block: %" PRIuDADDR "", myname,
1160 a_start_blk);
1161 return 1;
1162 }
1163
1164 if (a_end_blk < fs->first_block || a_end_blk > fs->last_block
1165 || a_end_blk < a_start_blk) {
1166 tsk_error_reset();
1167 tsk_error_set_errno(TSK_ERR_FS_WALK_RNG);
1168 tsk_error_set_errstr("%s: End block: %" PRIuDADDR "", myname,
1169 a_end_blk);
1170 return 1;
1171 }
1172
1173 /* Sanity check on flags -- make sure at least one ALLOC is set */
1174 if (((a_flags & TSK_FS_BLOCK_WALK_FLAG_ALLOC) == 0) &&
1175 ((a_flags & TSK_FS_BLOCK_WALK_FLAG_UNALLOC) == 0)) {
1176 a_flags |=
1177 (TSK_FS_BLOCK_WALK_FLAG_ALLOC |
1178 TSK_FS_BLOCK_WALK_FLAG_UNALLOC);
1179 }
1180 if (((a_flags & TSK_FS_BLOCK_WALK_FLAG_META) == 0) &&
1181 ((a_flags & TSK_FS_BLOCK_WALK_FLAG_CONT) == 0)) {
1182 a_flags |=
1183 (TSK_FS_BLOCK_WALK_FLAG_CONT | TSK_FS_BLOCK_WALK_FLAG_META);
1184 }
1185
1186
1187 /* Other initialization */
1188 if ((fs_block = tsk_fs_block_alloc(fs)) == NULL) {
1189 return 1;
1190 }
1191 if ((cache_blk_buf = tsk_malloc(ffs->ffsbsize_b)) == NULL) {
1192 return 1;
1193 }
1194 cache_len_f = 0;
1195 cache_addr = 0;
1196
1197 /* Cycle through the fragment range requested */
1198 for (addr = a_start_blk; addr <= a_end_blk; addr++) {
1199 int retval;
1200 size_t cache_offset = 0;
1201 int myflags = ffs_block_getflags(fs, addr);
1202
1203 if ((tsk_verbose) && (myflags & TSK_FS_BLOCK_FLAG_META)
1204 && (myflags & TSK_FS_BLOCK_FLAG_UNALLOC))
1205 tsk_fprintf(stderr,
1206 "impossible: unallocated meta block %" PRIuDADDR, addr);
1207
1208 // test if we should call the callback with this one
1209 if ((myflags & TSK_FS_BLOCK_FLAG_META)
1210 && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_META)))
1211 continue;
1212 else if ((myflags & TSK_FS_BLOCK_FLAG_CONT)
1213 && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_CONT)))
1214 continue;
1215 else if ((myflags & TSK_FS_BLOCK_FLAG_ALLOC)
1216 && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_ALLOC)))
1217 continue;
1218 else if ((myflags & TSK_FS_BLOCK_FLAG_UNALLOC)
1219 && (!(a_flags & TSK_FS_BLOCK_WALK_FLAG_UNALLOC)))
1220 continue;
1221
1222
1223 if ((a_flags & TSK_FS_BLOCK_WALK_FLAG_AONLY) == 0) {
1224 /* we read in block-sized chunks and cache the result for later
1225 * calls. See if this fragment is in our cache */
1226 if ((cache_len_f == 0) || (addr >= cache_addr + cache_len_f)) {
1227 ssize_t cnt;
1228 int frags;
1229
1230 /* Ideally, we want to read in block sized chunks, verify we can do that */
1231 frags = a_end_blk > addr + ffs->ffsbsize_f - 1 ?
1232 ffs->ffsbsize_f : a_end_blk + 1 - addr;
1233
1234 cnt =
1235 tsk_fs_read_block(fs, addr, cache_blk_buf,
1236 fs->block_size * frags);
1237 if (cnt != fs->block_size * frags) {
1238 if (cnt >= 0) {
1239 tsk_error_reset();
1240 tsk_error_set_errno(TSK_ERR_FS_READ);
1241 }
1242 tsk_error_set_errstr2("ffs_block_walk: Block %"
1243 PRIuDADDR, addr);
1244 tsk_fs_block_free(fs_block);
1245 free(cache_blk_buf);
1246 return 1;
1247 }
1248 cache_len_f = frags;
1249 cache_addr = addr;
1250 }
1251 cache_offset = (size_t) ((addr - cache_addr) * fs->block_size);
1252 }
1253
1254 if (a_flags & TSK_FS_BLOCK_WALK_FLAG_AONLY)
1255 myflags |= TSK_FS_BLOCK_FLAG_AONLY;
1256
1257 // call the callback
1258 tsk_fs_block_set(fs, fs_block, addr,
1259 myflags | TSK_FS_BLOCK_FLAG_RAW, &cache_blk_buf[cache_offset]);
1260 retval = action(fs_block, ptr);
1261 if (retval == TSK_WALK_STOP) {
1262 break;
1263 }
1264 else if (retval == TSK_WALK_ERROR) {
1265 tsk_fs_block_free(fs_block);
1266 free(cache_blk_buf);
1267 return 1;
1268 }
1269 }
1270
1271 /* Cleanup */
1272 tsk_fs_block_free(fs_block);
1273 free(cache_blk_buf);
1274 return 0;
1275 }
1276
1277
1278
1279 /*
1280 * return 1 on error and 0 on success
1281 */
1282 static uint8_t
ffs_fscheck(TSK_FS_INFO * fs,FILE * hFile)1283 ffs_fscheck(TSK_FS_INFO * fs, FILE * hFile)
1284 {
1285 tsk_error_reset();
1286 tsk_error_set_errno(TSK_ERR_FS_UNSUPFUNC);
1287 tsk_error_set_errstr("fscheck not implemented for ffs yet");
1288 return 1;
1289 }
1290
1291
1292 /**
1293 * Print details about the file system to a file handle.
1294 *
1295 * @param fs File system to print details on
1296 * @param hFile File handle to print text to
1297 *
1298 * @returns 1 on error and 0 on success
1299 */
1300 static uint8_t
ffs_fsstat(TSK_FS_INFO * fs,FILE * hFile)1301 ffs_fsstat(TSK_FS_INFO * fs, FILE * hFile)
1302 {
1303 unsigned int i;
1304 time_t tmptime;
1305 ffs_csum1 *csum1 = NULL;
1306 ffs_cgd *cgd = NULL;
1307
1308 FFS_INFO *ffs = (FFS_INFO *) fs;
1309 ffs_sb1 *sb1 = ffs->fs.sb1;
1310 ffs_sb2 *sb2 = ffs->fs.sb2;
1311 int flags;
1312 char timeBuf[128];
1313
1314 // clean up any error messages that are lying around
1315 tsk_error_reset();
1316
1317 tsk_fprintf(hFile, "FILE SYSTEM INFORMATION\n");
1318 tsk_fprintf(hFile, "--------------------------------------------\n");
1319
1320 if ((fs->ftype == TSK_FS_TYPE_FFS1)
1321 || (fs->ftype == TSK_FS_TYPE_FFS1B)) {
1322 tsk_fprintf(hFile, "File System Type: UFS 1\n");
1323 tmptime = tsk_getu32(fs->endian, sb1->wtime);
1324 tsk_fprintf(hFile, "Last Written: %s\n",
1325 (tmptime > 0) ? tsk_fs_time_to_str(tmptime,
1326 timeBuf) : "empty");
1327 tsk_fprintf(hFile, "Last Mount Point: %s\n", sb1->last_mnt);
1328
1329 flags = sb1->fs_flags;
1330 }
1331 else {
1332 tsk_fprintf(hFile, "File System Type: UFS 2\n");
1333 tmptime = tsk_getu32(fs->endian, sb2->wtime);
1334 tsk_fprintf(hFile, "Last Written: %s\n",
1335 (tmptime > 0) ? tsk_fs_time_to_str(tmptime,
1336 timeBuf) : "empty");
1337 tsk_fprintf(hFile, "Last Mount Point: %s\n", sb2->last_mnt);
1338 tsk_fprintf(hFile, "Volume Name: %s\n", sb2->volname);
1339 tsk_fprintf(hFile, "System UID: %" PRIu64 "\n",
1340 tsk_getu64(fs->endian, sb2->swuid));
1341 flags = tsk_getu32(fs->endian, sb2->fs_flags);
1342 }
1343
1344 if (flags) {
1345 int cnt = 0;
1346
1347 tsk_fprintf(hFile, "Flags: ");
1348
1349 if (flags & FFS_SB_FLAG_UNCLEAN)
1350 tsk_fprintf(hFile, "%s Unclean", (cnt++ == 0 ? "" : ","));
1351
1352 if (flags & FFS_SB_FLAG_SOFTDEP)
1353 tsk_fprintf(hFile, "%s Soft Dependencies",
1354 (cnt++ == 0 ? "" : ","));
1355
1356 if (flags & FFS_SB_FLAG_NEEDFSCK)
1357 tsk_fprintf(hFile, "%s Needs fsck", (cnt++ == 0 ? "" : ","));
1358
1359 if (flags & FFS_SB_FLAG_INDEXDIR)
1360 tsk_fprintf(hFile, "%s Index directories",
1361 (cnt++ == 0 ? "" : ","));
1362
1363 if (flags & FFS_SB_FLAG_ACL)
1364 tsk_fprintf(hFile, "%s ACLs", (cnt++ == 0 ? "" : ","));
1365
1366 if (flags & FFS_SB_FLAG_MULTILABEL)
1367 tsk_fprintf(hFile, "%s TrustedBSD MAC Multi-label",
1368 (cnt++ == 0 ? "" : ","));
1369
1370 if (flags & FFS_SB_FLAG_UPDATED)
1371 tsk_fprintf(hFile, "%s Updated Flag Location",
1372 (cnt++ == 0 ? "" : ","));
1373
1374 tsk_fprintf(hFile, "\n");
1375 }
1376
1377
1378
1379 tsk_fprintf(hFile, "\nMETADATA INFORMATION\n");
1380 tsk_fprintf(hFile, "--------------------------------------------\n");
1381
1382 tsk_fprintf(hFile, "Inode Range: %" PRIuINUM " - %" PRIuINUM "\n",
1383 fs->first_inum, fs->last_inum);
1384 tsk_fprintf(hFile, "Root Directory: %" PRIuINUM "\n", fs->root_inum);
1385 if ((fs->ftype == TSK_FS_TYPE_FFS1)
1386 || (fs->ftype == TSK_FS_TYPE_FFS1B)) {
1387 tsk_fprintf(hFile, "Num of Avail Inodes: %" PRIu32 "\n",
1388 tsk_getu32(fs->endian, sb1->cstotal.ino_free));
1389 tsk_fprintf(hFile, "Num of Directories: %" PRIu32 "\n",
1390 tsk_getu32(fs->endian, sb1->cstotal.dir_num));
1391 }
1392 else {
1393 tsk_fprintf(hFile, "Num of Avail Inodes: %" PRIu64 "\n",
1394 tsk_getu64(fs->endian, sb2->cstotal.ino_free));
1395 tsk_fprintf(hFile, "Num of Directories: %" PRIu64 "\n",
1396 tsk_getu64(fs->endian, sb2->cstotal.dir_num));
1397 }
1398
1399
1400 tsk_fprintf(hFile, "\nCONTENT INFORMATION\n");
1401 tsk_fprintf(hFile, "--------------------------------------------\n");
1402
1403 tsk_fprintf(hFile, "Fragment Range: %" PRIuDADDR " - %" PRIuDADDR "\n",
1404 fs->first_block, fs->last_block);
1405
1406 if (fs->last_block != fs->last_block_act)
1407 tsk_fprintf(hFile,
1408 "Total Range in Image: %" PRIuDADDR " - %" PRIuDADDR "\n",
1409 fs->first_block, fs->last_block_act);
1410
1411 tsk_fprintf(hFile, "Block Size: %u\n", ffs->ffsbsize_b);
1412 tsk_fprintf(hFile, "Fragment Size: %u\n", fs->block_size);
1413
1414 if ((fs->ftype == TSK_FS_TYPE_FFS1)
1415 || (fs->ftype == TSK_FS_TYPE_FFS1B)) {
1416 tsk_fprintf(hFile, "Num of Avail Full Blocks: %" PRIu32 "\n",
1417 tsk_getu32(fs->endian, sb1->cstotal.blk_free));
1418 tsk_fprintf(hFile, "Num of Avail Fragments: %" PRIu32 "\n",
1419 tsk_getu32(fs->endian, sb1->cstotal.frag_free));
1420 }
1421 else {
1422 tsk_fprintf(hFile, "Num of Avail Full Blocks: %" PRIu64 "\n",
1423 tsk_getu64(fs->endian, sb2->cstotal.blk_free));
1424 tsk_fprintf(hFile, "Num of Avail Fragments: %" PRIu64 "\n",
1425 tsk_getu64(fs->endian, sb2->cstotal.frag_free));
1426 }
1427
1428 tsk_fprintf(hFile, "\nCYLINDER GROUP INFORMATION\n");
1429 tsk_fprintf(hFile, "--------------------------------------------\n");
1430
1431 tsk_fprintf(hFile, "Number of Cylinder Groups: %" PRIu32 "\n",
1432 ffs->groups_count);
1433 tsk_fprintf(hFile, "Inodes per group: %" PRId32 "\n",
1434 tsk_gets32(fs->endian, sb1->cg_inode_num));
1435 tsk_fprintf(hFile, "Fragments per group: %" PRId32 "\n",
1436 tsk_gets32(fs->endian, sb1->cg_frag_num));
1437
1438
1439 /* UFS 1 and 2 use the same ssize field and use the same csum1 */
1440 if (tsk_getu32(fs->endian, sb1->cg_ssize_b)) {
1441 ssize_t cnt;
1442 csum1 =
1443 (ffs_csum1 *) tsk_malloc(tsk_getu32(fs->endian,
1444 sb1->cg_ssize_b));
1445 if (csum1 == NULL)
1446 return 1;
1447
1448 if ((fs->ftype == TSK_FS_TYPE_FFS1)
1449 || (fs->ftype == TSK_FS_TYPE_FFS1B)) {
1450 cnt =
1451 tsk_fs_read_block(fs, (TSK_DADDR_T) tsk_getu32(fs->endian,
1452 sb1->cg_saddr), (char *) csum1, tsk_getu32(fs->endian,
1453 sb1->cg_ssize_b));
1454
1455 if (cnt != tsk_getu32(fs->endian, sb1->cg_ssize_b)) {
1456 if (cnt >= 0) {
1457 tsk_error_reset();
1458 tsk_error_set_errno(TSK_ERR_FS_READ);
1459 }
1460 tsk_error_set_errstr2
1461 ("ffs_fsstat: FFS1 group descriptor at %" PRIu32,
1462 tsk_getu32(fs->endian, sb1->cg_saddr));
1463 return 1;
1464 }
1465 }
1466 else {
1467 cnt = tsk_fs_read_block
1468 (fs, (TSK_DADDR_T) tsk_getu64(fs->endian,
1469 sb2->cg_saddr), (char *) csum1, tsk_getu32(fs->endian,
1470 sb2->cg_ssize_b));
1471 if (cnt != tsk_getu32(fs->endian, sb2->cg_ssize_b)) {
1472 if (cnt >= 0) {
1473 tsk_error_reset();
1474 tsk_error_set_errno(TSK_ERR_FS_READ);
1475 }
1476 tsk_error_set_errstr2
1477 ("ffs_fsstat: FFS2 group descriptor at %" PRIu64,
1478 tsk_getu64(fs->endian, sb2->cg_saddr));
1479 return 1;
1480 }
1481 }
1482 }
1483
1484 for (i = 0; i < ffs->groups_count; i++) {
1485
1486 tsk_take_lock(&ffs->lock);
1487 if (ffs_group_load(ffs, i)) {
1488 tsk_release_lock(&ffs->lock);
1489 return 1;
1490 }
1491 cgd = (ffs_cgd *) ffs->grp_buf;
1492
1493 tsk_fprintf(hFile, "\nGroup %d:\n", i);
1494 if (cgd) {
1495 if ((fs->ftype == TSK_FS_TYPE_FFS1)
1496 || (fs->ftype == TSK_FS_TYPE_FFS1B)) {
1497 tmptime = tsk_getu32(fs->endian, cgd->wtime);
1498 }
1499 else {
1500 ffs_cgd2 *cgd2 = (ffs_cgd2 *) cgd;
1501 tmptime = (uint32_t) tsk_getu64(fs->endian, cgd2->wtime);
1502 }
1503 tsk_fprintf(hFile, " Last Written: %s\n",
1504 (tmptime > 0) ? tsk_fs_time_to_str(tmptime,
1505 timeBuf) : "empty");
1506 }
1507 tsk_release_lock(&ffs->lock);
1508
1509 tsk_fprintf(hFile, " Inode Range: %" PRIu32 " - %" PRIu32 "\n",
1510 (tsk_gets32(fs->endian, sb1->cg_inode_num) * i),
1511 ((uint32_t) ((tsk_gets32(fs->endian,
1512 sb1->cg_inode_num) * (i + 1)) - 1)
1513 < fs->last_inum) ? (uint32_t) ((tsk_gets32(fs->endian,
1514 sb1->cg_inode_num) * (i + 1)) -
1515 1) : (uint32_t) fs->last_inum);
1516
1517 tsk_fprintf(hFile,
1518 " Fragment Range: %" PRIuDADDR " - %" PRIuDADDR "\n",
1519 cgbase_lcl(fs, sb1, i),
1520 ((cgbase_lcl(fs, sb1, i + 1) - 1) <
1521 fs->last_block) ? (cgbase_lcl(fs, sb1,
1522 i + 1) - 1) : fs->last_block);
1523
1524 /* The first group is special because the first 16 sectors are
1525 * reserved for the boot block.
1526 * the next contains the primary Super Block
1527 */
1528 if (!i) {
1529 tsk_fprintf(hFile, " Boot Block: 0 - %" PRIu32 "\n",
1530 (uint32_t) (15 * 512 / fs->block_size));
1531
1532
1533 tsk_fprintf(hFile,
1534 " Super Block: %" PRIu32 " - %" PRIu32 "\n",
1535 (uint32_t) (16 * 512 / fs->block_size),
1536 (uint32_t) ((16 * 512 / fs->block_size) + ffs->ffsbsize_f -
1537 1));
1538 }
1539
1540 tsk_fprintf(hFile,
1541 " Super Block: %" PRIuDADDR " - %" PRIuDADDR "\n",
1542 cgsblock_lcl(fs, sb1, i),
1543 (cgsblock_lcl(fs, sb1, i) + ffs->ffsbsize_f - 1));
1544
1545
1546 tsk_fprintf(hFile,
1547 " Group Desc: %" PRIuDADDR " - %" PRIuDADDR "\n",
1548 cgtod_lcl(fs, sb1, i), (cgtod_lcl(fs, sb1,
1549 i) + ffs->ffsbsize_f - 1));
1550
1551
1552 if (fs->ftype == TSK_FS_TYPE_FFS2) {
1553 tsk_fprintf(hFile,
1554 " Inode Table: %" PRIuDADDR " - %" PRIuDADDR "\n",
1555 cgimin_lcl(fs, sb1, i),
1556 (cgimin_lcl(fs, sb1, i) +
1557 ((roundup
1558 (tsk_gets32(fs->endian,
1559 sb1->cg_inode_num) *
1560 sizeof(ffs_inode2), fs->block_size)
1561 / fs->block_size) - 1)));
1562 }
1563 else {
1564 tsk_fprintf(hFile,
1565 " Inode Table: %" PRIuDADDR " - %" PRIuDADDR "\n",
1566 cgimin_lcl(fs, sb1, i),
1567 (cgimin_lcl(fs, sb1, i) +
1568 ((roundup
1569 (tsk_gets32(fs->endian,
1570 sb1->cg_inode_num) *
1571 sizeof(ffs_inode1), fs->block_size)
1572 / fs->block_size) - 1)));
1573 }
1574
1575 tsk_fprintf(hFile, " Data Fragments: ");
1576
1577 /* For all groups besides the first, the space before the
1578 * super block is also used for data
1579 */
1580 if (i)
1581 tsk_fprintf(hFile, "%" PRIuDADDR " - %" PRIuDADDR ", ",
1582 cgbase_lcl(fs, sb1, i), cgsblock_lcl(fs, sb1, i) - 1);
1583
1584 tsk_fprintf(hFile, "%" PRIuDADDR " - %" PRIuDADDR "\n",
1585 cgdmin_lcl(fs, sb1, i),
1586 ((cgbase_lcl(fs, sb1, i + 1) - 1) < fs->last_block) ?
1587 (cgbase_lcl(fs, sb1, i + 1) - 1) : fs->last_block);
1588
1589
1590 if ((csum1)
1591 && ((i + 1) * sizeof(ffs_csum1) < tsk_getu32(fs->endian,
1592 sb1->cg_ssize_b))) {
1593 tsk_fprintf(hFile,
1594 " Global Summary (from the superblock summary area):\n");
1595 tsk_fprintf(hFile, " Num of Dirs: %" PRIu32 "\n",
1596 tsk_getu32(fs->endian, &csum1[i].dir_num));
1597 tsk_fprintf(hFile, " Num of Avail Blocks: %" PRIu32 "\n",
1598 tsk_getu32(fs->endian, &csum1[i].blk_free));
1599 tsk_fprintf(hFile, " Num of Avail Inodes: %" PRIu32 "\n",
1600 tsk_getu32(fs->endian, &csum1[i].ino_free));
1601 tsk_fprintf(hFile, " Num of Avail Frags: %" PRIu32 "\n",
1602 tsk_getu32(fs->endian, &csum1[i].frag_free));
1603 }
1604
1605 if (cgd) {
1606 tsk_fprintf(hFile,
1607 " Local Summary (from the group descriptor):\n");
1608 tsk_fprintf(hFile, " Num of Dirs: %" PRIu32 "\n",
1609 tsk_getu32(fs->endian, &cgd->cs.dir_num));
1610 tsk_fprintf(hFile, " Num of Avail Blocks: %" PRIu32 "\n",
1611 tsk_getu32(fs->endian, &cgd->cs.blk_free));
1612 tsk_fprintf(hFile, " Num of Avail Inodes: %" PRIu32 "\n",
1613 tsk_getu32(fs->endian, &cgd->cs.ino_free));
1614 tsk_fprintf(hFile, " Num of Avail Frags: %" PRIu32 "\n",
1615 tsk_getu32(fs->endian, &cgd->cs.frag_free));
1616 tsk_fprintf(hFile,
1617 " Last Block Allocated: %" PRIuDADDR "\n",
1618 tsk_getu32(fs->endian,
1619 &cgd->last_alloc_blk) + cgbase_lcl(fs, sb1, i));
1620 tsk_fprintf(hFile,
1621 " Last Fragment Allocated: %" PRIuDADDR "\n",
1622 tsk_getu32(fs->endian,
1623 &cgd->last_alloc_frag) + cgbase_lcl(fs, sb1, i));
1624 tsk_fprintf(hFile, " Last Inode Allocated: %" PRIu32 "\n",
1625 tsk_getu32(fs->endian,
1626 &cgd->last_alloc_ino) + (tsk_gets32(fs->endian,
1627 sb1->cg_inode_num) * i));
1628 }
1629 }
1630 return 0;
1631 }
1632
1633
1634
1635 /************************* istat *******************************/
1636
1637 typedef struct {
1638 FILE *hFile;
1639 int idx;
1640 } FFS_PRINT_ADDR;
1641
1642
1643 static TSK_WALK_RET_ENUM
print_addr_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 a_flags,void * ptr)1644 print_addr_act(TSK_FS_FILE * fs_file, TSK_OFF_T a_off, TSK_DADDR_T addr,
1645 char *buf, size_t size, TSK_FS_BLOCK_FLAG_ENUM a_flags, void *ptr)
1646 {
1647 TSK_FS_INFO *fs = fs_file->fs_info;
1648 FFS_PRINT_ADDR *print = (FFS_PRINT_ADDR *) ptr;
1649
1650 if (a_flags & TSK_FS_BLOCK_FLAG_CONT) {
1651 int i, s;
1652 /* cycle through the fragments if they exist */
1653 for (i = 0, s = (int) size; s > 0; s -= fs->block_size, i++) {
1654
1655 /* sparse file */
1656 if (addr)
1657 tsk_fprintf(print->hFile, "%" PRIuDADDR " ", addr + i);
1658 else
1659 tsk_fprintf(print->hFile, "0 ");
1660
1661 if (++(print->idx) == 8) {
1662 tsk_fprintf(print->hFile, "\n");
1663 print->idx = 0;
1664 }
1665 }
1666 }
1667
1668 return TSK_WALK_CONT;
1669 }
1670
1671
1672
1673 /**
1674 * Print details on a specific file to a file handle.
1675 *
1676 * @param fs File system file is located in
1677 * @param hFile File handle to print text to
1678 * @param inum Address of file in file system
1679 * @param numblock The number of blocks in file to force print (can go beyond file size)
1680 * @param sec_skew Clock skew in seconds to also print times in
1681 *
1682 * @returns 1 on error and 0 on success
1683 */
1684 static uint8_t
ffs_istat(TSK_FS_INFO * fs,TSK_FS_ISTAT_FLAG_ENUM istat_flags,FILE * hFile,TSK_INUM_T inum,TSK_DADDR_T numblock,int32_t sec_skew)1685 ffs_istat(TSK_FS_INFO * fs, TSK_FS_ISTAT_FLAG_ENUM istat_flags, FILE * hFile, TSK_INUM_T inum,
1686 TSK_DADDR_T numblock, int32_t sec_skew)
1687 {
1688 FFS_INFO *ffs = (FFS_INFO *) fs;
1689 TSK_FS_META *fs_meta;
1690 TSK_FS_FILE *fs_file;
1691 char ls[12];
1692 FFS_PRINT_ADDR print;
1693 const TSK_FS_ATTR *fs_attr_indir;
1694 char *dino_buf;
1695 char timeBuf[128];
1696
1697 // clean up any error messages that are lying around
1698 tsk_error_reset();
1699
1700 if ((fs_file = tsk_fs_file_open_meta(fs, NULL, inum)) == NULL) {
1701 return 1;
1702 }
1703 fs_meta = fs_file->meta;
1704
1705 tsk_fprintf(hFile, "inode: %" PRIuINUM "\n", inum);
1706 tsk_fprintf(hFile, "%sAllocated\n",
1707 (fs_meta->flags & TSK_FS_META_FLAG_ALLOC) ? "" : "Not ");
1708
1709 tsk_take_lock(&ffs->lock);
1710 tsk_fprintf(hFile, "Group: %" PRI_FFSGRP "\n", ffs->grp_num);
1711 tsk_release_lock(&ffs->lock);
1712
1713 if (fs_meta->link)
1714 tsk_fprintf(hFile, "symbolic link to: %s\n", fs_meta->link);
1715
1716 tsk_fprintf(hFile, "uid / gid: %" PRIuUID " / %" PRIuGID "\n",
1717 fs_meta->uid, fs_meta->gid);
1718
1719
1720 tsk_fs_meta_make_ls(fs_meta, ls, sizeof(ls));
1721 tsk_fprintf(hFile, "mode: %s\n", ls);
1722
1723 tsk_fprintf(hFile, "size: %" PRIdOFF "\n", fs_meta->size);
1724 tsk_fprintf(hFile, "num of links: %u\n", fs_meta->nlink);
1725
1726
1727 if (sec_skew != 0) {
1728 tsk_fprintf(hFile, "\nAdjusted Inode Times:\n");
1729 if (fs_meta->mtime)
1730 fs_meta->mtime -= sec_skew;
1731 if (fs_meta->atime)
1732 fs_meta->atime -= sec_skew;
1733 if (fs_meta->ctime)
1734 fs_meta->ctime -= sec_skew;
1735
1736 tsk_fprintf(hFile, "Accessed:\t%s\n",
1737 tsk_fs_time_to_str(fs_meta->atime, timeBuf));
1738 tsk_fprintf(hFile, "File Modified:\t%s\n",
1739 tsk_fs_time_to_str(fs_meta->mtime, timeBuf));
1740 tsk_fprintf(hFile, "Inode Modified:\t%s\n",
1741 tsk_fs_time_to_str(fs_meta->ctime, timeBuf));
1742
1743 if (fs_meta->mtime)
1744 fs_meta->mtime += sec_skew;
1745 if (fs_meta->atime)
1746 fs_meta->atime += sec_skew;
1747 if (fs_meta->ctime)
1748 fs_meta->ctime += sec_skew;
1749
1750 tsk_fprintf(hFile, "\nOriginal Inode Times:\n");
1751 }
1752 else {
1753 tsk_fprintf(hFile, "\nInode Times:\n");
1754 }
1755
1756 tsk_fprintf(hFile, "Accessed:\t%s\n",
1757 tsk_fs_time_to_str(fs_meta->atime, timeBuf));
1758 tsk_fprintf(hFile, "File Modified:\t%s\n",
1759 tsk_fs_time_to_str(fs_meta->mtime, timeBuf));
1760 tsk_fprintf(hFile, "Inode Modified:\t%s\n",
1761 tsk_fs_time_to_str(fs_meta->ctime, timeBuf));
1762
1763 if ((dino_buf = (char *) tsk_malloc(sizeof(ffs_inode2))) == NULL)
1764 return 1;
1765 // we won't have dino_buf for "virtual" files
1766 if ((fs->ftype == TSK_FS_TYPE_FFS2) && (dino_buf)) {
1767 ffs_inode2 *in = (ffs_inode2 *) dino_buf;
1768 /* Are there extended attributes */
1769 if (tsk_getu32(fs->endian, in->di_extsize) > 0) {
1770 ffs_extattr *ea;
1771 uint32_t size;
1772 char name[257];
1773 char *blk_buf;
1774
1775 if ((blk_buf = tsk_malloc(ffs->ffsbsize_b)) == NULL) {
1776 tsk_fs_file_close(fs_file);
1777 free(dino_buf);
1778 return 1;
1779 }
1780
1781 size = tsk_getu32(fs->endian, in->di_extsize);
1782 tsk_fprintf(hFile, "\nExtended Attributes:\n");
1783 tsk_fprintf(hFile,
1784 "Size: %" PRIu32 " (%" PRIu64 ", %" PRIu64 ")\n", size,
1785 tsk_getu64(fs->endian, in->di_extb[0]),
1786 tsk_getu64(fs->endian, in->di_extb[1]));
1787
1788
1789 /* Process first block */
1790 // @@@ Incorporate values into this as well
1791 if ((tsk_getu64(fs->endian, in->di_extb[0]) >= fs->first_block)
1792 && (tsk_getu64(fs->endian,
1793 in->di_extb[0]) <= fs->last_block)) {
1794 uintptr_t end;
1795 ssize_t cnt;
1796
1797 cnt =
1798 tsk_fs_read_block(fs, tsk_getu64(fs->endian,
1799 in->di_extb[0]), blk_buf, ffs->ffsbsize_b);
1800 if (cnt != ffs->ffsbsize_b) {
1801 if (cnt >= 0) {
1802 tsk_error_reset();
1803 tsk_error_set_errno(TSK_ERR_FS_READ);
1804 }
1805 tsk_error_set_errstr2
1806 ("ffs_istat: FFS2 extended attribute 0 at %"
1807 PRIu64, tsk_getu64(fs->endian, in->di_extb[0]));
1808 tsk_fs_file_close(fs_file);
1809 free(blk_buf);
1810 free(dino_buf);
1811 return 1;
1812 }
1813
1814 ea = (ffs_extattr *) blk_buf;
1815
1816 if (size > ffs->ffsbsize_b) {
1817 end = (uintptr_t) ea + ffs->ffsbsize_b;
1818 size -= ffs->ffsbsize_b;
1819 }
1820 else {
1821 end = (uintptr_t) ea + size;
1822 size = 0;
1823 }
1824
1825 for (; (uintptr_t) ea < end;
1826 ea =
1827 (ffs_extattr *) ((uintptr_t) ea +
1828 tsk_getu32(fs->endian, ea->reclen))) {
1829 memcpy(name, ea->name, ea->nlen);
1830 name[ea->nlen] = '\0';
1831 tsk_fprintf(hFile, "%s\n", name);
1832 }
1833 }
1834 if ((tsk_getu64(fs->endian, in->di_extb[1]) >= fs->first_block)
1835 && (tsk_getu64(fs->endian,
1836 in->di_extb[1]) <= fs->last_block)) {
1837 uintptr_t end;
1838 ssize_t cnt;
1839
1840 cnt =
1841 tsk_fs_read_block(fs, tsk_getu64(fs->endian,
1842 in->di_extb[1]), blk_buf, ffs->ffsbsize_b);
1843 if (cnt != ffs->ffsbsize_b) {
1844 if (cnt >= 0) {
1845 tsk_error_reset();
1846 tsk_error_set_errno(TSK_ERR_FS_INODE_COR);
1847 }
1848 tsk_error_set_errstr2
1849 ("ffs_istat: FFS2 extended attribute 1 at %"
1850 PRIu64, tsk_getu64(fs->endian, in->di_extb[1]));
1851 tsk_fs_file_close(fs_file);
1852 free(blk_buf);
1853 free(dino_buf);
1854 return 1;
1855 }
1856
1857 ea = (ffs_extattr *) blk_buf;
1858
1859 if (size > ffs->ffsbsize_b)
1860 end = (uintptr_t) ea + ffs->ffsbsize_b;
1861 else
1862 end = (uintptr_t) ea + size;
1863
1864 for (; (uintptr_t) ea < end;
1865 ea =
1866 (ffs_extattr *) ((uintptr_t) ea +
1867 tsk_getu32(fs->endian, ea->reclen))) {
1868 memcpy(name, ea->name, ea->nlen);
1869 name[ea->nlen] = '\0';
1870 tsk_fprintf(hFile, "%s\n", name);
1871 }
1872 }
1873 free(blk_buf);
1874 }
1875 free(dino_buf);
1876 }
1877
1878
1879 /* A bad hack to force a specified number of blocks */
1880 if (numblock > 0)
1881 fs_meta->size = numblock * ffs->ffsbsize_b;
1882
1883 tsk_fprintf(hFile, "\nDirect Blocks:\n");
1884
1885 if (istat_flags & TSK_FS_ISTAT_RUNLIST) {
1886 const TSK_FS_ATTR * fs_attr_direct = tsk_fs_file_attr_get_type(fs_file,
1887 TSK_FS_ATTR_TYPE_DEFAULT, 0, 0);
1888 if (fs_attr_direct && (fs_attr_direct->flags & TSK_FS_ATTR_NONRES)) {
1889 if (tsk_fs_attr_print(fs_attr_direct, hFile)) {
1890 tsk_fprintf(hFile, "\nError creating run lists\n");
1891 tsk_error_print(hFile);
1892 tsk_error_reset();
1893 }
1894 }
1895 }
1896 else {
1897 print.idx = 0;
1898 print.hFile = hFile;
1899
1900 if (tsk_fs_file_walk(fs_file, TSK_FS_FILE_WALK_FLAG_AONLY,
1901 print_addr_act, (void *)&print)) {
1902 tsk_fprintf(hFile, "\nError reading blocks in file\n");
1903 tsk_error_print(hFile);
1904 tsk_fs_file_close(fs_file);
1905 return 1;
1906 }
1907
1908 if (print.idx != 0)
1909 tsk_fprintf(hFile, "\n");
1910 }
1911
1912 fs_attr_indir = tsk_fs_file_attr_get_type(fs_file,
1913 TSK_FS_ATTR_TYPE_UNIX_INDIR, 0, 0);
1914 if (fs_attr_indir) {
1915 tsk_fprintf(hFile, "\nIndirect Blocks:\n");
1916 if (istat_flags & TSK_FS_ISTAT_RUNLIST) {
1917 if (tsk_fs_attr_print(fs_attr_indir, hFile)) {
1918 tsk_fprintf(hFile, "\nError creating run lists\n");
1919 tsk_error_print(hFile);
1920 tsk_error_reset();
1921 }
1922 }
1923 else {
1924 print.idx = 0;
1925
1926 if (tsk_fs_attr_walk(fs_attr_indir, TSK_FS_FILE_WALK_FLAG_AONLY,
1927 print_addr_act, (void *)&print)) {
1928 tsk_fprintf(hFile, "\nError reading indirect attribute: ");
1929 tsk_error_print(hFile);
1930 tsk_error_reset();
1931 }
1932 else if (print.idx != 0) {
1933 tsk_fprintf(hFile, "\n");
1934 }
1935 }
1936 }
1937
1938 tsk_fs_file_close(fs_file);
1939 return 0;
1940 }
1941
1942 /* Return 1 on error and 0 on success */
1943 uint8_t
ffs_jopen(TSK_FS_INFO * fs,TSK_INUM_T inum)1944 ffs_jopen(TSK_FS_INFO * fs, TSK_INUM_T inum)
1945 {
1946 tsk_error_reset();
1947 tsk_error_set_errno(TSK_ERR_FS_UNSUPFUNC);
1948 tsk_error_set_errstr("UFS does not have a journal");
1949 return 1;
1950 }
1951
1952 uint8_t
ffs_jentry_walk(TSK_FS_INFO * fs,int a_flags,TSK_FS_JENTRY_WALK_CB action,void * ptr)1953 ffs_jentry_walk(TSK_FS_INFO * fs, int a_flags,
1954 TSK_FS_JENTRY_WALK_CB action, void *ptr)
1955 {
1956 tsk_error_reset();
1957 tsk_error_set_errno(TSK_ERR_FS_UNSUPFUNC);
1958 tsk_error_set_errstr("UFS does not have a journal");
1959 return 1;
1960 }
1961
1962
1963 uint8_t
ffs_jblk_walk(TSK_FS_INFO * fs,TSK_DADDR_T start,TSK_DADDR_T end,int a_flags,TSK_FS_JBLK_WALK_CB action,void * ptr)1964 ffs_jblk_walk(TSK_FS_INFO * fs, TSK_DADDR_T start, TSK_DADDR_T end,
1965 int a_flags, TSK_FS_JBLK_WALK_CB action, void *ptr)
1966 {
1967 tsk_error_reset();
1968 tsk_error_set_errno(TSK_ERR_FS_UNSUPFUNC);
1969 tsk_error_set_errstr("UFS does not have a journal");
1970 return 1;
1971 }
1972
1973
1974 /* ffs_close - close a fast file system */
1975 static void
ffs_close(TSK_FS_INFO * fs)1976 ffs_close(TSK_FS_INFO * fs)
1977 {
1978 FFS_INFO *ffs = (FFS_INFO *) fs;
1979
1980 fs->tag = 0;
1981
1982 free(ffs->grp_buf);
1983 free(ffs->itbl_buf);
1984
1985 tsk_deinit_lock(&ffs->lock);
1986
1987 free(ffs->fs.sb1);
1988 tsk_fs_free(fs);
1989 }
1990
1991 /**
1992 * \internal
1993 * Open part of a disk image as a FFS/UFS file system.
1994 *
1995 * @param img_info Disk image to analyze
1996 * @param offset Byte offset where file system starts
1997 * @param ftype Specific type of file system
1998 * @returns NULL on error or if data is not a FFS file system
1999 */
2000 TSK_FS_INFO *
ffs_open(TSK_IMG_INFO * img_info,TSK_OFF_T offset,TSK_FS_TYPE_ENUM ftype,uint8_t test)2001 ffs_open(TSK_IMG_INFO * img_info, TSK_OFF_T offset, TSK_FS_TYPE_ENUM ftype, uint8_t test)
2002 {
2003 char *myname = "ffs_open";
2004 FFS_INFO *ffs;
2005 unsigned int len;
2006 TSK_FS_INFO *fs;
2007 ssize_t cnt;
2008
2009 // clean up any error messages that are lying around
2010 tsk_error_reset();
2011
2012 if (TSK_FS_TYPE_ISFFS(ftype) == 0) {
2013 tsk_error_reset();
2014 tsk_error_set_errno(TSK_ERR_FS_ARG);
2015 tsk_error_set_errstr("Invalid FS Type in ffs_open");
2016 return NULL;
2017 }
2018
2019 if (img_info->sector_size == 0) {
2020 tsk_error_reset();
2021 tsk_error_set_errno(TSK_ERR_FS_ARG);
2022 tsk_error_set_errstr("ffs_open: sector size is 0");
2023 return NULL;
2024 }
2025
2026 if ((ffs = (FFS_INFO *) tsk_fs_malloc(sizeof(*ffs))) == NULL)
2027 return NULL;
2028
2029 fs = &(ffs->fs_info);
2030
2031 fs->ftype = ftype;
2032 fs->flags = 0;
2033 fs->duname = "Fragment";
2034 fs->tag = TSK_FS_INFO_TAG;
2035
2036 fs->img_info = img_info;
2037 fs->offset = offset;
2038
2039 /* Both sbs are the same size */
2040 len = roundup(sizeof(ffs_sb1), img_info->sector_size);
2041 ffs->fs.sb1 = (ffs_sb1 *) tsk_malloc(len);
2042 if (ffs->fs.sb1 == NULL) {
2043 fs->tag = 0;
2044 tsk_fs_free((TSK_FS_INFO *)ffs);
2045 return NULL;
2046 }
2047
2048 /* check the magic and figure out the endian ordering */
2049
2050 /* Try UFS2 first - I read somewhere that some upgrades
2051 * kept the original UFS1 superblock in addition to
2052 * the new one */
2053 cnt = tsk_fs_read
2054 (fs, (TSK_OFF_T) UFS2_SBOFF, (char *) ffs->fs.sb2,
2055 sizeof(ffs_sb2));
2056 if (cnt != sizeof(ffs_sb2)) {
2057 if (cnt >= 0) {
2058 tsk_error_reset();
2059 tsk_error_set_errno(TSK_ERR_FS_READ);
2060 }
2061 tsk_error_set_errstr("%s: Superblock at %" PRIuDADDR, myname,
2062 (TSK_OFF_T) UFS2_SBOFF);
2063 fs->tag = 0;
2064 free(ffs->fs.sb1);
2065 tsk_fs_free((TSK_FS_INFO *)ffs);
2066 return NULL;
2067 }
2068
2069 /* If that didn't work, try the 256KB UFS2 location */
2070 if (tsk_fs_guessu32(fs, ffs->fs.sb2->magic, UFS2_FS_MAGIC)) {
2071 if (tsk_verbose)
2072 fprintf(stderr, "ufs_open: Trying 256KB UFS2 location\n");
2073
2074 cnt = tsk_fs_read
2075 (fs, (TSK_OFF_T) UFS2_SBOFF2, (char *) ffs->fs.sb2,
2076 sizeof(ffs_sb2));
2077 if (cnt != sizeof(ffs_sb2)) {
2078 if (cnt >= 0) {
2079 tsk_error_reset();
2080 tsk_error_set_errno(TSK_ERR_FS_READ);
2081 }
2082 tsk_error_set_errstr2("%s: Superblock at %" PRIuDADDR,
2083 myname, (TSK_OFF_T) UFS2_SBOFF2);
2084 fs->tag = 0;
2085 free(ffs->fs.sb1);
2086 tsk_fs_free((TSK_FS_INFO *)ffs);
2087 return NULL;
2088 }
2089
2090 /* Try UFS1 if that did not work */
2091 if (tsk_fs_guessu32(fs, ffs->fs.sb2->magic, UFS2_FS_MAGIC)) {
2092 if (tsk_verbose)
2093 fprintf(stderr, "ufs_open: Trying UFS1 location\n");
2094
2095 cnt = tsk_fs_read
2096 (fs, (TSK_OFF_T) UFS1_SBOFF, (char *) ffs->fs.sb1, len);
2097 if (cnt != len) {
2098 if (cnt >= 0) {
2099 tsk_error_reset();
2100 tsk_error_set_errno(TSK_ERR_FS_READ);
2101 }
2102 tsk_error_set_errstr2("%s: Superblock at %" PRIuDADDR,
2103 myname, (TSK_OFF_T) UFS1_SBOFF);
2104 fs->tag = 0;
2105 free(ffs->fs.sb1);
2106 tsk_fs_free((TSK_FS_INFO *)ffs);
2107 return NULL;
2108 }
2109 if (tsk_fs_guessu32(fs, ffs->fs.sb1->magic, UFS1_FS_MAGIC)) {
2110 tsk_error_reset();
2111 tsk_error_set_errno(TSK_ERR_FS_MAGIC);
2112 tsk_error_set_errstr("No UFS Magic Found");
2113 if (tsk_verbose)
2114 fprintf(stderr, "ufs_open: No UFS magic found\n");
2115 fs->tag = 0;
2116 free(ffs->fs.sb1);
2117 tsk_fs_free((TSK_FS_INFO *)ffs);
2118 return NULL;
2119 }
2120 else {
2121 // @@@ NEED TO DIFFERENTIATE BETWEEN A & B - UID/GID location in inode
2122 fs->ftype = TSK_FS_TYPE_FFS1;
2123 }
2124 }
2125 else {
2126 fs->ftype = TSK_FS_TYPE_FFS2;
2127 }
2128 }
2129 else {
2130 fs->ftype = TSK_FS_TYPE_FFS2;
2131 }
2132
2133
2134 /*
2135 * Translate some filesystem-specific information to generic form.
2136 */
2137
2138 if (fs->ftype == TSK_FS_TYPE_FFS2) {
2139 fs->block_count = tsk_gets64(fs->endian, ffs->fs.sb2->frag_num);
2140 fs->block_size = tsk_gets32(fs->endian, ffs->fs.sb2->fsize_b);
2141 ffs->ffsbsize_b = tsk_gets32(fs->endian, ffs->fs.sb2->bsize_b);
2142 ffs->ffsbsize_f = tsk_gets32(fs->endian, ffs->fs.sb2->bsize_frag);
2143 ffs->groups_count = tsk_gets32(fs->endian, ffs->fs.sb2->cg_num);
2144 }
2145 else {
2146 fs->block_count = tsk_gets32(fs->endian, ffs->fs.sb1->frag_num);
2147 fs->block_size = tsk_gets32(fs->endian, ffs->fs.sb1->fsize_b);
2148 ffs->ffsbsize_b = tsk_gets32(fs->endian, ffs->fs.sb1->bsize_b);
2149 ffs->ffsbsize_f = tsk_gets32(fs->endian, ffs->fs.sb1->bsize_frag);
2150 ffs->groups_count = tsk_gets32(fs->endian, ffs->fs.sb1->cg_num);
2151 }
2152
2153 // apply some sanity checks before we start using these numbers
2154 if ((fs->block_size == 0) || (ffs->ffsbsize_b == 0) || (ffs->ffsbsize_f == 0)
2155 || (fs->block_size % 512) || (ffs->ffsbsize_b % 512)) {
2156 tsk_error_reset();
2157 tsk_error_set_errno(TSK_ERR_FS_MAGIC);
2158 tsk_error_set_errstr
2159 ("Not a UFS FS (invalid fragment or block size)");
2160 if (tsk_verbose)
2161 fprintf(stderr, "ufs_open: invalid fragment or block size\n");
2162 fs->tag = 0;
2163 free(ffs->fs.sb1);
2164 tsk_fs_free((TSK_FS_INFO *)ffs);
2165 return NULL;
2166 }
2167
2168 if ((ffs->ffsbsize_b / fs->block_size) != ffs->ffsbsize_f) {
2169 tsk_error_reset();
2170 tsk_error_set_errno(TSK_ERR_FS_MAGIC);
2171 tsk_error_set_errstr("Not a UFS FS (frag / block size mismatch)");
2172 if (tsk_verbose)
2173 fprintf(stderr, "ufs_open: fragment / block size mismatch\n");
2174 fs->tag = 0;
2175 free(ffs->fs.sb1);
2176 tsk_fs_free((TSK_FS_INFO *)ffs);
2177 return NULL;
2178 }
2179
2180 /*
2181 * Block calculations
2182 */
2183 fs->first_block = 0;
2184 fs->last_block = fs->last_block_act = fs->block_count - 1;
2185 fs->dev_bsize = img_info->sector_size;
2186
2187 // determine the last block we have in this image
2188 if ((TSK_DADDR_T) ((img_info->size - offset) / fs->block_size) <
2189 fs->block_count)
2190 fs->last_block_act =
2191 (img_info->size - offset) / fs->block_size - 1;
2192
2193
2194
2195 // Inode / meta data calculations
2196 if (fs->ftype == TSK_FS_TYPE_FFS2) {
2197 fs->inum_count = ffs->groups_count * tsk_gets32(fs->endian, ffs->fs.sb2->cg_inode_num) + 1; // we are adding 1 in this calc to account for Orphans directory
2198 }
2199 else {
2200 fs->inum_count = ffs->groups_count * tsk_gets32(fs->endian, ffs->fs.sb1->cg_inode_num) + 1; // we are adding 1 in this calc to account for Orphans directory
2201 }
2202
2203 fs->root_inum = FFS_ROOTINO;
2204 fs->first_inum = FFS_FIRSTINO;
2205 fs->last_inum = fs->inum_count - 1;
2206
2207 /* Volume ID - in the same place for both types */
2208 for (fs->fs_id_used = 0; fs->fs_id_used < 8; fs->fs_id_used++) {
2209 fs->fs_id[fs->fs_id_used] = ffs->fs.sb1->fs_id[fs->fs_id_used];
2210 }
2211
2212 // set the function pointers
2213 fs->inode_walk = ffs_inode_walk;
2214 fs->block_walk = ffs_block_walk;
2215 fs->block_getflags = ffs_block_getflags;
2216
2217 fs->get_default_attr_type = tsk_fs_unix_get_default_attr_type;
2218 fs->load_attrs = tsk_fs_unix_make_data_run;
2219 fs->name_cmp = tsk_fs_unix_name_cmp;
2220
2221 fs->file_add_meta = ffs_inode_lookup;
2222 fs->dir_open_meta = ffs_dir_open_meta;
2223 fs->fsstat = ffs_fsstat;
2224 fs->fscheck = ffs_fscheck;
2225 fs->istat = ffs_istat;
2226 fs->close = ffs_close;
2227 fs->jblk_walk = ffs_jblk_walk;
2228 fs->jentry_walk = ffs_jentry_walk;
2229 fs->jopen = ffs_jopen;
2230 fs->journ_inum = 0;
2231
2232 // initialize caches
2233 ffs->grp_buf = NULL;
2234 ffs->grp_num = 0xffffffff;
2235 ffs->grp_addr = 0;
2236
2237 ffs->itbl_buf = NULL;
2238 ffs->itbl_addr = 0;
2239
2240 /*
2241 * Print some stats.
2242 */
2243 if (tsk_verbose)
2244 tsk_fprintf(stderr,
2245 "inodes %" PRIuINUM " root ino %" PRIuINUM " cyl groups %"
2246 PRId32 " blocks %" PRIuDADDR "\n", fs->inum_count,
2247 fs->root_inum, ffs->groups_count, fs->block_count);
2248
2249 tsk_init_lock(&ffs->lock);
2250
2251 return fs;
2252 }
2253