static int FuseHFS_removexattr(const char *path, const char *name) { dprintf("removexattr %s %s\n", path, name); if (_readonly) return -EPERM; // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; // find file hfsdirent ent; if (hfs_stat(NULL, hfspath, &ent) == -1) { free(hfspath); return -ENOENT; } if (strcmp(name, XATTR_FINDERINFO_NAME) == 0) { free(hfspath); // not really removing it return 0; } else if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && (!(ent.flags & HFS_ISDIR))) { // resource fork hfsfile *fp = hfs_open(NULL, hfspath); hfs_setfork(fp, 1); hfs_seek(fp, 0, SEEK_SET); hfs_truncate(fp, 0); hfs_close(fp); free(hfspath); return 0; } free(hfspath); return -ENOATTR; }
/* * NAME: opensrc() * DESCRIPTION: open the source file; set hint for destination filename */ static hfsfile *opensrc(hfsvol *vol, const char *srcname, const char **dsthint, const char *ext) { hfsfile *file; hfsdirent ent; static char name[HFS_MAX_FLEN + 4 + 1]; char *ptr; file = hfs_open(vol, srcname); if (file == 0) { ERROR(errno, hfs_error); return 0; } if (hfs_fstat(file, &ent) == -1) { ERROR(errno, hfs_error); hfs_close(file); return 0; } strcpy(name, ent.name); for (ptr = name; *ptr; ++ptr) { switch (*ptr) { case '/': *ptr = '-'; break; case ' ': *ptr = '_'; break; } } if (ext) strcat(name, ext); *dsthint = name; return file; }
static int FuseHFS_truncate (const char *path, off_t length) { dprintf("truncate %s %lu\n", path, length); if (_readonly) return -EPERM; // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; hfsfile *file = hfs_open(NULL, hfspath); free(hfspath); if (file == NULL) return -errno; if (hfs_truncate(file, length) == -1) { hfs_close(file); perror("truncate"); return -errno; } hfs_close(file); return 0; }
static int FuseHFS_open(const char *path, struct fuse_file_info *fi) { dprintf("open %s\n", path); // apparently, MacFUSE won't open the same file more than once. This won't break if it stays this way. // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; // open file hfsfile *file = NULL; if ((file = hfs_open(NULL, hfspath))) { // file fi->fh = (uint64_t)file; free(hfspath); return 0; } free(hfspath); perror("hfs_open"); return -errno; }
static int FuseHFS_create(const char *path, mode_t mode, struct fuse_file_info *fi) { dprintf("create %s\n", path); if (_readonly) return -EPERM; // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; // open file hfsfile *file; if ((file = hfs_create(NULL, hfspath, "TEXT", "FUSE"))) { // close and reopen, because it won't exist until it's closed hfs_close(file); file = hfs_open(NULL, hfspath); fi->fh = (uint64_t)file; free(hfspath); return 0; } free(hfspath); perror("hfs_create"); return -errno; }
static int FuseHFS_setxattr(const char *path, const char *name, const char *value, size_t size, int flags, uint32_t position) { dprintf("setxattr %s %s %p %lu %02x %u\n", path, name, value, size, flags, position); if (_readonly) return -EPERM; // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; // find file hfsdirent ent; if (hfs_stat(NULL, hfspath, &ent) == -1) { free(hfspath); return -ENOENT; } if (strcmp(name, XATTR_FINDERINFO_NAME) == 0) { if (size != 32) { dprintf("setxattr: finder info is not 32 bytes\n"); free(hfspath); return -ERANGE; } // write finder info to dirent if (ent.flags & HFS_ISDIR) { // directory ent.u.dir.rect.top = OSReadBigInt16(value, 0); ent.u.dir.rect.left = OSReadBigInt16(value, 2); ent.u.dir.rect.bottom = OSReadBigInt16(value, 4); ent.u.dir.rect.right = OSReadBigInt16(value, 6); ent.fdflags = OSReadBigInt16(value, 8); ent.fdlocation.v = OSReadBigInt16(value, 10); ent.fdlocation.h = OSReadBigInt16(value, 12); ent.u.dir.view = OSReadBigInt16(value, 14); // DXInfo ((DXInfo*)(ent.u.dir.xinfo))->frScroll.v = OSReadBigInt16(value, 16); ((DXInfo*)(ent.u.dir.xinfo))->frScroll.h = OSReadBigInt16(value, 18); ((DXInfo*)(ent.u.dir.xinfo))->frOpenChain = OSReadBigInt32(value, 20); ((DXInfo*)(ent.u.dir.xinfo))->frUnused = OSReadBigInt16(value, 24); ((DXInfo*)(ent.u.dir.xinfo))->frComment = OSReadBigInt16(value, 26); ((DXInfo*)(ent.u.dir.xinfo))->frPutAway = OSReadBigInt32(value, 28); } else { // regular file memcpy(ent.u.file.type, value, 4); memcpy(ent.u.file.creator, value+4, 4); ent.u.file.type[4] = ent.u.file.type[4] = '\0'; ent.fdflags = OSReadBigInt16(value, 8); ent.fdlocation.v = OSReadBigInt16(value, 10); ent.fdlocation.h = OSReadBigInt16(value, 12); ent.u.file.window = OSReadBigInt16(value, 14); // FXInfo ((FXInfo*)(ent.u.file.xinfo))->fdIconID = OSReadBigInt16(value, 16); ((FXInfo*)(ent.u.file.xinfo))->fdUnused[0] = OSReadBigInt16(value, 18); ((FXInfo*)(ent.u.file.xinfo))->fdUnused[1] = OSReadBigInt16(value, 20); ((FXInfo*)(ent.u.file.xinfo))->fdUnused[2] = OSReadBigInt16(value, 22); ((FXInfo*)(ent.u.file.xinfo))->fdUnused[3] = OSReadBigInt16(value, 24); ((FXInfo*)(ent.u.file.xinfo))->fdComment = OSReadBigInt16(value, 26); ((FXInfo*)(ent.u.file.xinfo))->fdPutAway = OSReadBigInt32(value, 28); // bless parent folder if it's a system file if ((strcmp(ent.u.file.type, "zsys") == 0) && (strcmp(ent.u.file.creator, "MACS") == 0) && (strcmp(ent.name, "System") == 0)) { // bless dprintf("setxattr: blessing folder %lu\n", ent.parid); hfsvolent volent; hfs_vstat(NULL, &volent); volent.blessed = ent.parid; hfs_vsetattr(NULL, &volent); } } // update file hfs_setattr(NULL, hfspath, &ent); free(hfspath); return 0; } else if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && (!(ent.flags & HFS_ISDIR))) { // resource fork // TODO: how are resource forks truncated? hfsfile *fp = hfs_open(NULL, hfspath); hfs_setfork(fp, 1); hfs_seek(fp, position, SEEK_SET); hfs_write(fp, value, size); hfs_close(fp); // the end free(hfspath); return 0; } else { free(hfspath); return 0; } free(hfspath); return -ENOATTR; }
static int FuseHFS_getxattr(const char *path, const char *name, char *value, size_t size, uint32_t position) { //dprintf("getxattr %s %s %p %lu %u\n", path, name, value, size, position); // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; // find file hfsdirent ent; if (hfs_stat(NULL, hfspath, &ent) == -1) { free(hfspath); return -ENOENT; } if (strcmp(name, XATTR_FINDERINFO_NAME) == 0) { if (value == NULL) { free(hfspath); return 32; } if (size < 32) { free(hfspath); return -ERANGE; } // return finder info if (ent.flags & HFS_ISDIR) { // directory info OSWriteBigInt16(value, 0, ent.u.dir.rect.top); OSWriteBigInt16(value, 2, ent.u.dir.rect.left); OSWriteBigInt16(value, 4, ent.u.dir.rect.bottom); OSWriteBigInt16(value, 6, ent.u.dir.rect.right); OSWriteBigInt16(value, 8, ent.fdflags); OSWriteBigInt16(value, 10, ent.fdlocation.v); OSWriteBigInt16(value, 12, ent.fdlocation.h); OSWriteBigInt16(value, 14, ent.u.dir.view); // DXInfo OSWriteBigInt16(value, 16, ((DXInfo*)(ent.u.dir.xinfo))->frScroll.v); OSWriteBigInt16(value, 18, ((DXInfo*)(ent.u.dir.xinfo))->frScroll.h); OSWriteBigInt32(value, 20, ((DXInfo*)(ent.u.dir.xinfo))->frOpenChain); OSWriteBigInt16(value, 24, ((DXInfo*)(ent.u.dir.xinfo))->frUnused); OSWriteBigInt16(value, 26, ((DXInfo*)(ent.u.dir.xinfo))->frComment); OSWriteBigInt32(value, 28, ((DXInfo*)(ent.u.dir.xinfo))->frPutAway); } else { // file info memcpy(value, ent.u.file.type, 4); memcpy(value+4, ent.u.file.creator, 4); OSWriteBigInt16(value, 8, ent.fdflags); OSWriteBigInt16(value, 10, ent.fdlocation.v); OSWriteBigInt16(value, 12, ent.fdlocation.h); OSWriteBigInt16(value, 14, ent.u.file.window); // FXInfo OSWriteBigInt16(value, 16, ((FXInfo*)(ent.u.file.xinfo))->fdIconID); OSWriteBigInt16(value, 18, ((FXInfo*)(ent.u.file.xinfo))->fdUnused[0]); OSWriteBigInt16(value, 20, ((FXInfo*)(ent.u.file.xinfo))->fdUnused[1]); OSWriteBigInt16(value, 22, ((FXInfo*)(ent.u.file.xinfo))->fdUnused[2]); OSWriteBigInt16(value, 24, ((FXInfo*)(ent.u.file.xinfo))->fdUnused[3]); OSWriteBigInt16(value, 26, ((FXInfo*)(ent.u.file.xinfo))->fdComment); OSWriteBigInt32(value, 28, ((FXInfo*)(ent.u.file.xinfo))->fdPutAway); } free(hfspath); return 32; } else if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && (!(ent.flags & HFS_ISDIR)) && ent.u.file.rsize) { // resource fork if (value == NULL) { free(hfspath); return ent.u.file.rsize-position; } int bw = ent.u.file.rsize-position; if (bw > size) bw = size; // copy resource fork hfsfile *fp = hfs_open(NULL, hfspath); hfs_setfork(fp, 1); hfs_seek(fp, position, SEEK_SET); hfs_read(fp, value, bw); hfs_close(fp); // the end free(hfspath); return bw; } free(hfspath); dprintf("getxattr: ENOATTR\n"); return -ENOATTR; }
TSK_FS_INFO * tsk_fs_open(TSK_IMG_INFO * img_info, TSK_OFF_T offset, const TSK_TCHAR * type) { /* We will try different file systems ... * We need to try all of them in case more than one matches */ if (type == NULL) { TSK_FS_INFO *fs_info, *fs_set = NULL; char *set = NULL; if (tsk_verbose) tsk_fprintf(stderr, "fsopen: Auto detection mode at offset %" PRIuOFF "\n", offset); if ((fs_info = ntfs_open(img_info, offset, TSK_FS_INFO_TYPE_NTFS_AUTO, 1)) != NULL) { set = "NTFS"; fs_set = fs_info; } else { tsk_error_reset(); } if ((fs_info = fatfs_open(img_info, offset, TSK_FS_INFO_TYPE_FAT_AUTO, 1)) != NULL) { if (set == NULL) { set = "FAT"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "FAT or %s", set); return NULL; } } else { tsk_error_reset(); } if ((fs_info = ext2fs_open(img_info, offset, TSK_FS_INFO_TYPE_EXT_AUTO, 1)) != NULL) { if (set == NULL) { set = "EXT2/3"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "EXT2/3 or %s", set); return NULL; } } else { tsk_error_reset(); } if ((fs_info = ffs_open(img_info, offset, TSK_FS_INFO_TYPE_FFS_AUTO)) != NULL) { if (set == NULL) { set = "UFS"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "UFS or %s", set); return NULL; } } else { tsk_error_reset(); } #if TSK_USE_HFS if ((fs_info = hfs_open(img_info, offset, TSK_FS_INFO_TYPE_HFS, 1)) != NULL) { if (set == NULL) { set = "HFS"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "HFS or %s", set); return NULL; } } else { tsk_error_reset(); } #endif if ((fs_info = iso9660_open(img_info, offset, TSK_FS_INFO_TYPE_ISO9660, 1)) != NULL) { if (set != NULL) { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "ISO9660 or %s", set); return NULL; } fs_set = fs_info; } else { tsk_error_reset(); } if (fs_set == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; tsk_errstr[0] = '\0'; tsk_errstr2[0] = '\0'; return NULL; } return fs_set; } else { uint8_t ftype; ftype = tsk_fs_parse_type(type); switch (ftype & TSK_FS_INFO_TYPE_FS_MASK) { case TSK_FS_INFO_TYPE_FFS_TYPE: return ffs_open(img_info, offset, ftype); case TSK_FS_INFO_TYPE_EXT_TYPE: return ext2fs_open(img_info, offset, ftype, 0); case TSK_FS_INFO_TYPE_FAT_TYPE: return fatfs_open(img_info, offset, ftype, 0); case TSK_FS_INFO_TYPE_NTFS_TYPE: return ntfs_open(img_info, offset, ftype, 0); case TSK_FS_INFO_TYPE_ISO9660_TYPE: return iso9660_open(img_info, offset, ftype, 0); #if 0 case TSK_FS_INFO_TYPE_HFS_TYPE: return hfs_open(img_info, offset, ftype, 0); #endif case TSK_FS_INFO_TYPE_RAW_TYPE: return rawfs_open(img_info, offset); case TSK_FS_INFO_TYPE_SWAP_TYPE: return swapfs_open(img_info, offset); case TSK_FS_INFO_TYPE_UNSUPP: default: tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNSUPTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "%s", type); return NULL; } } }
/** * \ingroup fslib * Tries to process data in a disk image at a given offset as a file system. * Returns a structure that can be used for analysis and reporting. * * @param a_img_info Disk image to analyze * @param a_offset Byte offset to start analyzing from * @param a_ftype Type of file system (or autodetect) * * @return NULL on error */ TSK_FS_INFO * tsk_fs_open_img(TSK_IMG_INFO * a_img_info, TSK_OFF_T a_offset, TSK_FS_TYPE_ENUM a_ftype) { if (a_img_info == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_fs_open_img: Null image handle"); return NULL; } /* We will try different file systems ... * We need to try all of them in case more than one matches */ if (a_ftype == TSK_FS_TYPE_DETECT) { TSK_FS_INFO *fs_info, *fs_set = NULL; char *set = NULL; if (tsk_verbose) tsk_fprintf(stderr, "fsopen: Auto detection mode at offset %" PRIuOFF "\n", a_offset); if ((fs_info = ntfs_open(a_img_info, a_offset, TSK_FS_TYPE_NTFS_DETECT, 1)) != NULL) { set = "NTFS"; fs_set = fs_info; } else { tsk_error_reset(); } if ((fs_info = fatfs_open(a_img_info, a_offset, TSK_FS_TYPE_FAT_DETECT, 1)) != NULL) { if (set == NULL) { set = "FAT"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "FAT or %s", set); return NULL; } } else { tsk_error_reset(); } if ((fs_info = ext2fs_open(a_img_info, a_offset, TSK_FS_TYPE_EXT_DETECT, 1)) != NULL) { if (set == NULL) { set = "EXT2/3"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "EXT2/3 or %s", set); return NULL; } } else { tsk_error_reset(); } if ((fs_info = ffs_open(a_img_info, a_offset, TSK_FS_TYPE_FFS_DETECT)) != NULL) { if (set == NULL) { set = "UFS"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "UFS or %s", set); return NULL; } } else { tsk_error_reset(); } #if TSK_USE_HFS if ((fs_info = hfs_open(a_img_info, a_offset, TSK_FS_TYPE_HFS_DETECT, 1)) != NULL) { if (set == NULL) { set = "HFS"; fs_set = fs_info; } else { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "HFS or %s", set); return NULL; } } else { tsk_error_reset(); } #endif if ((fs_info = iso9660_open(a_img_info, a_offset, TSK_FS_TYPE_ISO9660_DETECT, 1)) != NULL) { if (set != NULL) { fs_set->close(fs_set); fs_info->close(fs_info); tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "ISO9660 or %s", set); return NULL; } fs_set = fs_info; } else { tsk_error_reset(); } if (fs_set == NULL) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNKTYPE; tsk_errstr[0] = '\0'; tsk_errstr2[0] = '\0'; return NULL; } return fs_set; } else { if (TSK_FS_TYPE_ISNTFS(a_ftype)) return ntfs_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISFAT(a_ftype)) return fatfs_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISFFS(a_ftype)) return ffs_open(a_img_info, a_offset, a_ftype); else if (TSK_FS_TYPE_ISEXT(a_ftype)) return ext2fs_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISHFS(a_ftype)) return hfs_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISISO9660(a_ftype)) return iso9660_open(a_img_info, a_offset, a_ftype, 0); else if (TSK_FS_TYPE_ISRAW(a_ftype)) return rawfs_open(a_img_info, a_offset); else if (TSK_FS_TYPE_ISSWAP(a_ftype)) return swapfs_open(a_img_info, a_offset); else { tsk_error_reset(); tsk_errno = TSK_ERR_FS_UNSUPTYPE; snprintf(tsk_errstr, TSK_ERRSTR_L, "%X", (int) a_ftype); return NULL; } } }
PedFileSystem* hfsplus_open (PedGeometry* geom) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; PedFileSystem* fs; HfsPVolumeHeader* vh; HfsPPrivateFSData* priv_data; PedGeometry* wrapper_geom; unsigned int map_sectors; if (!hfsc_can_use_geom (geom)) return NULL; fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); if (!fs) goto hpo; vh = (HfsPVolumeHeader*) ped_malloc (sizeof (HfsPVolumeHeader)); if (!vh) goto hpo_fs; priv_data = (HfsPPrivateFSData*)ped_malloc (sizeof (HfsPPrivateFSData)); if (!priv_data) goto hpo_vh; fs->geom = ped_geometry_duplicate (geom); if (!fs->geom) goto hpo_pd; fs->type_specific = (void*) priv_data; if ((wrapper_geom = hfs_and_wrapper_probe (geom))) { HfsPrivateFSData* hfs_priv_data; PedSector abs_sect, length; unsigned int bs; ped_geometry_destroy (wrapper_geom); priv_data->wrapper = hfs_open(geom); if (!priv_data->wrapper) goto hpo_gm; hfs_priv_data = (HfsPrivateFSData*) priv_data->wrapper->type_specific; bs = PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) / PED_SECTOR_SIZE_DEFAULT; abs_sect = (PedSector) geom->start + (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb->start_block) + (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb->old_new .embedded.location.start_block ) * bs; length = (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb->old_new .embedded.location.block_count) * bs; priv_data->plus_geom = ped_geometry_new (geom->dev, abs_sect, length); if (!priv_data->plus_geom) goto hpo_wr; priv_data->free_geom = 1; } else { priv_data->wrapper = NULL; priv_data->plus_geom = fs->geom; priv_data->free_geom = 0; } if (!ped_geometry_read (priv_data->plus_geom, buf, 2, 1)) goto hpo_pg; memcpy (vh, buf, sizeof (HfsPVolumeHeader)); priv_data->vh = vh; if (vh->signature != PED_CPU_TO_BE16(HFSP_SIGNATURE) && vh->signature != PED_CPU_TO_BE16(HFSX_SIGNATURE)) { ped_exception_throw ( PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL, _("No valid HFS[+X] signature has been found while " "opening.")); goto hpo_pg; } if (vh->signature == PED_CPU_TO_BE16(HFSP_SIGNATURE) && vh->version != PED_CPU_TO_BE16(HFSP_VERSION)) { if (ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_IGNORE_CANCEL, _("Version %d of HFS+ isn't supported."), PED_BE16_TO_CPU(vh->version)) != PED_EXCEPTION_IGNORE) goto hpo_pg; } if (vh->signature == PED_CPU_TO_BE16(HFSX_SIGNATURE) && vh->version != PED_CPU_TO_BE16(HFSX_VERSION)) { if (ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_IGNORE_CANCEL, _("Version %d of HFSX isn't supported."), PED_BE16_TO_CPU(vh->version)) != PED_EXCEPTION_IGNORE) goto hpo_pg; } priv_data->jib_start_block = 0; priv_data->jl_start_block = 0; if (vh->attributes & PED_CPU_TO_BE32(1<<HFSP_JOURNALED)) { if (!hfsj_replay_journal(fs)) goto hpo_pg; } priv_data->bad_blocks_loaded = 0; priv_data->bad_blocks_xtent_nb = 0; priv_data->bad_blocks_xtent_list = NULL; priv_data->extents_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_XTENT_ID), vh->extents_file.extents, PED_BE64_TO_CPU ( vh->extents_file.logical_size ) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->extents_file) goto hpo_pg; priv_data->catalog_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_CATALOG_ID), vh->catalog_file.extents, PED_BE64_TO_CPU ( vh->catalog_file.logical_size ) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->catalog_file) goto hpo_ce; priv_data->attributes_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ATTRIB_ID), vh->attributes_file.extents, PED_BE64_TO_CPU ( vh->attributes_file.logical_size) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->attributes_file) goto hpo_cc; map_sectors = ( PED_BE32_TO_CPU (vh->total_blocks) + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8); priv_data->dirty_alloc_map = (uint8_t*) ped_malloc ((map_sectors + 7) / 8); if (!priv_data->dirty_alloc_map) goto hpo_cl; memset(priv_data->dirty_alloc_map, 0, (map_sectors + 7) / 8); priv_data->alloc_map = (uint8_t*) ped_malloc (map_sectors * PED_SECTOR_SIZE_DEFAULT); if (!priv_data->alloc_map) goto hpo_dm; priv_data->allocation_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ALLOC_ID), vh->allocation_file.extents, PED_BE64_TO_CPU ( vh->allocation_file.logical_size) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->allocation_file) goto hpo_am; if (!hfsplus_file_read (priv_data->allocation_file, priv_data->alloc_map, 0, map_sectors)) { hfsplus_close(fs); return NULL; } fs->type = &hfsplus_type; fs->checked = ((PED_BE32_TO_CPU (vh->attributes) >> HFS_UNMOUNTED) & 1) && !((PED_BE32_TO_CPU (vh->attributes) >> HFSP_INCONSISTENT) & 1); return fs; /*--- clean error handling ---*/ hpo_am: free(priv_data->alloc_map); hpo_dm: free(priv_data->dirty_alloc_map); hpo_cl: hfsplus_file_close (priv_data->attributes_file); hpo_cc: hfsplus_file_close (priv_data->catalog_file); hpo_ce: hfsplus_file_close (priv_data->extents_file); hpo_pg: if (priv_data->free_geom) ped_geometry_destroy (priv_data->plus_geom); hpo_wr: if (priv_data->wrapper) hfs_close(priv_data->wrapper); hpo_gm: ped_geometry_destroy (fs->geom); hpo_pd: free(priv_data); hpo_vh: free(vh); hpo_fs: free(fs); hpo: return NULL; }
int make_desktop(hfsvol *vol, int end) /* hfsvol *vol; Mac volume */ { hfsfile *hfp; /* Mac file */ hfsdirent ent; /* Mac finderinfo */ unsigned short clps; /* clump size */ unsigned short blks; /* blocks in a clump */ unsigned char *blk; /* user data */ int i; /* set up default directory entries - not all these fields are needed, but we'll set them up anyway ... */ ent.rsize = 0; /* resource size == 0 */ strcpy(ent.creator, DBFC); /* creator */ strcpy(ent.type, DBT); /* type */ ent.crdate = ent.mddate = time(0); /* date is now */ ent.fdflags = HFS_FNDR_ISINVISIBLE; /* invisible files */ /* clear the DB file */ blk = hce->hfs_ce + hce->hfs_ce_size*HFS_BLOCKSZ; blks = hce->hfs_dt_size; clps = blks*HFS_BLOCKSZ; memset(blk, 0, clps); /* create "Desktop DB" (if it doesn't exist) */ if(hfs_create(vol, DB, ent.type, ent.creator) == 0) { /* DB file size from hce_mem info */ /* set up "Desktop DB" data - following found by od'ing the "Desktop DB" file */ d_putw(blk+8, 0x100); d_putw(blk+10, 0x3); d_putw(blk+32, 0x200); d_putw(blk+34, 0x25); d_putl(blk+36, blks); d_putl(blk+40, blks - 1); d_putw(blk+48, clps); d_putw(blk+50, 0xff); d_putw(blk+120, 0x20a); d_putw(blk+122, 0x100); d_putw(blk+248, 0x8000); d_putl(blk+504, 0x1f800f8); d_putl(blk+508, 0x78000e); /* entries for "Desktop DB" */ ent.dsize = clps; /* size = clump size */ /* open file */ if((hfp = hfs_open(vol, DB)) == 0) err(1, hfs_error); /* "write" file */ write_fork(hfp, clps); /* set DB file attributes */ if (hfs_fsetattr(hfp, &ent) < 0) err(1, hfs_error); /* find the real start of the file */ end += hce->hfs_ce_size; /* close DB file */ if (hfs_close(hfp, end, 0) < 0) err(1, hfs_error); } else { /* if it already exists, then make sure it has the correct type/creator and flags */ if(hfs_setattr(vol, DB, &ent) < 0) err(1, hfs_error); } /* setup "Desktop DF" file as an empty file */ strcpy(ent.type, DFT); /* type */ ent.dsize = 0; /* empty */ /* create DF file (if it doesn't exist) - no need to open it */ hfs_create(vol, DF, ent.type, ent.creator); /* set DB file attributes */ if (hfs_setattr(vol, DF, &ent) < 0) err(1, hfs_error); return 0; }
/* copy_to_mac_vol: copy all files in a directory to corresponding ** Mac folder. ** ** Files are copied recursively to corresponding folders on the Mac ** volume. The caller routine needs to do a hfs_chdir before calling this ** routine. */ int FDECL2(copy_to_mac_vol, hfsvol *, vol, struct directory *, node) { struct directory_entry * s_entry; /* ISO directory entry */ struct directory_entry * s_entry1; /* tmp ISO directory entry */ struct directory *dpnt; /* ISO directory */ hfsfile *hfp; /* HFS file */ hfsdirent *ent; /* HFS file entities */ long id; /* current HFS folder */ long dext, rext; /* real data/rsrc start blk */ int ret; /* result code */ int new_name; /* HFS file has modified name */ int tens; int digits; int i; /* store the current HFS directory ID */ if ((id = hfs_getcwd(vol)) == 0) return(-1); if (verbose > 1) fprintf(stderr,"HFS scanning %s\n", node->whole_name); /* loop through the ISO directory entries and process files */ for(s_entry = node->contents; s_entry; s_entry = s_entry->next) { /* ignore directory and associated (rsrc) files */ if(s_entry->isorec.flags[0]) continue; /* ignore any non-Mac type file */ if(!s_entry->hfs_ent) continue; #ifdef DEBUG fprintf(stderr," Name = %s", s_entry->whole_name); fprintf(stderr," Startb = %d\n", s_entry->starting_block); #endif /* DEBUG */ ent = s_entry->hfs_ent; /* create file */ i = HFS_MAX_FLEN - strlen(ent->name); new_name = 0; tens = TEN; digits = 1; while (1) { /* try to open file - if it exists, then append '_' to the name and try again */ errno = 0; if ((hfs_create(vol, ent->name, ent->type, ent->creator)) < 0) { if (errno != EEXIST ) { /* not an "exist" error, or we can't append as the filename is already HFS_MAX_FLEN chars */ snprintf(hce->error, ERROR_SIZE, "can't HFS create file %s", s_entry->whole_name); return(-1); } else if (i == 0) { /* File name at max HFS length - make unique name */ if (!new_name) new_name++; sprintf(ent->name + HFS_MAX_FLEN - digits - 1, "%s%d", LCHAR, new_name); new_name++; if (new_name == tens) { tens *= TEN; digits++; } } else { /* append '_' to get new name */ strcat(ent->name, LCHAR); i--; new_name = 1; } } else break; } /* warn that we have a new name */ if (new_name && verbose > 0) { fprintf(stderr, "Using HFS name: %s for %s\n", ent->name, s_entry->whole_name); } /* open file */ if ((hfp = hfs_open(vol, ent->name)) == 0) { snprintf(hce->error, ERROR_SIZE, "can't HFS open %s", s_entry->whole_name); return(-1); } /* if it has a data fork, then "write" it out */ if (ent->dsize) write_fork(hfp, ent->dsize); /* if it has a resource fork, set the fork and "write" it out */ if (ent->rsize) { if ((hfs_setfork(hfp, 1)) < 0) return(-1); write_fork(hfp, ent->rsize); } /* update any HFS file attributes */ if ((hfs_fsetattr(hfp, ent)) < 0) { snprintf(hce->error, ERROR_SIZE, "can't HFS set attributes %s", s_entry->whole_name); return(-1); } /* get the ISO starting block of data fork (may be zero) and convert to the equivalent HFS block */ if (ent->dsize) dext = s_entry->starting_block * BLK_CONV; else dext = 0; /* if the file has a resource fork (associated file), get it's ISO starting block and convert as above */ if (s_entry->assoc && ent->rsize) rext = s_entry->assoc->starting_block * BLK_CONV; else rext = 0; /* close the file and update the starting blocks */ if (hfs_close(hfp, dext, rext) < 0) { snprintf(hce->error, ERROR_SIZE, "can't HFS close file %s", s_entry->whole_name); return(-1); } } /* process sub-directories - have a slight problem here, if the directory had been relocated, then we need to find the real directory - we do this by first finding the real directory_entry, and then finding it's directory info */ /* following code taken from joliet.c */ for(s_entry=node->contents;s_entry;s_entry=s_entry->next) { if((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) { /* if the directory has been reloacted, then search the relocated directory for the real entry */ for(s_entry1=reloc_dir->contents;s_entry1;s_entry1=s_entry1->next) { if(s_entry1->parent_rec == s_entry) break; } /* have a problem - can't find the real directory */ if(s_entry1 == NULL) { snprintf(hce->error, ERROR_SIZE, "can't locate relocated directory %s", s_entry->whole_name); return(-1); } } else s_entry1 = s_entry; /* now have the correct entry - now find the actual directory */ if ((s_entry1->isorec.flags[0] & 2) && strcmp(s_entry1->name,".") && strcmp(s_entry1->name,"..")) { if((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) dpnt = reloc_dir->subdir; else dpnt = node->subdir; while(1) { if (dpnt->self == s_entry1) break; dpnt = dpnt->next; if(!dpnt) { snprintf(hce->error, ERROR_SIZE, "can't find directory location %s", s_entry1->whole_name); return (-1); } } /* now have the correct directory - so do the HFS stuff */ ent = dpnt->hfs_ent; /* if we don't have hfs entries, then this is a "deep" directory - this will be processed later */ if (!ent) continue; /* make sub-folder */ i = HFS_MAX_FLEN - strlen(ent->name); new_name = 0; tens = TEN; digits = 1; while (1) { /* try to create new directory - if it exists, then append '_' to the name and try again */ errno = 0; if (hfs_mkdir(vol, ent->name) < 0) { if (errno != EEXIST) { /* not an "exist" error, or we can't append as the filename is already HFS_MAX_FLEN chars */ snprintf(hce->error, ERROR_SIZE, "can't HFS create folder %s", s_entry->whole_name); return(-1); } else if (i == 0) { /* File name at max HFS length - make unique name */ if (!new_name) new_name++; sprintf(ent->name + HFS_MAX_FLEN - digits - 1, "%s%d", LCHAR, new_name); new_name++; if (new_name == tens) { tens *= TEN; digits++; } } else { /* append '_' to get new name */ strcat(ent->name, LCHAR); i--; new_name = 1; } } else break; } /* warn that we have a new name */ if (new_name && verbose > 0) { fprintf(stderr, "Using HFS name: %s for %s\n", ent->name, s_entry->whole_name); } /* see if we need to "bless" this folder */ if (hfs_bless && strcmp(s_entry->whole_name, hfs_bless) == 0) { hfs_stat(vol, ent->name, ent); hfs_vsetbless(vol, ent->cnid); if (verbose > 0) { fprintf(stderr, "Blessing %s (%s)\n", ent->name, s_entry->whole_name); } /* stop any further checks */ hfs_bless = NULL; } /* change to sub-folder */ if (hfs_chdir(vol, ent->name) < 0) return(-1); /* recursively copy files ... */ ret = copy_to_mac_vol(vol, dpnt); if (ret < 0) return(ret); /* change back to this folder */ if (hfs_setcwd(vol, id) < 0) return(-1); } } return(0); }
/** * \ingroup fslib * Tries to process data in a disk image at a given offset as a file system. * Returns a structure that can be used for analysis and reporting. * * @param a_img_info Disk image to analyze * @param a_offset Byte offset to start analyzing from * @param a_ftype Type of file system (or autodetect) * * @return NULL on error */ TSK_FS_INFO * tsk_fs_open_img(TSK_IMG_INFO * a_img_info, TSK_OFF_T a_offset, TSK_FS_TYPE_ENUM a_ftype) { TSK_FS_INFO *fs_info; const struct { char* name; TSK_FS_INFO* (*open)(TSK_IMG_INFO*, TSK_OFF_T, TSK_FS_TYPE_ENUM, uint8_t); TSK_FS_TYPE_ENUM type; } FS_OPENERS[] = { { "NTFS", ntfs_open, TSK_FS_TYPE_NTFS_DETECT }, { "FAT", fatfs_open, TSK_FS_TYPE_FAT_DETECT }, { "EXT2/3/4", ext2fs_open, TSK_FS_TYPE_EXT_DETECT }, { "UFS", ffs_open, TSK_FS_TYPE_FFS_DETECT }, { "YAFFS2", yaffs2_open, TSK_FS_TYPE_YAFFS2_DETECT }, #if TSK_USE_HFS { "HFS", hfs_open, TSK_FS_TYPE_HFS_DETECT }, #endif { "ISO9660", iso9660_open, TSK_FS_TYPE_ISO9660_DETECT } }; if (a_img_info == NULL) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_ARG); tsk_error_set_errstr("tsk_fs_open_img: Null image handle"); return NULL; } /* We will try different file systems ... * We need to try all of them in case more than one matches */ if (a_ftype == TSK_FS_TYPE_DETECT) { unsigned long i; const char *name_first = ""; TSK_FS_INFO *fs_first = NULL; if (tsk_verbose) tsk_fprintf(stderr, "fsopen: Auto detection mode at offset %" PRIuOFF "\n", a_offset); for (i = 0; i < sizeof(FS_OPENERS)/sizeof(FS_OPENERS[0]); ++i) { if ((fs_info = FS_OPENERS[i].open( a_img_info, a_offset, FS_OPENERS[i].type, 1)) != NULL) { // fs opens as type i if (fs_first == NULL) { // first success opening fs name_first = FS_OPENERS[i].name; fs_first = fs_info; } else { // second success opening fs, which means we // cannot autodetect the fs type and must give up fs_first->close(fs_first); fs_info->close(fs_info); tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_UNKTYPE); tsk_error_set_errstr( "%s or %s", FS_OPENERS[i].name, name_first); return NULL; } } else { // fs does not open as type i tsk_error_reset(); } } if (fs_first == NULL) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_UNKTYPE); } return fs_first; } else if (TSK_FS_TYPE_ISNTFS(a_ftype)) { return ntfs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISFAT(a_ftype)) { return fatfs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISFFS(a_ftype)) { return ffs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISEXT(a_ftype)) { return ext2fs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISHFS(a_ftype)) { return hfs_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISISO9660(a_ftype)) { return iso9660_open(a_img_info, a_offset, a_ftype, 0); } else if (TSK_FS_TYPE_ISRAW(a_ftype)) { return rawfs_open(a_img_info, a_offset); } else if (TSK_FS_TYPE_ISSWAP(a_ftype)) { return swapfs_open(a_img_info, a_offset); } else if (TSK_FS_TYPE_ISYAFFS2(a_ftype)) { return yaffs2_open(a_img_info, a_offset, a_ftype, 0); } tsk_error_reset(); tsk_error_set_errno(TSK_ERR_FS_UNSUPTYPE); tsk_error_set_errstr("%X", (int) a_ftype); return NULL; }