📄 fatfs_meta.c
字号:
/*** fatfs** The Sleuth Kit **** Content and meta data layer support for the FAT file system **** Brian Carrier [carrier <at> sleuthkit [dot] org]** Copyright (c) 2006-2008 Brian Carrier, Basis Technology. All Rights reserved** Copyright (c) 2003-2005 Brian Carrier. All rights reserved **** TASK** Copyright (c) 2002 Brian Carrier, @stake Inc. All rights reserved****** This software is distributed under the Common Public License 1.0**** Unicode added with support from I.D.E.A.L. Technology Corp (Aug '05)***//** * \file fatfs_meta.c * Contains the internal TSK FAT file system code to handle metadata structures. */#include "tsk_fs_i.h"#include "tsk_fatfs.h"/* * Identify if the dentry is a valid 8.3 name * * returns 1 if it is, 0 if it does not */static uint8_tis_83_name(fatfs_dentry * de){ if (!de) return 0; /* The IS_NAME macro will fail if the value is 0x05, which is only * valid in name[0], similarly with '.' */ if ((de->name[0] != FATFS_SLOT_E5) && (de->name[0] != '.') && (FATFS_IS_83_NAME(de->name[0]) == 0)) return 0; // the name cannot start with 0x20 if (de->name[0] == 0x20) return 0; /* the second name field can only be . if the first one is a . */ if (de->name[1] == '.') { if (de->name[0] != '.') return 0; } else if (FATFS_IS_83_NAME(de->name[1]) == 0) return 0; if ((FATFS_IS_83_NAME(de->name[2]) == 0) || (FATFS_IS_83_NAME(de->name[3]) == 0) || (FATFS_IS_83_NAME(de->name[4]) == 0) || (FATFS_IS_83_NAME(de->name[5]) == 0) || (FATFS_IS_83_NAME(de->name[6]) == 0) || (FATFS_IS_83_NAME(de->name[7]) == 0) || (FATFS_IS_83_EXT(de->ext[0]) == 0) || (FATFS_IS_83_EXT(de->ext[1]) == 0) || (FATFS_IS_83_EXT(de->ext[2]) == 0)) return 0; /* Ensure that if we get a "space", that the rest of the * name is spaces. This is not in the spec, but is how * windows operates and serves as a good check to remove * false positives. We do not do this check for the * volume label though. */ if ((de->attrib & FATFS_ATTR_VOLUME) != FATFS_ATTR_VOLUME) { if (((de->name[1] == 0x20) && (de->name[2] != 0x20)) || ((de->name[2] == 0x20) && (de->name[3] != 0x20)) || ((de->name[3] == 0x20) && (de->name[4] != 0x20)) || ((de->name[4] == 0x20) && (de->name[5] != 0x20)) || ((de->name[5] == 0x20) && (de->name[6] != 0x20)) || ((de->name[6] == 0x20) && (de->name[7] != 0x20)) || ((de->ext[1] == 0x20) && (de->ext[2] != 0x20))) return 0; } return 1;}/*** Convert the DOS time to the UNIX version** ** UNIX stores the time in seconds from 1970 in UTC** FAT dates are the actual date with the year relative to 1980** */static time_tdos2unixtime(uint16_t date, uint16_t time){ struct tm tm1; time_t ret; if (date == 0) return 0; memset(&tm1, 0, sizeof(struct tm)); tm1.tm_sec = ((time & FATFS_SEC_MASK) >> FATFS_SEC_SHIFT) * 2; if ((tm1.tm_sec < 0) || (tm1.tm_sec > 60)) tm1.tm_sec = 0; tm1.tm_min = ((time & FATFS_MIN_MASK) >> FATFS_MIN_SHIFT); if ((tm1.tm_min < 0) || (tm1.tm_min > 59)) tm1.tm_min = 0; tm1.tm_hour = ((time & FATFS_HOUR_MASK) >> FATFS_HOUR_SHIFT); if ((tm1.tm_hour < 0) || (tm1.tm_hour > 23)) tm1.tm_hour = 0; tm1.tm_mday = ((date & FATFS_DAY_MASK) >> FATFS_DAY_SHIFT); if ((tm1.tm_mday < 1) || (tm1.tm_mday > 31)) tm1.tm_mday = 0; tm1.tm_mon = ((date & FATFS_MON_MASK) >> FATFS_MON_SHIFT) - 1; if ((tm1.tm_mon < 0) || (tm1.tm_mon > 11)) tm1.tm_mon = 0; /* There is a limit to the year because the UNIX time value is * a 32-bit value * the maximum UNIX time is Tue Jan 19 03:14:07 2038 */ tm1.tm_year = ((date & FATFS_YEAR_MASK) >> FATFS_YEAR_SHIFT) + 80; if ((tm1.tm_year < 0) || (tm1.tm_year > 137)) tm1.tm_year = 0; /* set the daylight savings variable to -1 so that mktime() figures * it out */ tm1.tm_isdst = -1; ret = mktime(&tm1); if (ret < 0) { if (tsk_verbose) tsk_fprintf(stderr, "dos2unixtime: Error running mktime(): %d:%d:%d %d/%d/%d", ((time & FATFS_HOUR_MASK) >> FATFS_HOUR_SHIFT), ((time & FATFS_MIN_MASK) >> FATFS_MIN_SHIFT), ((time & FATFS_SEC_MASK) >> FATFS_SEC_SHIFT) * 2, ((date & FATFS_MON_MASK) >> FATFS_MON_SHIFT) - 1, ((date & FATFS_DAY_MASK) >> FATFS_DAY_SHIFT), ((date & FATFS_YEAR_MASK) >> FATFS_YEAR_SHIFT) + 80); return 0; } return ret;}/* * convert the attribute list in FAT to a UNIX mode */static TSK_FS_META_TYPE_ENUMattr2type(uint16_t attr){ if (attr & FATFS_ATTR_DIRECTORY) return TSK_FS_META_TYPE_DIR; else return TSK_FS_META_TYPE_REG;}static intattr2mode(uint16_t attr){ int mode; /* every file is executable */ mode = (TSK_FS_META_MODE_IXUSR | TSK_FS_META_MODE_IXGRP | TSK_FS_META_MODE_IXOTH); if ((attr & FATFS_ATTR_READONLY) == 0) mode |= (TSK_FS_META_MODE_IRUSR | TSK_FS_META_MODE_IRGRP | TSK_FS_META_MODE_IROTH); if ((attr & FATFS_ATTR_HIDDEN) == 0) mode |= (TSK_FS_META_MODE_IWUSR | TSK_FS_META_MODE_IWGRP | TSK_FS_META_MODE_IWOTH); return mode;}/** * \internal * Copy the contents of a raw directry entry into a TSK_FS_INFO structure. * * @param fatfs File system that directory entry is from * @param fs_meta Generic inode structure to copy data into * @param in Directory entry to copy data from * @param sect Sector address where directory entry is from -- used * to determine allocation status. * @param inum Address of the inode. * * @returns 1 on error and 0 on success. Errors should only occur for * Unicode conversion problems and when this occurs the name will be * NULL terminated (but with unknown contents). * */TSK_RETVAL_ENUMfatfs_dinode_copy(FATFS_INFO * fatfs, TSK_FS_META * fs_meta, fatfs_dentry * in, TSK_DADDR_T sect, TSK_INUM_T inum){ int retval; int i; TSK_FS_INFO *fs = (TSK_FS_INFO *) & fatfs->fs_info; TSK_DADDR_T *addr_ptr; if (fs_meta->content_len < FATFS_FILE_CONTENT_LEN) { if ((fs_meta = tsk_fs_meta_realloc(fs_meta, FATFS_FILE_CONTENT_LEN)) == NULL) { return 1; } } fs_meta->attr_state = TSK_FS_META_ATTR_EMPTY; if (fs_meta->attr) { tsk_fs_attrlist_markunused(fs_meta->attr); } fs_meta->mode = attr2mode(in->attrib); fs_meta->type = attr2type(in->attrib); fs_meta->addr = inum; /* Use the allocation status of the sector to determine if the * dentry is allocated or not */ retval = fatfs_is_sectalloc(fatfs, sect); if (retval == -1) { return TSK_ERR; } else if (retval == 1) { fs_meta->flags = ((in->name[0] == FATFS_SLOT_DELETED) ? TSK_FS_META_FLAG_UNALLOC : TSK_FS_META_FLAG_ALLOC); } else { fs_meta->flags = TSK_FS_META_FLAG_UNALLOC; } /* Slot has not been used yet */ fs_meta->flags |= ((in->name[0] == FATFS_SLOT_EMPTY) ? TSK_FS_META_FLAG_UNUSED : TSK_FS_META_FLAG_USED); if ((in->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) { /* LFN entries don't have these values */ fs_meta->nlink = 0; fs_meta->size = 0; fs_meta->mtime = 0; fs_meta->atime = 0; fs_meta->ctime = 0; fs_meta->crtime = 0; } else { /* There is no notion of link in FAT, just deleted or not */ fs_meta->nlink = (in->name[0] == FATFS_SLOT_DELETED) ? 0 : 1; fs_meta->size = (TSK_OFF_T) tsk_getu32(fs->endian, in->size); /* If these are valid dates, then convert to a unix date format */ if (FATFS_ISDATE(tsk_getu16(fs->endian, in->wdate))) fs_meta->mtime = dos2unixtime(tsk_getu16(fs->endian, in->wdate), tsk_getu16(fs->endian, in->wtime)); else fs_meta->mtime = 0; if (FATFS_ISDATE(tsk_getu16(fs->endian, in->adate))) fs_meta->atime = dos2unixtime(tsk_getu16(fs->endian, in->adate), 0); else fs_meta->atime = 0; /* cdate is the creation date in FAT and there is no change, * so we just put in into change and set create to 0. The other * front-end code knows how to handle it and display it */ if (FATFS_ISDATE(tsk_getu16(fs->endian, in->cdate))) fs_meta->crtime = dos2unixtime(tsk_getu16(fs->endian, in->cdate), tsk_getu16(fs->endian, in->ctime)); else fs_meta->crtime = 0; // FAT does not have a changed time fs_meta->ctime = 0; } /* Values that do not exist in FAT */ fs_meta->uid = 0; fs_meta->gid = 0; fs_meta->seq = 0; /* We will be copying a name, so allocate a structure */ if (fs_meta->name2 == NULL) { if ((fs_meta->name2 = (TSK_FS_META_NAME_LIST *) tsk_malloc(sizeof(TSK_FS_META_NAME_LIST))) == NULL) return TSK_ERR; fs_meta->name2->next = NULL; } /* If we have a LFN entry, then we need to convert the three * parts of the name to UTF-8 and copy it into the name structure . */ if ((in->attrib & FATFS_ATTR_LFN) == FATFS_ATTR_LFN) { fatfs_dentry_lfn *lfn = (fatfs_dentry_lfn *) in; /* Convert the first part of the name */ UTF8 *name8 = (UTF8 *) fs_meta->name2->name; UTF16 *name16 = (UTF16 *) lfn->part1; int retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16, (UTF16 *) & lfn->part1[10], &name8, (UTF8 *) ((uintptr_t) fs_meta->name2->name + sizeof(fs_meta->name2->name)), TSKlenientConversion); if (retVal != TSKconversionOK) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNICODE; snprintf(tsk_errstr, TSK_ERRSTR_L, "fatfs_dinode_copy: Error converting FAT LFN (1) to UTF8: %d", retVal); *name8 = '\0'; return TSK_COR; } /* Convert the second part of the name */ name16 = (UTF16 *) lfn->part2; retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16, (UTF16 *) & lfn->part2[12], &name8, (UTF8 *) ((uintptr_t) fs_meta->name2-> name + sizeof(fs_meta->name2->name)), TSKlenientConversion); if (retVal != TSKconversionOK) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNICODE; snprintf(tsk_errstr, TSK_ERRSTR_L, "fatfs_dinode_copy: Error converting FAT LFN (2) to UTF8: %d", retVal); *name8 = '\0'; return TSK_COR; } /* Convert the third part of the name */ name16 = (UTF16 *) lfn->part3; retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16, (UTF16 *) & lfn->part3[4], &name8, (UTF8 *) ((uintptr_t) fs_meta->name2-> name + sizeof(fs_meta->name2->name)), TSKlenientConversion); if (retVal != TSKconversionOK) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNICODE; snprintf(tsk_errstr, TSK_ERRSTR_L, "fatfs_dinode_copy: Error converting FAT LFN (3) to UTF8: %d",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -