static void _generate_partition (PedPartition* part, struct partition_table* pt) { DVHPartData* dvh_part_data = part->disk_specific; /* Assert not a bootfile */ PED_ASSERT ((part->type & PED_PARTITION_LOGICAL) == 0); pt->pt_nblks = PED_CPU_TO_BE32 (part->geom.length); pt->pt_firstlbn = PED_CPU_TO_BE32 (part->geom.start); pt->pt_type = PED_CPU_TO_BE32 (dvh_part_data->type); }
static int amiga_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) { struct PartitionBlock *partition; PED_ASSERT (part != NULL); PED_ASSERT (part->disk_specific != NULL); partition = PART(part->disk_specific); switch (flag) { case PED_PARTITION_BOOT: if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_BOOTABLE); else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_BOOTABLE)); return 1; case PED_PARTITION_HIDDEN: if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_NOMOUNT); else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_NOMOUNT)); return 1; case PED_PARTITION_RAID: if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_RAID); else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_RAID)); return 1; case PED_PARTITION_LVM: if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_LVM); else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_LVM)); return 1; default: return 0; } }
static void _generate_boot_file (PedPartition* part, struct volume_directory* vd) { DVHPartData* dvh_part_data = part->disk_specific; /* Assert it's a bootfile */ PED_ASSERT ((part->type & PED_PARTITION_LOGICAL) != 0); vd->vd_nbytes = PED_CPU_TO_BE32 (dvh_part_data->real_file_size); vd->vd_lbn = PED_CPU_TO_BE32 (part->geom.start); memset (vd->vd_name, 0, VDNAMESIZE); strncpy (vd->vd_name, dvh_part_data->name, VDNAMESIZE); }
static void _amiga_calculate_checksum (struct AmigaBlock *blk) { blk->amiga_ChkSum = PED_CPU_TO_BE32( PED_BE32_TO_CPU(blk->amiga_ChkSum) - _amiga_checksum((struct AmigaBlock *) blk)); return; }
int hfsj_update_jib(PedFileSystem* fs, uint32_t block) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; priv_data->vh->journal_info_block = PED_CPU_TO_BE32(block); if (!hfsplus_update_vh (fs)) return 0; priv_data->jib_start_block = block; return 1; }
static int amiga_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) { struct PartitionBlock *partition; PED_ASSERT (part != NULL); PED_ASSERT (part->disk_specific != NULL); partition = PART(part->disk_specific); switch (flag) { case PED_PARTITION_BOOT: return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_BOOTABLE)); case PED_PARTITION_HIDDEN: return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_NOMOUNT)); case PED_PARTITION_RAID: return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_RAID)); case PED_PARTITION_LVM: return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_LVM)); default: return 0; } }
/* TODO : use exceptions to report errors */ static int hfsplus_extract (PedFileSystem* fs, PedTimer* timer) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsPVolumeHeader* vh = priv_data->vh; HfsPPrivateFile* startup_file; if (priv_data->wrapper) { /* TODO : create nested timer */ hfs_extract (priv_data->wrapper, timer); } ped_exception_throw ( PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK, _("This is not a real %s check. This is going to extract " "special low level files for debugging purposes."), "HFS+"); extract_buffer = ped_malloc(BLOCK_MAX_BUFF * PED_SECTOR_SIZE_DEFAULT); if (!extract_buffer) return 0; hfsplus_extract_vh(HFSP_VH_FILENAME, fs); hfsplus_extract_file(HFSP_CATALOG_FILENAME, priv_data->catalog_file); hfsplus_extract_file(HFSP_EXTENTS_FILENAME, priv_data->extents_file); hfsplus_extract_file(HFSP_ATTRIB_FILENAME, priv_data->attributes_file); hfsplus_extract_file(HFSP_BITMAP_FILENAME, priv_data->allocation_file); startup_file = hfsplus_file_open(fs, PED_CPU_TO_BE32(HFSP_STARTUP_ID), vh->startup_file.extents, PED_BE64_TO_CPU ( vh->startup_file.logical_size) / PED_SECTOR_SIZE_DEFAULT); if (startup_file) { hfsplus_extract_file(HFSP_STARTUP_FILENAME, startup_file); hfsplus_file_close(startup_file); startup_file = NULL; } free(extract_buffer); extract_buffer = NULL; return 0; /* nothing has been fixed by us ! */ }
static int hfsplus_cache_from_attributes(HfsCPrivateCache* cache, PedFileSystem* fs, PedTimer* timer) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; uint8_t node_1[PED_SECTOR_SIZE_DEFAULT]; uint8_t* node; HfsPHeaderRecord* header; HfsPPrivateGenericKey* generic_key; HfsPForkDataAttr* fork_ext_data; HfsPExtDescriptor* extent; unsigned int leaf_node, record_number; unsigned int i, j, size, bsize; /* attributes file is facultative */ if (!priv_data->attributes_file->sect_nb) return 1; /* Search the extent starting at *ptr_block in the catalog file */ if (!hfsplus_file_read_sector (priv_data->attributes_file, node_1, 0)) return 0; header = ((HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC)); leaf_node = PED_BE32_TO_CPU (header->first_leaf_node); bsize = PED_BE16_TO_CPU (header->node_size); size = bsize / PED_SECTOR_SIZE_DEFAULT; PED_ASSERT(size < 256); node = (uint8_t*) ped_malloc(bsize); if (!node) return 0; HfsPNodeDescriptor *desc = (HfsPNodeDescriptor*) node; for (; leaf_node; leaf_node = PED_BE32_TO_CPU (desc->next)) { if (!hfsplus_file_read (priv_data->attributes_file, node, (PedSector) leaf_node * size, size)) { free (node); return 0; } record_number = PED_BE16_TO_CPU (desc->rec_nb); for (i = 1; i <= record_number; i++) { unsigned int skip; generic_key = (HfsPPrivateGenericKey*) (node + PED_BE16_TO_CPU(*((uint16_t *) (node+(bsize - 2*i))))); skip = ( 2 + PED_BE16_TO_CPU (generic_key->key_length) + 1 ) & ~1; fork_ext_data = (HfsPForkDataAttr*) (((uint8_t*)generic_key) + skip); /* check for obvious error in FS */ if (((uint8_t*)generic_key - node < HFS_FIRST_REC) || ((uint8_t*)fork_ext_data - node >= (signed) bsize - 2 * (signed)(record_number+1))) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("The file system contains errors.")); free (node); return 0; } if (fork_ext_data->record_type == PED_CPU_TO_BE32 ( HFSP_ATTR_FORK ) ) { extent = fork_ext_data->fork_res.fork.extents; for (j = 0; j < HFSP_EXT_NB; ++j) { if (!extent[j].block_count) break; if (!hfsc_cache_add_extent( cache, PED_BE32_TO_CPU ( extent[j].start_block ), PED_BE32_TO_CPU ( extent[j].block_count ), leaf_node, (uint8_t*)extent-node, size, CR_BTREE_ATTR, j ) ) { free(node); return 0; } } } else if (fork_ext_data->record_type == PED_CPU_TO_BE32 ( HFSP_ATTR_EXTENTS ) ) { extent = fork_ext_data->fork_res.extents; for (j = 0; j < HFSP_EXT_NB; ++j) { if (!extent[j].block_count) break; if (!hfsc_cache_add_extent( cache, PED_BE32_TO_CPU ( extent[j].start_block ), PED_BE32_TO_CPU ( extent[j].block_count ), leaf_node, (uint8_t*)extent-node, size, CR_BTREE_ATTR, j ) ) { free(node); return 0; } } } else continue; } } free (node); return 1; }
static int hfsplus_cache_from_extent(HfsCPrivateCache* cache, PedFileSystem* fs, PedTimer* timer) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; uint8_t node_1[PED_SECTOR_SIZE_DEFAULT]; uint8_t* node; HfsPHeaderRecord* header; HfsPExtentKey* extent_key; HfsPExtDescriptor* extent; unsigned int leaf_node, record_number; unsigned int i, j, size, bsize; if (!priv_data->extents_file->sect_nb) { ped_exception_throw ( PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK, _("This HFS+ volume has no extents overflow " "file. This is quite unusual!")); return 1; } if (!hfsplus_file_read_sector (priv_data->extents_file, node_1, 0)) return 0; header = ((HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC)); leaf_node = PED_BE32_TO_CPU (header->first_leaf_node); bsize = PED_BE16_TO_CPU (header->node_size); size = bsize / PED_SECTOR_SIZE_DEFAULT; PED_ASSERT(size < 256); node = (uint8_t*) ped_malloc (bsize); if (!node) return -1; HfsPNodeDescriptor *desc = (HfsPNodeDescriptor*) node; for (; leaf_node; leaf_node = PED_BE32_TO_CPU (desc->next)) { if (!hfsplus_file_read (priv_data->extents_file, node, (PedSector) leaf_node * size, size)) { free (node); return 0; } record_number = PED_BE16_TO_CPU (desc->rec_nb); for (i = 1; i <= record_number; i++) { uint8_t where; extent_key = (HfsPExtentKey*) (node + PED_BE16_TO_CPU(*((uint16_t *) (node+(bsize - 2*i))))); extent = (HfsPExtDescriptor*) (((uint8_t*)extent_key) + sizeof (HfsPExtentKey)); /* check for obvious error in FS */ if (((uint8_t*)extent_key - node < HFS_FIRST_REC) || ((uint8_t*)extent - node >= (signed)bsize - 2 * (signed)(record_number+1))) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("The file system contains errors.")); free (node); return -1; } switch (extent_key->file_ID) { case PED_CPU_TO_BE32 (HFS_XTENT_ID) : if (ped_exception_throw ( PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL, _("The extents overflow file should not" " contain its own extents! You should " "check the file system.")) != PED_EXCEPTION_IGNORE) return 0; where = CR_BTREE_EXT_EXT; break; case PED_CPU_TO_BE32 (HFS_CATALOG_ID) : where = CR_BTREE_EXT_CAT; break; case PED_CPU_TO_BE32 (HFSP_ALLOC_ID) : where = CR_BTREE_EXT_ALLOC; break; case PED_CPU_TO_BE32 (HFSP_STARTUP_ID) : where = CR_BTREE_EXT_START; break; case PED_CPU_TO_BE32 (HFSP_ATTRIB_ID) : where = CR_BTREE_EXT_ATTR; break; default : where = CR_BTREE_EXT_0; break; } for (j = 0; j < HFSP_EXT_NB; ++j) { if (!extent[j].block_count) break; if (!hfsc_cache_add_extent( cache, PED_BE32_TO_CPU(extent[j].start_block), PED_BE32_TO_CPU(extent[j].block_count), leaf_node, (uint8_t*)extent - node, size, where, j ) ) { free (node); return 0; } } } } free (node); return 1; }
static int hfsplus_do_move (PedFileSystem* fs, unsigned int *ptr_src, unsigned int *ptr_dest, HfsCPrivateCache* cache, HfsCPrivateExtent* ref) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsPPrivateFile* file; HfsPExtDescriptor* extent; HfsCPrivateExtent* move; int new_start; new_start = hfsplus_effect_move_extent (fs, ptr_src, ptr_dest, ref->ext_length); if (new_start == -1) return -1; if (ref->ext_start != (unsigned) new_start) { switch (ref->where) { /************ VH ************/ case CR_PRIM_CAT : priv_data->catalog_file ->first[ref->ref_index].start_block = PED_CPU_TO_BE32(new_start); goto CR_PRIM; case CR_PRIM_EXT : priv_data->extents_file ->first[ref->ref_index].start_block = PED_CPU_TO_BE32(new_start); goto CR_PRIM; case CR_PRIM_ATTR : priv_data->attributes_file ->first[ref->ref_index].start_block = PED_CPU_TO_BE32(new_start); goto CR_PRIM; case CR_PRIM_ALLOC : priv_data->allocation_file ->first[ref->ref_index].start_block = PED_CPU_TO_BE32(new_start); goto CR_PRIM; case CR_PRIM_START : /* No startup file opened */ CR_PRIM : extent = ( HfsPExtDescriptor* ) ( (uint8_t*)priv_data->vh + ref->ref_offset ); extent[ref->ref_index].start_block = PED_CPU_TO_BE32(new_start); if (!hfsplus_update_vh(fs)) return -1; break; /************** BTREE *************/ case CR_BTREE_CAT_JIB : if (!hfsj_update_jib(fs, new_start)) return -1; goto BTREE_CAT; case CR_BTREE_CAT_JL : if (!hfsj_update_jl(fs, new_start)) return -1; goto BTREE_CAT; BTREE_CAT: case CR_BTREE_CAT : file = priv_data->catalog_file; goto CR_BTREE; case CR_BTREE_ATTR : file = priv_data->attributes_file; goto CR_BTREE; case CR_BTREE_EXT_ATTR : if (priv_data->attributes_file ->cache[ref->ref_index].start_block == PED_CPU_TO_BE32(ref->ext_start)) priv_data->attributes_file ->cache[ref->ref_index].start_block = PED_CPU_TO_BE32(new_start); goto CR_BTREE_EXT; case CR_BTREE_EXT_CAT : if (priv_data->catalog_file ->cache[ref->ref_index].start_block == PED_CPU_TO_BE32(ref->ext_start)) priv_data->catalog_file ->cache[ref->ref_index].start_block = PED_CPU_TO_BE32(new_start); goto CR_BTREE_EXT; case CR_BTREE_EXT_ALLOC : if (priv_data->allocation_file ->cache[ref->ref_index].start_block == PED_CPU_TO_BE32(ref->ext_start)) priv_data->allocation_file ->cache[ref->ref_index].start_block = PED_CPU_TO_BE32(new_start); goto CR_BTREE_EXT; case CR_BTREE_EXT_START : /* No startup file opened */ CR_BTREE_EXT : case CR_BTREE_EXT_0 : file = priv_data->extents_file; CR_BTREE : PED_ASSERT(PED_SECTOR_SIZE_DEFAULT * ref->sect_by_block > ref->ref_offset); if (!hfsplus_file_read(file, hfsp_block, (PedSector)ref->ref_block * ref->sect_by_block, ref->sect_by_block)) return -1; extent = ( HfsPExtDescriptor* ) ( hfsp_block + ref->ref_offset ); extent[ref->ref_index].start_block = PED_CPU_TO_BE32(new_start); if (!hfsplus_file_write(file, hfsp_block, (PedSector)ref->ref_block * ref->sect_by_block, ref->sect_by_block) || !ped_geometry_sync_fast (priv_data->plus_geom)) return -1; break; /********** BUG *********/ default : ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("A reference to an extent comes from a place " "it should not. You should check the file " "system!")); return -1; break; } move = hfsc_cache_move_extent(cache, ref->ext_start, new_start); if (!move) return -1; PED_ASSERT(move == ref); } return new_start; }
/* This function reads bad blocks extents in the extents file and store it in f.s. specific data of fs */ int hfs_read_bad_blocks (const PedFileSystem *fs) { HfsPrivateFSData* priv_data = (HfsPrivateFSData*) fs->type_specific; if (priv_data->bad_blocks_loaded) return 1; { uint8_t record[sizeof (HfsExtentKey) + sizeof (HfsExtDataRec)]; HfsExtentKey search; HfsExtentKey* ret_key = (HfsExtentKey*) record; HfsExtDescriptor* ret_cache = (HfsExtDescriptor*) (record + sizeof (HfsExtentKey)); unsigned int block, last_start, first_pass = 1; search.key_length = sizeof (HfsExtentKey) - 1; search.type = HFS_DATA_FORK; search.file_ID = PED_CPU_TO_BE32 (HFS_BAD_BLOCK_ID); last_start = -1; block = 0; while (1) { int i; search.start = PED_CPU_TO_BE16 (block); if (!hfs_btree_search (priv_data->extent_file, (HfsPrivateGenericKey*) &search, record, sizeof (record), NULL) || ret_key->file_ID != search.file_ID || ret_key->type != search.type) { if (first_pass) break; else goto errbb; } if (PED_BE16_TO_CPU (ret_key->start) == last_start) break; last_start = PED_BE16_TO_CPU (ret_key->start); for (i = 0; i < HFS_EXT_NB; i++) { if (ret_cache[i].block_count) { HfsPrivateLinkExtent* new_xt = (HfsPrivateLinkExtent*) ped_malloc ( sizeof (HfsPrivateLinkExtent)); if (!new_xt) goto errbb; new_xt->next = priv_data->bad_blocks_xtent_list; memcpy(&(new_xt->extent), ret_cache+i, sizeof (HfsExtDescriptor)); priv_data->bad_blocks_xtent_list = new_xt; priv_data->bad_blocks_xtent_nb++; block += PED_BE16_TO_CPU ( ret_cache[i].block_count); } } first_pass = 0; } priv_data->bad_blocks_loaded = 1; return 1;} errbb: hfs_free_bad_blocks_list(priv_data->bad_blocks_xtent_list); priv_data->bad_blocks_xtent_list=NULL; priv_data->bad_blocks_xtent_nb=0; return 0; }
static int dvh_write (const PedDisk* disk) { DVHDiskData* dvh_disk_data = disk->disk_specific; struct volume_header vh; int i; PED_ASSERT (dvh_disk_data != NULL); _flush_stale_flags (disk); memset (&vh, 0, sizeof (struct volume_header)); vh.vh_magic = PED_CPU_TO_BE32 (VHMAGIC); vh.vh_rootpt = PED_CPU_TO_BE16 (dvh_disk_data->root - 1); vh.vh_swappt = PED_CPU_TO_BE16 (dvh_disk_data->swap - 1); if (dvh_disk_data->boot) { PedPartition* boot_part; boot_part = ped_disk_get_partition (disk, dvh_disk_data->boot); strcpy (vh.vh_bootfile, ped_partition_get_name (boot_part)); } vh.vh_dp = dvh_disk_data->dev_params; /* Set up rudimentary device geometry */ vh.vh_dp.dp_cyls = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.cylinders); vh.vh_dp.dp_trks0 = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.heads); vh.vh_dp.dp_secs = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.sectors); vh.vh_dp.dp_secbytes = PED_CPU_TO_BE16 ((short)disk->dev->sector_size); for (i = 0; i < NPARTAB; i++) { PedPartition* part = ped_disk_get_partition (disk, i + 1); if (part) _generate_partition (part, &vh.vh_pt[i]); } /* whole disk partition * This is only ever written here, and never modified * (or even shown) as it must contain the entire disk, * and parted does not like overlapping partitions */ vh.vh_pt[PNUM_VOLUME].pt_nblks = PED_CPU_TO_BE32 (disk->dev->length); vh.vh_pt[PNUM_VOLUME].pt_firstlbn = PED_CPU_TO_BE32 (0); vh.vh_pt[PNUM_VOLUME].pt_type = PED_CPU_TO_BE32 (PTYPE_VOLUME); for (i = 0; i < NVDIR; i++) { PedPartition* part = ped_disk_get_partition (disk, i + 1 + NPARTAB); if (part) _generate_boot_file (part, &vh.vh_vd[i]); } vh.vh_csum = 0; vh.vh_csum = PED_CPU_TO_BE32 (_checksum ((uint32_t*) &vh, sizeof (struct volume_header))); return (ptt_write_sector (disk, &vh, sizeof vh) && ped_device_sync (disk->dev)); }
static int amiga_write (const PedDisk* disk) { struct RigidDiskBlock *rdb; struct LinkedBlock *block; struct PartitionBlock *partition; PedPartition *part, *next_part; PedSector cylblocks, first_hb, last_hb; uint32_t * table; uint32_t i; uint32_t rdb_num, part_num, block_num, next_num; PED_ASSERT (disk != NULL); PED_ASSERT (disk->dev != NULL); PED_ASSERT (disk->disk_specific != NULL); if (!(rdb = ped_malloc (disk->dev->sector_size))) return 0; /* Let's read the rdb */ if ((rdb_num = _amiga_find_rdb (disk->dev, rdb)) == AMIGA_RDB_NOT_FOUND) { rdb_num = 2; size_t pb_size = sizeof (struct PartitionBlock); /* Initialize only the part that won't be copied over with a partition block in amiga_read. */ memset ((char *)(RDSK(disk->disk_specific)) + pb_size, 0, PED_SECTOR_SIZE_DEFAULT - pb_size); } else { memcpy (RDSK(disk->disk_specific), rdb, disk->dev->sector_size); } free (rdb); rdb = RDSK(disk->disk_specific); cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) * (PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors); first_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksLo); last_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksHi); /* Allocate a free block table and initialize it. There must be room for at least RDB_NUM + 2 entries, since the first RDB_NUM+1 entries get IDNAME_RIGIDDISK, and the following one must have LINK_END to serve as sentinel. */ size_t tab_size = 2 + MAX (last_hb - first_hb, rdb_num); if (!(table = ped_malloc (tab_size * sizeof *table))) return 0; for (i = 0; i <= rdb_num; i++) table[i] = IDNAME_RIGIDDISK; for ( ; i < tab_size; i++) table[i] = LINK_END; /* Let's allocate a partition block */ if (!(block = ped_malloc (disk->dev->sector_size))) { free (table); return 0; } /* And fill the free block table */ if (_amiga_find_free_blocks(disk, table, block, PED_BE32_TO_CPU (rdb->rdb_BadBlockList), IDNAME_BADBLOCK) == 0) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Failed to list bad blocks."), __func__); goto error_free_table; } if (_amiga_find_free_blocks(disk, table, block, PED_BE32_TO_CPU (rdb->rdb_PartitionList), IDNAME_PARTITION) == 0) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Failed to list partition blocks."), __func__); goto error_free_table; } if (_amiga_find_free_blocks(disk, table, block, PED_BE32_TO_CPU (rdb->rdb_FileSysHeaderList), IDNAME_FILESYSHEADER) == 0) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Failed to list file system blocks."), __func__); goto error_free_table; } if (_amiga_find_free_blocks(disk, table, block, PED_BE32_TO_CPU (rdb->rdb_BootBlockList), IDNAME_BOOT) == 0) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Failed to list boot blocks."), __func__); goto error_free_table; } block_num = part_num = _amiga_next_free_block(table, rdb_num+1, IDNAME_PARTITION); part = _amiga_next_real_partition(disk, NULL); rdb->rdb_PartitionList = PED_CPU_TO_BE32(part ? part_num : LINK_END); for (; part != NULL; part = next_part, block_num = next_num) { PED_ASSERT(part->disk_specific != NULL); PED_ASSERT(part->geom.start % cylblocks == 0); PED_ASSERT((part->geom.end + 1) % cylblocks == 0); next_part = _amiga_next_real_partition(disk, part); next_num = _amiga_next_free_block(table, block_num+1, IDNAME_PARTITION); partition = PART(part->disk_specific); if (next_part == NULL) partition->pb_Next = PED_CPU_TO_BE32(LINK_END); else partition->pb_Next = PED_CPU_TO_BE32(next_num); partition->de_LowCyl = PED_CPU_TO_BE32(part->geom.start/cylblocks); partition->de_HighCyl = PED_CPU_TO_BE32((part->geom.end+1)/cylblocks-1); _amiga_calculate_checksum(AMIGA(partition)); if (!ped_device_write (disk->dev, (void*) partition, block_num, 1)) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Failed to write partition block at %d."), block_num); goto error_free_table; /* WARNING : If we fail here, we stop everything, * and the partition table is lost. A better * solution should be found, using the second * half of the hardblocks to not overwrite the * old partition table. It becomes problematic * if we use more than half of the hardblocks. */ } } if (block_num > PED_BE32_TO_CPU (rdb->rdb_HighRDSKBlock)) rdb->rdb_HighRDSKBlock = PED_CPU_TO_BE32(block_num); _amiga_calculate_checksum(AMIGA(rdb)); if (!ped_device_write (disk->dev, (void*) disk->disk_specific, rdb_num, 1)) goto error_free_table; free (table); free (block); return ped_device_sync (disk->dev); error_free_table: free (table); free (block); return 0; }
PedFileSystem * hfs_open (PedGeometry* geom) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; PedFileSystem* fs; HfsMasterDirectoryBlock* mdb; HfsPrivateFSData* priv_data; if (!hfsc_can_use_geom (geom)) return NULL; /* Read MDB */ if (!ped_geometry_read (geom, buf, 2, 1)) return NULL; /* Allocate memory */ fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); if (!fs) goto ho; mdb = (HfsMasterDirectoryBlock*) ped_malloc (sizeof (HfsMasterDirectoryBlock)); if (!mdb) goto ho_fs; priv_data = (HfsPrivateFSData*) ped_malloc (sizeof (HfsPrivateFSData)); if (!priv_data) goto ho_mdb; memcpy (mdb, buf, sizeof (HfsMasterDirectoryBlock)); /* init structures */ priv_data->mdb = mdb; priv_data->bad_blocks_loaded = 0; priv_data->bad_blocks_xtent_nb = 0; priv_data->bad_blocks_xtent_list = NULL; priv_data->extent_file = hfs_file_open (fs, PED_CPU_TO_BE32 (HFS_XTENT_ID), mdb->extents_file_rec, PED_CPU_TO_BE32 (mdb->extents_file_size) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->extent_file) goto ho_pd; priv_data->catalog_file = hfs_file_open (fs, PED_CPU_TO_BE32 (HFS_CATALOG_ID), mdb->catalog_file_rec, PED_CPU_TO_BE32 (mdb->catalog_file_size) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->catalog_file) goto ho_ce; /* Read allocation blocks */ if (!ped_geometry_read(geom, priv_data->alloc_map, PED_BE16_TO_CPU (mdb->volume_bitmap_block), ( PED_BE16_TO_CPU (mdb->total_blocks) + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8) ) ) goto ho_cf; fs->type = &hfs_type; fs->geom = ped_geometry_duplicate (geom); if (!fs->geom) goto ho_cf; fs->type_specific = (void*) priv_data; fs->checked = ( PED_BE16_TO_CPU (mdb->volume_attributes) >> HFS_UNMOUNTED ) & 1; return fs; /*--- clean error handling ---*/ ho_cf: hfs_file_close(priv_data->catalog_file); ho_ce: hfs_file_close(priv_data->extent_file); ho_pd: free(priv_data); ho_mdb: free(mdb); ho_fs: free(fs); ho: return NULL; }
static PedDisk* amiga_alloc (const PedDevice* dev) { PedDisk *disk; struct RigidDiskBlock *rdb; PedSector cyl_size; int highest_cylinder, highest_block; PED_ASSERT(dev != NULL); cyl_size = dev->hw_geom.sectors * dev->hw_geom.heads; if (!(disk = _ped_disk_alloc (dev, &amiga_disk_type))) return NULL; if (!(disk->disk_specific = ped_malloc (disk->dev->sector_size))) { free (disk); return NULL; } rdb = disk->disk_specific; /* Upon failed assertion this does leak. That's fine, because if the assertion fails, you have bigger problems than this leak. */ PED_ASSERT(sizeof(*rdb) <= disk->dev->sector_size); memset(rdb, 0, disk->dev->sector_size); rdb->rdb_ID = PED_CPU_TO_BE32 (IDNAME_RIGIDDISK); rdb->rdb_SummedLongs = PED_CPU_TO_BE32 (64); rdb->rdb_HostID = PED_CPU_TO_BE32 (0); rdb->rdb_BlockBytes = PED_CPU_TO_BE32 (disk->dev->sector_size); rdb->rdb_Flags = PED_CPU_TO_BE32 (0); /* Block lists */ rdb->rdb_BadBlockList = PED_CPU_TO_BE32 (LINK_END); rdb->rdb_PartitionList = PED_CPU_TO_BE32 (LINK_END); rdb->rdb_FileSysHeaderList = PED_CPU_TO_BE32 (LINK_END); rdb->rdb_DriveInit = PED_CPU_TO_BE32 (LINK_END); rdb->rdb_BootBlockList = PED_CPU_TO_BE32 (LINK_END); /* Physical drive characteristics */ rdb->rdb_Cylinders = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); rdb->rdb_Sectors = PED_CPU_TO_BE32 (dev->hw_geom.sectors); rdb->rdb_Heads = PED_CPU_TO_BE32 (dev->hw_geom.heads); rdb->rdb_Interleave = PED_CPU_TO_BE32 (0); rdb->rdb_Park = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); rdb->rdb_WritePreComp = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); rdb->rdb_ReducedWrite = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); rdb->rdb_StepRate = PED_CPU_TO_BE32 (0); highest_cylinder = 1 + MAX_RDB_BLOCK / cyl_size; highest_block = highest_cylinder * cyl_size - 1; /* Logical driver characteristics */ rdb->rdb_RDBBlocksLo = PED_CPU_TO_BE32 (0); rdb->rdb_RDBBlocksHi = PED_CPU_TO_BE32 (highest_block); rdb->rdb_LoCylinder = PED_CPU_TO_BE32 (highest_cylinder); rdb->rdb_HiCylinder = PED_CPU_TO_BE32 (dev->hw_geom.cylinders -1); rdb->rdb_CylBlocks = PED_CPU_TO_BE32 (cyl_size); rdb->rdb_AutoParkSeconds = PED_CPU_TO_BE32 (0); /* rdb_HighRDSKBlock will only be set when writing */ rdb->rdb_HighRDSKBlock = PED_CPU_TO_BE32 (0); /* Driver identification */ _amiga_set_bstr("", rdb->rdb_DiskVendor, 8); _amiga_set_bstr(dev->model, rdb->rdb_DiskProduct, 16); _amiga_set_bstr("", rdb->rdb_DiskRevision, 4); _amiga_set_bstr("", rdb->rdb_ControllerVendor, 8); _amiga_set_bstr("", rdb->rdb_ControllerProduct, 16); _amiga_set_bstr("", rdb->rdb_ControllerRevision, 4); /* And calculate the checksum */ _amiga_calculate_checksum ((struct AmigaBlock *) rdb); return disk; }
static int hfsplus_volume_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; unsigned int nblock, nfree, mblock; unsigned int block, to_free, old_blocks; HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsPVolumeHeader* vh = priv_data->vh; int resize = 1; unsigned int hfsp_sect_block = ( PED_BE32_TO_CPU (vh->block_size) / PED_SECTOR_SIZE_DEFAULT ); unsigned int map_sectors; old_blocks = PED_BE32_TO_CPU (vh->total_blocks); /* Flush caches */ if (!ped_geometry_sync(priv_data->plus_geom)) return 0; /* Clear the unmounted bit */ /* and set the implementation code (Apple Creator Code) */ vh->attributes &= PED_CPU_TO_BE32 (~( 1 << HFS_UNMOUNTED )); vh->last_mounted_version = PED_CPU_TO_BE32(HFSP_IMPL_Shnk); if (!ped_geometry_read (priv_data->plus_geom, buf, 2, 1)) return 0; memcpy (buf, vh, sizeof (HfsPVolumeHeader)); if ( !ped_geometry_write (priv_data->plus_geom, buf, 2, 1) || !ped_geometry_sync (priv_data->plus_geom)) return 0; ped_timer_reset (timer); ped_timer_set_state_name(timer, _("shrinking")); ped_timer_update(timer, 0.0); /* relocate data */ to_free = ( priv_data->plus_geom->length - geom->length + hfsp_sect_block - 1 ) / hfsp_sect_block; block = hfsplus_find_start_pack (fs, to_free); if (!hfsplus_pack_free_space_from_block (fs, block, timer, to_free)) { resize = 0; ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Data relocation has failed.")); goto write_VH; } /* Calculate new block number and other VH field */ /* nblock must be rounded _down_ */ nblock = geom->length / hfsp_sect_block; nfree = PED_BE32_TO_CPU (vh->free_blocks) - (old_blocks - nblock); /* free block readjustement is only needed when incorrect nblock was used by my previous implementation, so detect the case */ if (priv_data->plus_geom->length < old_blocks * ( PED_BE32_TO_CPU (vh->block_size) / PED_SECTOR_SIZE_DEFAULT) ) { if (priv_data->plus_geom->length % hfsp_sect_block == 1) nfree++; } /* Check that all block after future end are really free */ mblock = ( priv_data->plus_geom->length - 2 ) / hfsp_sect_block; if (mblock > old_blocks - 1) mblock = old_blocks - 1; for ( block = nblock; block < mblock; block++ ) { if (TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) { resize = 0; ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Data relocation left some data at the end " "of the volume.")); goto write_VH; } } /* Mark out of volume blocks as used */ map_sectors = ( ( old_blocks + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8) ) * (PED_SECTOR_SIZE_DEFAULT * 8); for ( block = nblock; block < map_sectors; ++block) SET_BLOC_OCCUPATION(priv_data->alloc_map, block); /* Update geometry */ if (resize) { /* update in fs structure */ if (PED_BE32_TO_CPU (vh->next_allocation) >= nblock) vh->next_allocation = PED_CPU_TO_BE32 (0); vh->total_blocks = PED_CPU_TO_BE32 (nblock); vh->free_blocks = PED_CPU_TO_BE32 (nfree); /* update parted structure */ priv_data->plus_geom->length = geom->length; priv_data->plus_geom->end = priv_data->plus_geom->start + geom->length - 1; } /* Effective write */ write_VH: /* lasts two sectors are allocated by the alternate VH and a reserved sector, and last block is always reserved */ block = (priv_data->plus_geom->length - 1) / hfsp_sect_block; if (block < PED_BE32_TO_CPU (vh->total_blocks)) SET_BLOC_OCCUPATION(priv_data->alloc_map, block); block = (priv_data->plus_geom->length - 2) / hfsp_sect_block; if (block < PED_BE32_TO_CPU (vh->total_blocks)) SET_BLOC_OCCUPATION(priv_data->alloc_map, block); SET_BLOC_OCCUPATION(priv_data->alloc_map, PED_BE32_TO_CPU (vh->total_blocks) - 1); /* Write the _old_ area to set out of volume blocks as used */ map_sectors = ( old_blocks + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8); if (!hfsplus_file_write (priv_data->allocation_file, priv_data->alloc_map, 0, map_sectors)) { resize = 0; ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Error while writing the allocation file.")); } else { /* Write remaining part of allocation bitmap */ /* This is necessary to handle pre patch-11 and third party */ /* implementations */ memset(buf, 0xFF, PED_SECTOR_SIZE_DEFAULT); for (block = map_sectors; block < priv_data->allocation_file->sect_nb; ++block) { if (!hfsplus_file_write_sector ( priv_data->allocation_file, buf, block)) { ped_exception_throw ( PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE, _("Error while writing the " "compatibility part of the " "allocation file.")); break; } } } ped_geometry_sync (priv_data->plus_geom); if (resize) { /* Set the unmounted bit and clear the inconsistent bit */ vh->attributes |= PED_CPU_TO_BE32 ( 1 << HFS_UNMOUNTED ); vh->attributes &= ~ PED_CPU_TO_BE32 ( 1 << HFSP_INCONSISTENT ); } ped_timer_set_state_name(timer, _("writing HFS+ Volume Header")); if (!hfsplus_update_vh(fs)) { ped_geometry_sync(priv_data->plus_geom); return 0; } if (!ped_geometry_sync(priv_data->plus_geom)) return 0; ped_timer_update(timer, 1.0); return (resize); }
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; }
static int hfsj_replay_transaction(PedFileSystem* fs, HfsJJournalHeader* jh, PedSector jsector, PedSector jlength) { PedSector start, sector; HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsJBlockListHeader* blhdr; uint8_t* block; unsigned int blhdr_nbsect; int i, r; uint32_t cksum, size; blhdr_nbsect = PED_BE32_TO_CPU(jh->blhdr_size) / PED_SECTOR_SIZE_DEFAULT; blhdr = (HfsJBlockListHeader*) ped_malloc (blhdr_nbsect * PED_SECTOR_SIZE_DEFAULT); if (!blhdr) return 0; start = PED_BE64_TO_CPU(jh->start) / PED_SECTOR_SIZE_DEFAULT; do { start = hfsj_journal_read(priv_data->plus_geom, jh, jsector, jlength, start, blhdr_nbsect, blhdr); if (!start) goto err_replay; cksum = PED_BE32_TO_CPU(blhdr->checksum); blhdr->checksum = 0; if (cksum!=hfsj_calc_checksum((uint8_t*)blhdr, sizeof(*blhdr))){ ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Bad block list header checksum.")); goto err_replay; } blhdr->checksum = PED_CPU_TO_BE32(cksum); for (i=1; i < PED_BE16_TO_CPU(blhdr->num_blocks); ++i) { size = PED_BE32_TO_CPU(blhdr->binfo[i].bsize); sector = PED_BE64_TO_CPU(blhdr->binfo[i].bnum); if (!size) continue; if (size % PED_SECTOR_SIZE_DEFAULT) { ped_exception_throw( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Invalid size of a transaction " "block while replaying the journal " "(%i bytes)."), size); goto err_replay; } block = (uint8_t*) ped_malloc(size); if (!block) goto err_replay; start = hfsj_journal_read(priv_data->plus_geom, jh, jsector, jlength, start, size / PED_SECTOR_SIZE_DEFAULT, block); if (!start) { ped_free (block); goto err_replay; } /* the sector stored in the journal seems to be relative to the begin of the block device which contains the hfs+ journaled volume */ if (sector != ~0LL) r = ped_geometry_write (fs->geom, block, sector, size / PED_SECTOR_SIZE_DEFAULT); else r = 1; ped_free (block); /* check if wrapper mdb or vh with no wrapper has changed */ if ( (sector != ~0LL) && (2 >= sector) && (2 < sector + size / PED_SECTOR_SIZE_DEFAULT) ) hfsj_vh_replayed = 1; /* check if vh of embedded hfs+ has changed */ if ( (sector != ~0LL) && (priv_data->plus_geom != fs->geom) && (sector + fs->geom->start - priv_data->plus_geom->start <= 2) && (sector + size / PED_SECTOR_SIZE_DEFAULT + fs->geom->start - priv_data->plus_geom->start > 2) ) hfsj_vh_replayed = 1; if (!r) goto err_replay; } } while (blhdr->binfo[0].next); jh->start = PED_CPU_TO_BE64(start * PED_SECTOR_SIZE_DEFAULT); ped_free (blhdr); return (ped_geometry_sync (fs->geom)); err_replay: ped_free (blhdr); return 0; }
/* 1 => Success, the journal has been completly replayed, or don't need to */ int hfsj_replay_journal(PedFileSystem* fs) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; PedSector sector, length; HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsJJournalInfoBlock* jib; HfsJJournalHeader* jh; int binsect; uint32_t cksum; binsect = PED_BE32_TO_CPU(priv_data->vh->block_size) / PED_SECTOR_SIZE_DEFAULT; priv_data->jib_start_block = PED_BE32_TO_CPU(priv_data->vh->journal_info_block); sector = (PedSector) priv_data->jib_start_block * binsect; if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) return 0; jib = (HfsJJournalInfoBlock*) buf; if ( (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_IN_FS)) && !(jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_OTHER_DEV)) ) { priv_data->jl_start_block = HFS_64_TO_CPU(jib->offset, is_le) / ( PED_SECTOR_SIZE_DEFAULT * binsect ); } if (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_NEED_INIT)) return 1; if ( !(jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_IN_FS)) || (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_OTHER_DEV)) ) { ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_CANCEL, _("Journal stored outside of the volume are " "not supported. Try to desactivate the " "journal and run Parted again.")); return 0; } if ( (PED_BE64_TO_CPU(jib->offset) % PED_SECTOR_SIZE_DEFAULT) || (PED_BE64_TO_CPU(jib->size) % PED_SECTOR_SIZE_DEFAULT) ) { ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_CANCEL, _("Journal offset or size is not multiple of " "the sector size.")); return 0; } sector = PED_BE64_TO_CPU(jib->offset) / PED_SECTOR_SIZE_DEFAULT; length = PED_BE64_TO_CPU(jib->size) / PED_SECTOR_SIZE_DEFAULT; jib = NULL; if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) return 0; jh = (HfsJJournalHeader*) buf; if (jh->endian == PED_LE32_TO_CPU(HFSJ_ENDIAN_MAGIC)) is_le = 1; if ( (jh->magic != HFS_32_TO_CPU(HFSJ_HEADER_MAGIC, is_le)) || (jh->endian != HFS_32_TO_CPU(HFSJ_ENDIAN_MAGIC, is_le)) ) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Incorrect magic values in the journal header.")); return 0; } if ( (HFS_64_TO_CPU(jh->size, is_le)%PED_SECTOR_SIZE_DEFAULT) || (HFS_64_TO_CPU(jh->size, is_le)/PED_SECTOR_SIZE_DEFAULT != (uint64_t)length) ) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Journal size mismatch between journal info block " "and journal header.")); return 0; } if ( (HFS_64_TO_CPU(jh->start, is_le) % PED_SECTOR_SIZE_DEFAULT) || (HFS_64_TO_CPU(jh->end, is_le) % PED_SECTOR_SIZE_DEFAULT) || (HFS_32_TO_CPU(jh->blhdr_size, is_le) % PED_SECTOR_SIZE_DEFAULT) || (HFS_32_TO_CPU(jh->jhdr_size, is_le) % PED_SECTOR_SIZE_DEFAULT) ) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Some header fields are not multiple of the sector " "size.")); return 0; } if (HFS_32_TO_CPU(jh->jhdr_size, is_le) != PED_SECTOR_SIZE_DEFAULT) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("The sector size stored in the journal is not 512 " "bytes. Parted only supports 512 bytes length " "sectors.")); return 0; } cksum = HFS_32_TO_CPU(jh->checksum, is_le); jh->checksum = 0; if (cksum != hfsj_calc_checksum((uint8_t*)jh, sizeof(*jh))) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Bad journal checksum.")); return 0; } jh->checksum = HFS_CPU_TO_32(cksum, is_le); /* The 2 following test are in the XNU Darwin source code */ /* so I assume they're needed */ if (jh->start == jh->size) jh->start = HFS_CPU_TO_64(PED_SECTOR_SIZE_DEFAULT, is_le); if (jh->end == jh->size) jh->start = HFS_CPU_TO_64(PED_SECTOR_SIZE_DEFAULT, is_le); if (jh->start == jh->end) return 1; if (ped_exception_throw ( PED_EXCEPTION_WARNING, PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL, _("The journal is not empty. Parted must replay the " "transactions before opening the file system. This will " "modify the file system.")) != PED_EXCEPTION_FIX) return 0; while (jh->start != jh->end) { /* Replay one complete transaction */ if (!hfsj_replay_transaction(fs, jh, sector, length)) return 0; /* Recalculate cksum of the journal header */ jh->checksum = 0; /* need to be 0 while calculating the cksum */ cksum = hfsj_calc_checksum((uint8_t*)jh, sizeof(*jh)); jh->checksum = HFS_CPU_TO_32(cksum, is_le); /* Update the Journal Header */ if (!ped_geometry_write(priv_data->plus_geom, buf, sector, 1) || !ped_geometry_sync(priv_data->plus_geom)) return 0; } if (hfsj_vh_replayed) { /* probe could have reported incorrect info ! */ /* is there a way to ask parted to quit ? */ ped_exception_throw( PED_EXCEPTION_WARNING, PED_EXCEPTION_OK, _("The volume header or the master directory block has " "changed while replaying the journal. You should " "restart Parted.")); return 0; } return 1; }
static PedPartition* amiga_partition_new (const PedDisk* disk, PedPartitionType part_type, const PedFileSystemType* fs_type, PedSector start, PedSector end) { PedPartition *part; PedDevice *dev; PedSector cyl; struct PartitionBlock *partition; struct RigidDiskBlock *rdb; PED_ASSERT(disk != NULL); PED_ASSERT(disk->dev != NULL); PED_ASSERT(disk->disk_specific != NULL); dev = disk->dev; cyl = (PedSector) (dev->hw_geom.sectors * dev->hw_geom.heads); rdb = RDSK(disk->disk_specific); if (!(part = _ped_partition_alloc (disk, part_type, fs_type, start, end))) return NULL; if (ped_partition_is_active (part)) { if (!(part->disk_specific = ped_malloc (disk->dev->sector_size))) { free (part); return NULL; } partition = PART(part->disk_specific); memset(partition, 0, sizeof(struct PartitionBlock)); partition->pb_ID = PED_CPU_TO_BE32(IDNAME_PARTITION); partition->pb_SummedLongs = PED_CPU_TO_BE32(64); partition->pb_HostID = rdb->rdb_HostID; partition->pb_Flags = PED_CPU_TO_BE32(0); /* TODO : use a scheme including the device name and the * partition number, if it is possible */ _amiga_set_bstr("dhx", partition->pb_DriveName, 32); partition->de_TableSize = PED_CPU_TO_BE32(19); partition->de_SizeBlock = PED_CPU_TO_BE32(128); partition->de_SecOrg = PED_CPU_TO_BE32(0); partition->de_Surfaces = PED_CPU_TO_BE32(dev->hw_geom.heads); partition->de_SectorPerBlock = PED_CPU_TO_BE32(1); partition->de_BlocksPerTrack = PED_CPU_TO_BE32(dev->hw_geom.sectors); partition->de_Reserved = PED_CPU_TO_BE32(2); partition->de_PreAlloc = PED_CPU_TO_BE32(0); partition->de_Interleave = PED_CPU_TO_BE32(0); partition->de_LowCyl = PED_CPU_TO_BE32(start/cyl); partition->de_HighCyl = PED_CPU_TO_BE32((end+1)/cyl-1); partition->de_NumBuffers = PED_CPU_TO_BE32(30); partition->de_BufMemType = PED_CPU_TO_BE32(0); partition->de_MaxTransfer = PED_CPU_TO_BE32(0x7fffffff); partition->de_Mask = PED_CPU_TO_BE32(0xffffffff); partition->de_BootPri = PED_CPU_TO_BE32(0); partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); partition->de_Baud = PED_CPU_TO_BE32(0); partition->de_Control = PED_CPU_TO_BE32(0); partition->de_BootBlocks = PED_CPU_TO_BE32(0); } else { part->disk_specific = NULL; } return part; }
/* Update the HFS wrapper mdb and bad blocks file to reflect the new geometry of the embedded HFS+ volume */ static int hfsplus_wrapper_update (PedFileSystem* fs) { uint8_t node[PED_SECTOR_SIZE_DEFAULT]; HfsCPrivateLeafRec ref; HfsExtentKey key; HfsNodeDescriptor* node_desc = (HfsNodeDescriptor*) node; HfsExtentKey* ret_key; HfsExtDescriptor* ret_data; unsigned int i; HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsPrivateFSData* hfs_priv_data = (HfsPrivateFSData*) priv_data->wrapper->type_specific; unsigned int hfs_sect_block = PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) / PED_SECTOR_SIZE_DEFAULT ; PedSector hfsplus_sect = (PedSector) PED_BE32_TO_CPU (priv_data->vh->total_blocks) * ( PED_BE32_TO_CPU (priv_data->vh->block_size) / PED_SECTOR_SIZE_DEFAULT ); unsigned int hfs_blocks_embedded = (hfsplus_sect + hfs_sect_block - 1) / hfs_sect_block; unsigned int hfs_blocks_embedded_old; /* update HFS wrapper MDB */ hfs_blocks_embedded_old = PED_BE16_TO_CPU ( hfs_priv_data->mdb->old_new .embedded.location.block_count ); hfs_priv_data->mdb->old_new.embedded.location.block_count = PED_CPU_TO_BE16 (hfs_blocks_embedded); /* maybe macOS will boot with this */ /* update : yes it does \o/ :) */ hfs_priv_data->mdb->free_blocks = PED_CPU_TO_BE16 ( PED_BE16_TO_CPU (hfs_priv_data->mdb->free_blocks) + hfs_blocks_embedded_old - hfs_blocks_embedded ); if (!hfs_update_mdb(priv_data->wrapper)) return 0; /* force reload bad block list */ if (hfs_priv_data->bad_blocks_loaded) { hfs_free_bad_blocks_list (hfs_priv_data->bad_blocks_xtent_list); hfs_priv_data->bad_blocks_xtent_list = NULL; hfs_priv_data->bad_blocks_xtent_nb = 0; hfs_priv_data->bad_blocks_loaded = 0; } /* clean HFS wrapper allocation map */ for (i = PED_BE16_TO_CPU ( hfs_priv_data->mdb->old_new.embedded .location.start_block ) + hfs_blocks_embedded; i < PED_BE16_TO_CPU ( hfs_priv_data->mdb->old_new.embedded .location.start_block ) + hfs_blocks_embedded_old; i++ ) { CLR_BLOC_OCCUPATION(hfs_priv_data->alloc_map, i); } /* and save it */ if (!ped_geometry_write (fs->geom, hfs_priv_data->alloc_map, PED_BE16_TO_CPU ( hfs_priv_data->mdb->volume_bitmap_block ), ( PED_BE16_TO_CPU ( hfs_priv_data->mdb->total_blocks ) + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8))) return 0; if (!ped_geometry_sync (fs->geom)) return 0; /* search and update the bad blocks file */ key.key_length = sizeof(key) - 1; key.type = HFS_DATA_FORK; key.file_ID = PED_CPU_TO_BE32 (HFS_BAD_BLOCK_ID); key.start = 0; if (!hfs_btree_search (hfs_priv_data->extent_file, (HfsPrivateGenericKey*) &key, NULL, 0, &ref)) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("An error occurred while looking for the mandatory " "bad blocks file.")); return 0; } if (!hfs_file_read_sector (hfs_priv_data->extent_file, node, ref.node_number)) return 0; ret_key = (HfsExtentKey*) (node + ref.record_pos); ret_data = (HfsExtDescriptor*) ( node + ref.record_pos + sizeof (HfsExtentKey) ); while (ret_key->type == key.type && ret_key->file_ID == key.file_ID) { for (i = 0; i < HFS_EXT_NB; i++) { if ( ret_data[i].start_block == hfs_priv_data->mdb->old_new .embedded.location.start_block) { ret_data[i].block_count = hfs_priv_data->mdb->old_new .embedded.location.block_count; /* found ! : update */ if (!hfs_file_write_sector ( hfs_priv_data->extent_file, node, ref.node_number) || !ped_geometry_sync(fs->geom)) return 0; return 1; } } if (ref.record_number < PED_BE16_TO_CPU (node_desc->rec_nb)) { ref.record_number++; } else { ref.node_number = PED_BE32_TO_CPU (node_desc->next); if (!ref.node_number || !hfs_file_read_sector(hfs_priv_data->extent_file, node, ref.node_number)) goto bb_not_found; ref.record_number = 1; } ref.record_pos = PED_BE16_TO_CPU (*((uint16_t *) (node + (PED_SECTOR_SIZE_DEFAULT - 2*ref.record_number)))); ret_key = (HfsExtentKey*) (node + ref.record_pos); ret_data = (HfsExtDescriptor*) ( node + ref.record_pos + sizeof (HfsExtentKey) ); } bb_not_found: /* not found : not a valid hfs+ wrapper : failure */ ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("It seems there is an error in the HFS wrapper: the bad " "blocks file doesn't contain the embedded HFS+ volume.")); return 0; }
static int amiga_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) { struct PartitionBlock *partition; PED_ASSERT (part != NULL); PED_ASSERT (part->disk_specific != NULL); partition = PART(part->disk_specific); part->fs_type = fs_type; if (!fs_type) partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); /* 'LNX\0' */ else if (!strcmp (fs_type->name, "ext2")) partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); /* 'LNX\0' */ else if (!strcmp (fs_type->name, "ext3")) partition->de_DosType = PED_CPU_TO_BE32(0x45585403); /* 'EXT\3' */ else if (is_linux_swap (fs_type->name)) partition->de_DosType = PED_CPU_TO_BE32(0x53575000); /* 'SWP\0' */ else if (!strcmp (fs_type->name, "fat16")) partition->de_DosType = PED_CPU_TO_BE32(0x46415400); /* 'FAT\0' */ else if (!strcmp (fs_type->name, "fat32")) partition->de_DosType = PED_CPU_TO_BE32(0x46415401); /* 'FAT\1'*/ else if (!strcmp (fs_type->name, "hfs")) partition->de_DosType = PED_CPU_TO_BE32(0x48465300); /* 'HFS\0' */ else if (!strcmp (fs_type->name, "jfs")) partition->de_DosType = PED_CPU_TO_BE32(0x4a465300); /* 'JFS\0' */ else if (!strcmp (fs_type->name, "ntfs")) partition->de_DosType = PED_CPU_TO_BE32(0x4e544653); /* 'NTFS' */ else if (!strcmp (fs_type->name, "reiserfs")) partition->de_DosType = PED_CPU_TO_BE32(0x52465300); /* 'RFS\0' */ else if (!strcmp (fs_type->name, "sun-ufs")) partition->de_DosType = PED_CPU_TO_BE32(0x53554653); /* 'SUFS' */ else if (!strcmp (fs_type->name, "hp-ufs")) partition->de_DosType = PED_CPU_TO_BE32(0x48554653); /* 'HUFS' */ else if (!strcmp (fs_type->name, "xfs")) partition->de_DosType = PED_CPU_TO_BE32(0x58465300); /* 'XFS\0' */ else partition->de_DosType = PED_CPU_TO_BE32(0x00000000); /* unknown */ return 1; }