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