📄 fatfs_meta.c
字号:
// not sure why this would ever happen, but... else if (fs_meta->attr != NULL) { tsk_fs_attrlist_markunused(fs_meta->attr); } else if (fs_meta->attr == NULL) { fs_meta->attr = tsk_fs_attrlist_alloc(); } // sanity check on input if ((clust > (fatfs->lastclust)) && (FATFS_ISEOF(clust, fatfs->mask) == 0)) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; tsk_error_reset(); if (a_fs_file->meta->flags & TSK_FS_META_FLAG_UNALLOC) tsk_errno = TSK_ERR_FS_RECOVER; else tsk_errno = TSK_ERR_FS_INODE_COR; snprintf(tsk_errstr, TSK_ERRSTR_L, "fatfs_make_data_run: Starting cluster address too large: %" PRIuDADDR, clust); return 1; } /* We need to handle the special files specially because they * are not in the FAT. Except for FAT32 root dirs, those are normal. */ if ((a_fs_file->meta->addr == FATFS_ROOTINO) && (fs->ftype != TSK_FS_TYPE_FAT32) && (clust == 1)) { TSK_FS_ATTR_RUN *data_run; if (tsk_verbose) tsk_fprintf(stderr, "fatfs_make_data_run: Loading root directory\n"); // make a non-resident run data_run = tsk_fs_attr_run_alloc(); if (data_run == NULL) { return 1; } data_run->addr = fatfs->rootsect; data_run->len = fatfs->firstclustsect - fatfs->firstdatasect; if ((fs_attr = tsk_fs_attrlist_getnew(fs_meta->attr, TSK_FS_ATTR_NONRES)) == NULL) { return 1; } // initialize the data run if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run, NULL, TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT, data_run->len * fs->block_size, data_run->len * fs->block_size, 0, 0)) { return 1; } fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED; return 0; } // see if it is one of the special files else if ((a_fs_file->meta->addr > fs->last_inum - FATFS_NUM_SPECFILE) && (a_fs_file->meta->addr != TSK_FS_ORPHANDIR_INUM(fs))) { TSK_FS_ATTR_RUN *data_run; if (tsk_verbose) tsk_fprintf(stderr, "fatfs_make_data_run: Loading special file: %" PRIuINUM "\n", a_fs_file->meta->addr); // make a non-resident run data_run = tsk_fs_attr_run_alloc(); if (data_run == NULL) { return 1; } data_run->addr = clust; data_run->len = a_fs_file->meta->size / fs->block_size; if ((fs_attr = tsk_fs_attrlist_getnew(fs_meta->attr, TSK_FS_ATTR_NONRES)) == NULL) { return 1; } // initialize the data run if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run, NULL, TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT, data_run->len * fs->block_size, data_run->len * fs->block_size, 0, 0)) { return 1; } fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED; return 0; } /* A deleted file that we want to recover * In this case, we could get a lot of errors because of inconsistent * data. TO make it clear that these are from a recovery, we set most * error codes to _RECOVER so that they can be more easily suppressed. */ else if (fs_meta->flags & TSK_FS_META_FLAG_UNALLOC) { TSK_DADDR_T sbase; TSK_DADDR_T startclust = clust; TSK_OFF_T recoversize = fs_meta->size; int retval; TSK_FS_ATTR_RUN *data_run = NULL; TSK_FS_ATTR_RUN *data_run_head = NULL; TSK_OFF_T full_len_s = 0; uint8_t canRecover = 1; // set to 0 if recovery is not possible if (tsk_verbose) tsk_fprintf(stderr, "fatfs_make_data_run: Processing deleted file %" PRIuINUM " in recovery mode\n", fs_meta->addr); /* We know the size and the starting cluster * * We are going to take the clusters from the starting cluster * onwards and skip the clusters that are current allocated */ /* Sanity checks on the starting cluster */ /* Convert the cluster addr to a sector addr */ sbase = FATFS_CLUST_2_SECT(fatfs, startclust); if (sbase > fs->last_block) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_RECOVER; snprintf(tsk_errstr, TSK_ERRSTR_L, "fatfs_make_data_run: Starting cluster address too large (recovery): %" PRIuDADDR, sbase); fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; return 1; } else { /* If the starting cluster is already allocated then we can't * recover it */ retval = fatfs_is_clustalloc(fatfs, startclust); if (retval != 0) { canRecover = 0; } } /* Part 1 is to make sure there are enough unallocated clusters * for the size of the file */ clust = startclust; size_remain = recoversize; // we could make this negative so sign it for the comparison while (((int64_t) size_remain > 0) && (canRecover)) { int retval; sbase = FATFS_CLUST_2_SECT(fatfs, clust); /* Are we past the end of the FS? * that means we could not find enough unallocated clusters * for the file size */ if (sbase > fs->last_block) { canRecover = 0; if (tsk_verbose) tsk_fprintf(stderr, "Could not find enough unallocated sectors to recover with - aborting\n"); break; } /* Skip allocated clusters */ retval = fatfs_is_clustalloc(fatfs, clust); if (retval == -1) { canRecover = 0; break; } else if (retval == 1) { clust++; continue; } /* We can use this sector */ // see if we need a new run if ((data_run == NULL) || (data_run->addr + data_run->len != sbase)) { TSK_FS_ATTR_RUN *data_run_tmp = tsk_fs_attr_run_alloc(); if (data_run_tmp == NULL) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; tsk_fs_attr_run_free(data_run_head); return 1; } if (data_run_head == NULL) { data_run_head = data_run_tmp; data_run_tmp->offset = 0; } else if (data_run != NULL) { data_run->next = data_run_tmp; data_run_tmp->offset = data_run->offset + data_run->len; } data_run = data_run_tmp; data_run->len = 0; data_run->addr = sbase; } data_run->len += fatfs->csize; full_len_s += fatfs->csize; size_remain -= (fatfs->csize << fatfs->ssize_sh); clust++; } // Get a FS_DATA structure and add the runlist to it if ((fs_attr = tsk_fs_attrlist_getnew(fs_meta->attr, TSK_FS_ATTR_NONRES)) == NULL) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; return 1; } if (canRecover) { /* We can recover the file */ // initialize the data run if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run_head, NULL, TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT, fs_meta->size, roundup(fs_meta->size, fs->block_size), 0, 0)) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; return 1; } fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED; } // create a one cluster run else { TSK_FS_ATTR_RUN *data_run_tmp = tsk_fs_attr_run_alloc(); if (data_run_tmp == NULL) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; return 1; } data_run_tmp->addr = sbase; data_run_tmp->len = fatfs->csize; // initialize the data run if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run_tmp, NULL, TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT, fs_meta->size, roundup(fs_meta->size, fs->block_size), 0, 0)) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; return 1; } fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED; } return 0; } /* Normal cluster chain walking */ else { TSK_LIST *list_seen = NULL; TSK_FS_ATTR_RUN *data_run = NULL; TSK_FS_ATTR_RUN *data_run_head = NULL; TSK_OFF_T full_len_s = 0; TSK_DADDR_T sbase; if (tsk_verbose) tsk_fprintf(stderr, "fatfs_make_data_run: Processing file %" PRIuINUM " in normal mode\n", fs_meta->addr); /* Cycle through the cluster chain */ while ((clust & fatfs->mask) > 0 && (int64_t) size_remain > 0 && (0 == FATFS_ISEOF(clust, fatfs->mask))) { /* Convert the cluster addr to a sector addr */ sbase = FATFS_CLUST_2_SECT(fatfs, clust); if (sbase > fs->last_block) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; tsk_error_reset(); tsk_errno = TSK_ERR_FS_INODE_COR; snprintf(tsk_errstr, TSK_ERRSTR_L, "fatfs_make_data_run: Invalid sector address in FAT (too large): %" PRIuDADDR, sbase); return 1; } // see if we need a new run if ((data_run == NULL) || (data_run->addr + data_run->len != sbase)) { TSK_FS_ATTR_RUN *data_run_tmp = tsk_fs_attr_run_alloc(); if (data_run_tmp == NULL) { tsk_fs_attr_run_free(data_run_head); fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; return 1; } if (data_run_head == NULL) { data_run_head = data_run_tmp; data_run_tmp->offset = 0; } else if (data_run != NULL) { data_run->next = data_run_tmp; data_run_tmp->offset = data_run->offset + data_run->len; } data_run = data_run_tmp; data_run->len = 0; data_run->addr = sbase; } data_run->len += fatfs->csize; full_len_s += fatfs->csize; size_remain -= (fatfs->csize * fs->block_size); if ((int64_t) size_remain > 0) { TSK_DADDR_T nxt; if (fatfs_getFAT(fatfs, clust, &nxt)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "file walk: Inode: %" PRIuINUM " cluster: %" PRIuDADDR, fs_meta->addr, clust); fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; tsk_fs_attr_run_free(data_run_head); tsk_list_free(list_seen); list_seen = NULL; return 1; } clust = nxt; /* Make sure we do not get into an infinite loop */ if (tsk_list_find(list_seen, clust)) { if (tsk_verbose) tsk_fprintf(stderr, "Loop found while processing file\n"); break; } if (tsk_list_add(&list_seen, clust)) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; tsk_list_free(list_seen); list_seen = NULL; return 1; } } } // add the run list to the inode structure if ((fs_attr = tsk_fs_attrlist_getnew(fs_meta->attr, TSK_FS_ATTR_NONRES)) == NULL) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; return 1; } // initialize the data run if (tsk_fs_attr_set_run(a_fs_file, fs_attr, data_run_head, NULL, TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT, fs_meta->size, roundup(fs_meta->size, fs->block_size), 0, 0)) { fs_meta->attr_state = TSK_FS_META_ATTR_ERROR; return 1; } tsk_list_free(list_seen); list_seen = NULL; fs_meta->attr_state = TSK_FS_META_ATTR_STUDIED; return 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -