/* in this function */ static int hfs_extent_key_cmp(HfsPrivateGenericKey* a, HfsPrivateGenericKey* b) { HfsExtentKey* key1 = (HfsExtentKey*) a; HfsExtentKey* key2 = (HfsExtentKey*) b; /* do NOT use a substraction, because */ /* 0xFFFFFFFF - 1 = 0xFFFFFFFE so this */ /* would return -2, despite the fact */ /* 0xFFFFFFFF > 1 !!! (this is the 2.4 bug) */ if (key1->file_ID != key2->file_ID) return PED_BE32_TO_CPU(key1->file_ID) < PED_BE32_TO_CPU(key2->file_ID) ? -1 : +1; if (key1->type != key2->type) return (int)(key1->type - key2->type); if (key1->start == key2->start) return 0; /* the whole thing wont work with 16 bits ints */ /* anyway */ return (int)( PED_BE16_TO_CPU(key1->start) - PED_BE16_TO_CPU(key2->start) ); }
static HfsCPrivateCache* hfsplus_cache_extents(PedFileSystem* fs, PedTimer* timer) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsCPrivateCache* ret; unsigned int file_number, block_number; file_number = PED_BE32_TO_CPU(priv_data->vh->file_count); block_number = PED_BE32_TO_CPU(priv_data->vh->total_blocks); ret = hfsc_new_cache(block_number, file_number); if (!ret) return NULL; if (!hfsplus_cache_from_vh(ret, fs, timer) || !hfsplus_cache_from_catalog(ret, fs, timer) || !hfsplus_cache_from_extent(ret, fs, timer) || !hfsplus_cache_from_attributes(ret, fs, timer)) { ped_exception_throw( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Could not cache the file system in memory.")); hfsc_delete_cache(ret); return NULL; } return ret; }
static PedGeometry* xfs_probe (PedGeometry* geom) { PedSector block_size; PedSector block_count; union { struct xfs_sb sb; char bytes [512]; } buf; if (geom->length < XFS_SB_DADDR + 1) return NULL; if (!ped_geometry_read (geom, &buf, XFS_SB_DADDR, 1)) return NULL; if (PED_LE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) { block_size = PED_LE32_TO_CPU (buf.sb.sb_blocksize) / 512; block_count = PED_LE64_TO_CPU (buf.sb.sb_dblocks); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } if (PED_BE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) { block_size = PED_BE32_TO_CPU (buf.sb.sb_blocksize) / 512; block_count = PED_BE64_TO_CPU (buf.sb.sb_dblocks); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } return NULL; }
/* return 0 on error */ int hfs_file_write_sector (HfsPrivateFile* file, void *buf, PedSector sector) { PedSector abs_sector; if (sector >= file->sect_nb) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Trying to write HFS file with CNID %X behind EOF."), PED_BE32_TO_CPU(file->CNID)); return 0; } abs_sector = hfs_file_find_sector (file, sector); if (!abs_sector) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Could not find sector %lli of HFS file with " "CNID %X."), sector, PED_BE32_TO_CPU(file->CNID)); return 0; } return ped_geometry_write (file->fs->geom, buf, abs_sector, 1); }
static struct AmigaBlock * _amiga_read_block (const PedDevice *dev, struct AmigaBlock *blk, PedSector block, struct AmigaIds *ids) { if (!ped_device_read (dev, blk, block, 1)) return NULL; if (ids && !_amiga_id_in_list(PED_BE32_TO_CPU(blk->amiga_ID), ids)) return NULL; if (_amiga_checksum (blk) != 0) { switch (ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL, _("%s : Bad checksum on block %llu of type %s."), __func__, block, _amiga_block_id(PED_BE32_TO_CPU(blk->amiga_ID)))) { case PED_EXCEPTION_CANCEL : return NULL; case PED_EXCEPTION_FIX : _amiga_calculate_checksum(AMIGA(blk)); if (!ped_device_write ((PedDevice*)dev, blk, block, 1)) return NULL; case PED_EXCEPTION_IGNORE : case PED_EXCEPTION_UNHANDLED : default : return blk; } } return blk; }
static PedGeometry* ufs_probe_sun (PedGeometry* geom) { int8_t buf[512 * 3]; struct ufs_super_block *sb; if (geom->length < 5) return 0; if (!ped_geometry_read (geom, buf, 16, 3)) return 0; sb = (struct ufs_super_block *)buf; if (PED_BE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) { PedSector block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512; PedSector block_count = PED_BE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } if (PED_LE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) { PedSector block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512; PedSector block_count = PED_LE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } return NULL; }
static PedGeometry* _generic_apfs_probe (PedGeometry* geom, uint32_t kind) { uint32_t *block; PedSector root; struct PartitionBlock * part; uint32_t blocksize = 1, reserved = 2; PED_ASSERT (geom != NULL); PED_ASSERT (geom->dev != NULL); if (geom->dev->sector_size != 512) return NULL; /* Finds the blocksize and reserved values of the partition block */ if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Failed to allocate partition block\n"), __func__); goto error_part; } if (amiga_find_part(geom, part) != NULL) { reserved = PED_BE32_TO_CPU (part->de_Reserved); blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; } free (part); /* Test boot block */ if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Failed to allocate block\n"), __func__); goto error_block; } if (!ped_device_read (geom->dev, block, geom->start, blocksize)) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Couldn't read boot block %llu\n"), __func__, geom->start); goto error; } if (PED_BE32_TO_CPU (block[0]) != kind) { goto error; } /* Find and test the root block */ root = geom->start+reserved*blocksize; if (!ped_device_read (geom->dev, block, root, blocksize)) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Couldn't read root block %llu\n"), __func__, root); goto error; } if (_apfs_probe_root(block, blocksize, kind) == 1) { free(block); return ped_geometry_duplicate (geom); } error: free (block); error_block: error_part: return NULL; }
static int _amiga_find_free_blocks(const PedDisk *disk, uint32_t *table, struct LinkedBlock *block, uint32_t first, uint32_t type) { PedSector next; PED_ASSERT(disk != NULL); PED_ASSERT(disk->dev != NULL); for (next = first; next != LINK_END; next = PED_BE32_TO_CPU(block->lk_Next)) { if (table[next] != IDNAME_FREE) { switch (ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL, _("%s : Loop detected at block %d."), __func__, next)) { case PED_EXCEPTION_CANCEL : return 0; case PED_EXCEPTION_FIX : /* TODO : Need to add fixing code */ case PED_EXCEPTION_IGNORE : case PED_EXCEPTION_UNHANDLED : default : return 1; } } if (!_amiga_read_block (disk->dev, AMIGA(block), next, NULL)) { return 0; } if (PED_BE32_TO_CPU(block->lk_ID) != type) { switch (ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : The %s list seems bad at block %s."), __func__, _amiga_block_id(PED_BE32_TO_CPU(block->lk_ID)), next)) { /* TODO : to more subtile things here */ case PED_EXCEPTION_CANCEL : case PED_EXCEPTION_UNHANDLED : default : return 0; } } table[next] = type; if (PED_BE32_TO_CPU(block->lk_ID) == IDNAME_FILESYSHEADER) { if (_amiga_find_free_blocks(disk, table, block, PED_BE32_TO_CPU(LNK2(block)->lk2_Linked), IDNAME_LOADSEG) == 0) return 0; } } return 1; }
static int _amiga_checksum (struct AmigaBlock *blk) { uint32_t *rdb = (uint32_t *) blk; uint32_t sum; int i, end; sum = PED_BE32_TO_CPU (rdb[0]); end = PED_BE32_TO_CPU (rdb[1]); if (end > PED_SECTOR_SIZE_DEFAULT) end = PED_SECTOR_SIZE_DEFAULT; for (i = 1; i < end; i++) sum += PED_BE32_TO_CPU (rdb[i]); return sum; }
/* save any dirty sector of the allocation bitmap file */ static int hfsplus_save_allocation(PedFileSystem *fs) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; unsigned int map_sectors, i, j; int ret = 1; map_sectors = ( PED_BE32_TO_CPU (priv_data->vh->total_blocks) + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8); for (i = 0; i < map_sectors;) { for (j = i; (TST_BLOC_OCCUPATION(priv_data->dirty_alloc_map,j)); ++j) CLR_BLOC_OCCUPATION(priv_data->dirty_alloc_map,j); if (j-i) { ret = hfsplus_file_write(priv_data->allocation_file, priv_data->alloc_map + i * PED_SECTOR_SIZE_DEFAULT, i, j-i) && ret; i = j; } else ++i; } return ret; }
static int hfsplus_clobber (PedGeometry* geom) { unsigned int i = 1; uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; HfsMasterDirectoryBlock *mdb; mdb = (HfsMasterDirectoryBlock *) buf; if (!ped_geometry_read (geom, buf, 2, 1)) return 0; if (PED_BE16_TO_CPU (mdb->signature) == HFS_SIGNATURE) { /* embedded hfs+ */ PedGeometry *embedded; i = PED_BE32_TO_CPU(mdb->block_size) / PED_SECTOR_SIZE_DEFAULT; embedded = ped_geometry_new ( geom->dev, (PedSector) geom->start + PED_BE16_TO_CPU (mdb->start_block) + (PedSector) PED_BE16_TO_CPU ( mdb->old_new.embedded.location.start_block ) * i, (PedSector) PED_BE16_TO_CPU ( mdb->old_new.embedded.location.block_count ) * i ); if (!embedded) i = 0; else { i = hfs_clobber (embedded); ped_geometry_destroy (embedded); } } /* non-embedded or envelop destroy as hfs */ return ( hfs_clobber (geom) && i ); }
int hfsj_update_jl(PedFileSystem* fs, uint32_t block) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; PedSector sector; uint64_t offset; HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsJJournalInfoBlock* jib; int binsect; binsect = PED_BE32_TO_CPU(priv_data->vh->block_size) / PED_SECTOR_SIZE_DEFAULT; sector = (PedSector) priv_data->jib_start_block * binsect; if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) return 0; jib = (HfsJJournalInfoBlock*) buf; offset = (uint64_t)block * PED_SECTOR_SIZE_DEFAULT * binsect; jib->offset = PED_CPU_TO_BE64(offset); if (!ped_geometry_write(priv_data->plus_geom, buf, sector, 1) || !ped_geometry_sync(priv_data->plus_geom)) return 0; priv_data->jl_start_block = block; return 1; }
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; }
static PedPartition* _parse_boot_file (PedDisk* disk, struct volume_directory* vd) { PedPartition* part; DVHPartData* dvh_part_data; PedSector start = PED_BE32_TO_CPU (vd->vd_lbn); int length = PED_BE32_TO_CPU (vd->vd_nbytes); part = ped_partition_new (disk, PED_PARTITION_LOGICAL, NULL, start, start + length/512 - 1); if (!part) return NULL; dvh_part_data = part->disk_specific; dvh_part_data->real_file_size = length; strncpy (dvh_part_data->name, vd->vd_name, VDNAMESIZE); dvh_part_data->name[VDNAMESIZE] = 0; return part; }
/* two's complement 32-bit checksum */ static uint32_t _GL_ATTRIBUTE_PURE _checksum (const uint32_t* base, size_t size) { uint32_t sum = 0; size_t i; for (i = 0; i < size / sizeof (uint32_t); i++) sum = sum - PED_BE32_TO_CPU (base[i]); return sum; }
static PedPartition* _parse_partition (PedDisk* disk, struct partition_table* pt) { PedPartition* part; DVHPartData* dvh_part_data; PedSector start = PED_BE32_TO_CPU (pt->pt_firstlbn); PedSector length = PED_BE32_TO_CPU (pt->pt_nblks); part = ped_partition_new (disk, pt->pt_type ? 0 : PED_PARTITION_EXTENDED, NULL, start, start + length - 1); if (!part) return NULL; dvh_part_data = part->disk_specific; dvh_part_data->type = PED_BE32_TO_CPU (pt->pt_type); strcpy (dvh_part_data->name, ""); return part; }
static PedGeometry* ufs_probe_hp (PedGeometry* geom) { int8_t buf[1536]; struct ufs_super_block *sb; PedSector block_size; PedSector block_count; if (geom->length < 5) return 0; if (!ped_geometry_read (geom, buf, 16, 3)) return 0; sb = (struct ufs_super_block *)buf; /* Try sane bytesex */ switch (PED_BE32_TO_CPU(sb->fs_magic)) { case UFS_MAGIC_LFN: case UFS_MAGIC_FEA: case UFS_MAGIC_4GB: block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512; block_count = PED_BE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } /* Try perverted bytesex */ switch (PED_LE32_TO_CPU(sb->fs_magic)) { case UFS_MAGIC_LFN: case UFS_MAGIC_FEA: case UFS_MAGIC_4GB: block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512; block_count = PED_LE32_TO_CPU(sb->fs_size); return ped_geometry_new (geom->dev, geom->start, block_size * block_count); } return NULL; }
/* Used by hfsplus_probe and hfs_probe */ PedGeometry* hfs_and_wrapper_probe (PedGeometry* geom) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; HfsMasterDirectoryBlock *mdb; PedGeometry* geom_ret; PedSector search, max; PED_ASSERT (geom != NULL); PED_ASSERT (hfsc_can_use_geom (geom)); mdb = (HfsMasterDirectoryBlock *) buf; /* is 5 an intelligent value ? */ if ((geom->length < 5) || (!ped_geometry_read (geom, buf, 2, 1)) || (mdb->signature != PED_CPU_TO_BE16 (HFS_SIGNATURE)) ) return NULL; search = ((PedSector) PED_BE16_TO_CPU (mdb->start_block) + ((PedSector) PED_BE16_TO_CPU (mdb->total_blocks) * (PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT ))); max = search + (PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT); if (!(geom_ret = ped_geometry_new (geom->dev, geom->start, search + 2))) return NULL; for (; search < max; search++) { if (!ped_geometry_set (geom_ret, geom_ret->start, search + 2) || !ped_geometry_read (geom_ret, buf, search, 1)) break; if (mdb->signature == PED_CPU_TO_BE16 (HFS_SIGNATURE)) return geom_ret; } ped_geometry_destroy (geom_ret); return NULL; }
static int dvh_probe (const PedDevice *dev) { struct volume_header *vh; void *label; if (!ptt_read_sector (dev, 0, &label)) return 0; vh = (struct volume_header *) label; bool found = PED_BE32_TO_CPU (vh->vh_magic) == VHMAGIC; free (label); return found; }
static uint32_t _amiga_find_rdb (PedDevice *dev, struct RigidDiskBlock *rdb) { int i; struct AmigaIds *ids; ids = _amiga_add_id (IDNAME_RIGIDDISK, NULL); for (i = 0; i<RDB_LOCATION_LIMIT; i++) { if (!_amiga_read_block (dev, AMIGA(rdb), i, ids)) { continue; } if (PED_BE32_TO_CPU (rdb->rdb_ID) == IDNAME_RIGIDDISK) { _amiga_free_ids (ids); return i; } } _amiga_free_ids (ids); return AMIGA_RDB_NOT_FOUND; }
/* On error this function returns 0 */ PedSector hfs_get_empty_end (const PedFileSystem *fs) { HfsPrivateFSData* priv_data = (HfsPrivateFSData*) fs->type_specific; HfsMasterDirectoryBlock* mdb = priv_data->mdb; unsigned int block, last_bad, end_free_blocks; /* find the next block to the last bad block of the volume */ if (!hfs_read_bad_blocks (fs)) return 0; HfsPrivateLinkExtent* l; last_bad = 0; for (l = priv_data->bad_blocks_xtent_list; l; l = l->next) { if ((unsigned int) PED_BE16_TO_CPU (l->extent.start_block) + PED_BE16_TO_CPU (l->extent.block_count) > last_bad) last_bad = PED_BE16_TO_CPU (l->extent.start_block) + PED_BE16_TO_CPU (l->extent.block_count); } /* Count the free blocks from last_bad to the end of the volume */ end_free_blocks = 0; for (block = last_bad; block < PED_BE16_TO_CPU (mdb->total_blocks); block++) { if (!TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) end_free_blocks++; } /* Calculate the block that will by the first free at the end of the volume */ block = PED_BE16_TO_CPU (mdb->total_blocks) - end_free_blocks; return (PedSector) PED_BE16_TO_CPU (mdb->start_block) + (PedSector) block * (PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT); }
/* 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; }
/* return 0 on error */ int hfsplus_pack_free_space_from_block (PedFileSystem *fs, unsigned int fblock, PedTimer* timer, unsigned int to_free) { PedSector bytes_buff; HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsPVolumeHeader* vh = priv_data->vh; HfsCPrivateCache* cache; unsigned int to_fblock = fblock; unsigned int start = fblock; unsigned int divisor = PED_BE32_TO_CPU (vh->total_blocks) + 1 - start - to_free; int ret; PED_ASSERT (!hfsp_block); cache = hfsplus_cache_extents (fs, timer); if (!cache) return 0; /* Calculate the size of the copy buffer : * Takes BLOCK_MAX_BUFF HFS blocks, but if > BYTES_MAX_BUFF * takes the maximum number of HFS blocks so that the buffer * will remain smaller than or equal to BYTES_MAX_BUFF, with * a minimum of 1 HFS block */ bytes_buff = PED_BE32_TO_CPU (priv_data->vh->block_size) * (PedSector) BLOCK_MAX_BUFF; if (bytes_buff > BYTES_MAX_BUFF) { hfsp_block_count = BYTES_MAX_BUFF / PED_BE32_TO_CPU (priv_data->vh->block_size); if (!hfsp_block_count) hfsp_block_count = 1; bytes_buff = (PedSector) hfsp_block_count * PED_BE32_TO_CPU (priv_data->vh->block_size); } else hfsp_block_count = BLOCK_MAX_BUFF; /* If the cache code requests more space, give it to him */ if (bytes_buff < hfsc_cache_needed_buffer (cache)) bytes_buff = hfsc_cache_needed_buffer (cache); hfsp_block = (uint8_t*) ped_malloc (bytes_buff); if (!hfsp_block) goto error_cache; if (!hfsplus_read_bad_blocks (fs)) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Bad blocks list could not be loaded.")); goto error_alloc; } while ( fblock < ( priv_data->plus_geom->length - 2 ) / ( PED_BE32_TO_CPU (vh->block_size) / PED_SECTOR_SIZE_DEFAULT ) ) { if (TST_BLOC_OCCUPATION (priv_data->alloc_map, fblock) && (!hfsplus_is_bad_block (fs, fblock))) { if (!(ret = hfsplus_move_extent_starting_at (fs, &fblock, &to_fblock, cache))) to_fblock = ++fblock; else if (ret == -1) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("An error occurred during extent " "relocation.")); goto error_alloc; } } else { fblock++; } ped_timer_update(timer, (float)(to_fblock - start) / divisor); } free (hfsp_block); hfsp_block = NULL; hfsp_block_count = 0; hfsc_delete_cache (cache); return 1; error_alloc: free (hfsp_block); hfsp_block = NULL; hfsp_block_count = 0; error_cache: hfsc_delete_cache (cache); return 0; }
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; }
/* -1 is ok because there can only be 2^32-1 blocks, so the max possible last one is 2^32-2 (and anyway it contains Alternate VH), so -1 (== 2^32-1[2^32]) never represent a valid block */ static int hfsplus_effect_move_extent (PedFileSystem *fs, unsigned int *ptr_fblock, unsigned int *ptr_to_fblock, unsigned int size) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; unsigned int i, ok = 0; unsigned int next_to_fblock; unsigned int start, stop; PED_ASSERT (hfsp_block != NULL); PED_ASSERT (*ptr_to_fblock <= *ptr_fblock); /* quiet GCC */ start = stop = 0; /* Try to fit the extent AT or _BEFORE_ the wanted place, or then in the gap between dest and source. If failed try to fit the extent after source, for 2 pass relocation The extent is always copied in a non overlapping way */ /* Backward search */ /* 1 pass relocation AT or BEFORE *ptr_to_fblock */ if (*ptr_to_fblock != *ptr_fblock) { start = stop = *ptr_fblock < *ptr_to_fblock+size ? *ptr_fblock : *ptr_to_fblock+size; while (start && stop-start != size) { --start; if (TST_BLOC_OCCUPATION(priv_data->alloc_map,start)) stop = start; } ok = (stop-start == size); } /* Forward search */ /* 1 pass relocation in the gap merged with 2 pass reloc after source */ if (!ok && *ptr_to_fblock != *ptr_fblock) { start = stop = *ptr_to_fblock+1; while (stop < PED_BE32_TO_CPU(priv_data->vh->total_blocks) && stop-start != size) { if (TST_BLOC_OCCUPATION(priv_data->alloc_map,stop)) start = stop + 1; ++stop; } ok = (stop-start == size); } /* new non overlapping room has been found ? */ if (ok) { /* enough room */ PedSector abs_sector; unsigned int ai, j, block; unsigned int block_sz = (PED_BE32_TO_CPU ( priv_data->vh->block_size) / PED_SECTOR_SIZE_DEFAULT); if (stop > *ptr_to_fblock && stop <= *ptr_fblock) /* Fit in the gap */ next_to_fblock = stop; else /* Before or after the gap */ next_to_fblock = *ptr_to_fblock; /* move blocks */ for (i = 0; i < size; /*i++*/) { j = size - i; j = (j < hfsp_block_count) ? j : hfsp_block_count ; abs_sector = (PedSector) (*ptr_fblock + i) * block_sz; if (!ped_geometry_read (priv_data->plus_geom, hfsp_block, abs_sector, block_sz * j)) return -1; abs_sector = (PedSector) (start + i) * block_sz; if (!ped_geometry_write (priv_data->plus_geom, hfsp_block, abs_sector, block_sz * j)) return -1; for (ai = i+j; i < ai; i++) { /* free source block */ block = *ptr_fblock + i; CLR_BLOC_OCCUPATION(priv_data->alloc_map,block); SET_BLOC_OCCUPATION(priv_data->dirty_alloc_map, block/(PED_SECTOR_SIZE_DEFAULT*8)); /* set dest block */ block = start + i; SET_BLOC_OCCUPATION(priv_data->alloc_map,block); SET_BLOC_OCCUPATION(priv_data->dirty_alloc_map, block/(PED_SECTOR_SIZE_DEFAULT*8)); } } if (!ped_geometry_sync_fast (priv_data->plus_geom)) return -1; *ptr_fblock += size; *ptr_to_fblock = next_to_fblock; } else { if (*ptr_fblock != *ptr_to_fblock) /* not enough room */ ped_exception_throw (PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE, _("An extent has not been relocated.")); start = *ptr_fblock; *ptr_fblock = *ptr_to_fblock = start + size; } return start; }
static int hfsplus_cache_from_catalog(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; HfsPCatalogKey* catalog_key; HfsPCatalog* catalog_data; HfsPExtDescriptor* extent; unsigned int leaf_node, record_number; unsigned int i, j, size, bsize; uint32_t jib = priv_data->jib_start_block, jl = priv_data->jl_start_block; if (!priv_data->catalog_file->sect_nb) { ped_exception_throw ( PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK, _("This HFS+ volume has no catalog file. " "This is very unusual!")); return 1; } /* Search the extent starting at *ptr_block in the catalog file */ if (!hfsplus_file_read_sector (priv_data->catalog_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->catalog_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; uint8_t where; catalog_key = (HfsPCatalogKey*) ( node + PED_BE16_TO_CPU (*((uint16_t *) (node+(bsize - 2*i)))) ); skip = ( 2 + PED_BE16_TO_CPU (catalog_key->key_length) + 1) & ~1; catalog_data = (HfsPCatalog*) (((uint8_t*)catalog_key) + skip); /* check for obvious error in FS */ if (((uint8_t*)catalog_key - node < HFS_FIRST_REC) || ((uint8_t*)catalog_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 (PED_BE16_TO_CPU(catalog_data->type)!=HFS_CAT_FILE) continue; extent = catalog_data->sel.file.data_fork.extents; for (j = 0; j < HFSP_EXT_NB; ++j) { if (!extent[j].block_count) break; where = CR_BTREE_CAT; if ( PED_BE32_TO_CPU(extent[j].start_block) == jib ) { jib = 0; where = CR_BTREE_CAT_JIB; } else if ( PED_BE32_TO_CPU(extent[j].start_block) == jl ) { jl = 0; where = CR_BTREE_CAT_JL; } 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; } } extent = catalog_data->sel.file.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_CAT, j ) ) { free (node); return 0; } } } } free (node); return 1; }
static int hfsplus_cache_from_vh(HfsCPrivateCache* cache, PedFileSystem* fs, PedTimer* timer) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; HfsPExtDescriptor* extent; unsigned int j; extent = priv_data->vh->allocation_file.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), 0, /* unused for vh */ ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), 1, /* load / save 1 sector */ CR_PRIM_ALLOC, j ) ) return 0; } extent = priv_data->vh->extents_file.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), 0, /* unused for vh */ ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), 1, /* load / save 1 sector */ CR_PRIM_EXT, j ) ) return 0; } extent = priv_data->vh->catalog_file.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), 0, /* unused for vh */ ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), 1, /* load / save 1 sector */ CR_PRIM_CAT, j ) ) return 0; } extent = priv_data->vh->attributes_file.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), 0, /* unused for vh */ ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), 1, /* load / save 1 sector */ CR_PRIM_ATTR, j ) ) return 0; } extent = priv_data->vh->startup_file.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), 0, /* unused for vh */ ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), 1, /* load / save 1 sector */ CR_PRIM_START, j ) ) return 0; } return 1; }
static int dvh_read (PedDisk* disk) { DVHDiskData* dvh_disk_data = disk->disk_specific; int i; struct volume_header vh; char boot_name [BFNAMESIZE + 1]; #ifndef DISCOVER_ONLY int write_back = 0; #endif PED_ASSERT (dvh_disk_data != NULL); ped_disk_delete_all (disk); void *s0; if (!ptt_read_sector (disk->dev, 0, &s0)) return 0; memcpy (&vh, s0, sizeof vh); free (s0); if (_checksum ((uint32_t*) &vh, sizeof (struct volume_header))) { if (ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL, _("Checksum is wrong, indicating the partition " "table is corrupt.")) == PED_EXCEPTION_CANCEL) return 0; } PED_ASSERT (PED_BE32_TO_CPU (vh.vh_magic) == VHMAGIC); dvh_disk_data->dev_params = vh.vh_dp; strncpy (boot_name, vh.vh_bootfile, BFNAMESIZE); boot_name[BFNAMESIZE] = 0; /* normal partitions */ for (i = 0; i < NPARTAB; i++) { PedPartition* part; if (!vh.vh_pt[i].pt_nblks) continue; /* Skip the whole-disk partition, parted disklikes overlap */ if (PED_BE32_TO_CPU (vh.vh_pt[i].pt_type) == PTYPE_VOLUME) continue; part = _parse_partition (disk, &vh.vh_pt[i]); if (!part) goto error_delete_all; part->fs_type = ped_file_system_probe (&part->geom); part->num = i + 1; if (PED_BE16_TO_CPU (vh.vh_rootpt) == i) ped_partition_set_flag (part, PED_PARTITION_ROOT, 1); if (PED_BE16_TO_CPU (vh.vh_swappt) == i) ped_partition_set_flag (part, PED_PARTITION_SWAP, 1); PedConstraint *constraint_exact = ped_constraint_exact (&part->geom); bool ok = ped_disk_add_partition (disk, part, constraint_exact); ped_constraint_destroy (constraint_exact); if (!ok) { ped_partition_destroy (part); goto error_delete_all; } } if (!ped_disk_extended_partition (disk)) { #ifdef DISCOVER_ONLY return 1; #else switch (_handle_no_volume_header (disk)) { case PED_EXCEPTION_CANCEL: return 0; case PED_EXCEPTION_IGNORE: return 1; case PED_EXCEPTION_FIX: write_back = 1; break; default: break; } #endif } /* boot partitions */ for (i = 0; i < NVDIR; i++) { PedPartition* part; if (!vh.vh_vd[i].vd_nbytes) continue; part = _parse_boot_file (disk, &vh.vh_vd[i]); if (!part) goto error_delete_all; part->fs_type = ped_file_system_probe (&part->geom); part->num = NPARTAB + i + 1; if (!strcmp (boot_name, ped_partition_get_name (part))) ped_partition_set_flag (part, PED_PARTITION_BOOT, 1); PedConstraint *constraint_exact = ped_constraint_exact (&part->geom); bool ok = ped_disk_add_partition (disk, part, constraint_exact); ped_constraint_destroy (constraint_exact); if (!ok) { ped_partition_destroy (part); goto error_delete_all; } } #ifndef DISCOVER_ONLY if (write_back) dvh_write (disk); #endif return 1; error_delete_all: ped_disk_delete_all (disk); return 0; }
/* other BTrees has well */ int hfs_btree_search (HfsPrivateFile* b_tree_file, HfsPrivateGenericKey* key, void *record_out, unsigned int record_size, HfsCPrivateLeafRec* record_ref) { uint8_t node[PED_SECTOR_SIZE_DEFAULT]; HfsHeaderRecord* header; HfsNodeDescriptor* desc = (HfsNodeDescriptor*) node; HfsPrivateGenericKey* record_key = NULL; unsigned int node_number, record_number; int i; /* Read the header node */ if (!hfs_file_read_sector(b_tree_file, node, 0)) return 0; header = ((HfsHeaderRecord*) (node + PED_BE16_TO_CPU(*((uint16_t *) (node+(PED_SECTOR_SIZE_DEFAULT-2)))))); /* Get the node number of the root */ node_number = PED_BE32_TO_CPU(header->root_node); if (!node_number) return 0; /* Read the root node */ if (!hfs_file_read_sector(b_tree_file, node, node_number)) return 0; /* Follow the white rabbit */ while (1) { record_number = PED_BE16_TO_CPU (desc->rec_nb); for (i = record_number; i; i--) { record_key = (HfsPrivateGenericKey*) (node + PED_BE16_TO_CPU(*((uint16_t *) (node+(PED_SECTOR_SIZE_DEFAULT - 2*i))))); /* check for obvious error in FS */ if (((uint8_t*)record_key - node < HFS_FIRST_REC) || ((uint8_t*)record_key - node >= PED_SECTOR_SIZE_DEFAULT - 2 * (signed)(record_number+1))) { ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("The file system contains errors.")); return 0; } if (hfs_extent_key_cmp(record_key, key) <= 0) break; } if (!i) return 0; if (desc->type == HFS_IDX_NODE) { unsigned int skip; skip = (1 + record_key->key_length + 1) & ~1; node_number = PED_BE32_TO_CPU (*((uint32_t *) (((uint8_t *) record_key) + skip))); if (!hfs_file_read_sector(b_tree_file, node, node_number)) return 0; } else break; } /* copy the result if needed */ if (record_size) memcpy (record_out, record_key, record_size); /* send record reference if needed */ if (record_ref) { record_ref->node_size = 1; /* in sectors */ record_ref->node_number = node_number; record_ref->record_pos = (uint8_t*)record_key - node; record_ref->record_number = i; } /* success */ return 1; }