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; }
FatTraverseInfo* fat_traverse_begin (PedFileSystem* fs, FatCluster start_cluster, const char* dir_name) { FatSpecific* fs_info = FAT_SPECIFIC (fs); FatTraverseInfo* trav_info; trav_info = (FatTraverseInfo*) ped_malloc (sizeof (FatTraverseInfo)); if (!trav_info) goto error; trav_info->dir_name = strdup (dir_name); if (!trav_info->dir_name) goto error_free_trav_info; trav_info->fs = fs; trav_info->is_legacy_root_dir = (fs_info->fat_type == FAT_TYPE_FAT16) && (start_cluster == 0); trav_info->dirty = 0; trav_info->eof = 0; trav_info->current_entry = -1; if (trav_info->is_legacy_root_dir) { trav_info->buffer_size = 512 * fs_info->root_dir_sector_count; } else { trav_info->next_buffer = start_cluster; trav_info->buffer_size = fs_info->cluster_size; } trav_info->dir_entries = (FatDirEntry*) ped_malloc (trav_info->buffer_size); if (!trav_info->dir_entries) goto error_free_dir_name; if (trav_info->is_legacy_root_dir) { if (!ped_geometry_read (fs->geom, trav_info->dir_entries, fs_info->root_dir_offset, fs_info->root_dir_sector_count)) goto error_free_dir_entries; } else { if (!read_next_dir_buffer (trav_info)) goto error_free_dir_entries; } return trav_info; error_free_dir_entries: free (trav_info->dir_entries); error_free_dir_name: free (trav_info->dir_name); error_free_trav_info: free (trav_info); error: return NULL; }
static PedPartition* dvh_partition_new (const PedDisk* disk, PedPartitionType part_type, const PedFileSystemType* fs_type, PedSector start, PedSector end) { PedPartition* part; DVHPartData* dvh_part_data; part = _ped_partition_alloc (disk, part_type, fs_type, start, end); if (!part) goto error; if (!ped_partition_is_active (part)) { part->disk_specific = NULL; return part; } dvh_part_data = part->disk_specific = ped_malloc (sizeof (DVHPartData)); if (!dvh_part_data) goto error_free_part; dvh_part_data->type = (part_type == PED_PARTITION_EXTENDED) ? PTYPE_VOLHDR : PTYPE_RAW; strcpy (dvh_part_data->name, ""); dvh_part_data->real_file_size = part->geom.length * 512; return part; error_free_part: _ped_partition_free (part); error: return NULL; }
static int loop_write (const PedDisk* disk) { size_t buflen = disk->dev->sector_size; char *buf = ped_malloc (buflen); if (buf == NULL) return 0; if (ped_disk_get_partition (disk, 1)) { if (!ped_device_read (disk->dev, buf, 0, 1)) { free (buf); return 0; } if (strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)) != 0) { free (buf); return 1; } memset (buf, 0, strlen (LOOP_SIGNATURE)); return ped_device_write (disk->dev, buf, 0, 1); } memset (buf, 0, buflen); strcpy (buf, LOOP_SIGNATURE); int write_ok = ped_device_write (disk->dev, buf, 0, 1); free (buf); return write_ok; }
static PedPartition* bsd_partition_new (const PedDisk* disk, PedPartitionType part_type, const PedFileSystemType* fs_type, PedSector start, PedSector end) { PedPartition* part; BSDPartitionData* bsd_data; part = _ped_partition_alloc (disk, part_type, fs_type, start, end); if (!part) goto error; if (ped_partition_is_active (part)) { part->disk_specific = bsd_data = ped_malloc (sizeof (BSDPartitionData)); if (!bsd_data) goto error_free_part; bsd_data->type = 0; bsd_data->boot = 0; bsd_data->raid = 0; bsd_data->lvm = 0; } else { part->disk_specific = NULL; } return part; error_free_part: free (part); error: return 0; }
static PedPartition* dvh_partition_duplicate (const PedPartition* part) { PedPartition* result; DVHPartData* part_data = part->disk_specific; DVHPartData* result_data; result = _ped_partition_alloc (part->disk, part->type, part->fs_type, part->geom.start, part->geom.end); if (!result) goto error; result->num = part->num; if (!ped_partition_is_active (part)) { result->disk_specific = NULL; return result; } result_data = result->disk_specific = ped_malloc (sizeof (DVHPartData)); if (!result_data) goto error_free_part; result_data->type = part_data->type; strcpy (result_data->name, part_data->name); result_data->real_file_size = part_data->real_file_size; return result; error_free_part: _ped_partition_free (result); error: return NULL; }
static PedPartition* pc98_partition_new ( const PedDisk* disk, PedPartitionType part_type, const PedFileSystemType* fs_type, PedSector start, PedSector end) { PedPartition* part; PC98PartitionData* pc98_data; part = _ped_partition_alloc (disk, part_type, fs_type, start, end); if (!part) goto error; if (ped_partition_is_active (part)) { part->disk_specific = pc98_data = ped_malloc (sizeof (PC98PartitionData)); if (!pc98_data) goto error_free_part; pc98_data->ipl_sector = 0; pc98_data->hidden = 0; pc98_data->boot = 0; strcpy (pc98_data->name, ""); } else { part->disk_specific = NULL; } return part; error_free_part: free (part); error: return 0; }
static PedDisk* dvh_duplicate (const PedDisk* disk) { PedDisk* new_disk; DVHDiskData* new_dvh_disk_data; DVHDiskData* old_dvh_disk_data = disk->disk_specific; PED_ASSERT (old_dvh_disk_data != NULL); new_disk = ped_disk_new_fresh (disk->dev, &dvh_disk_type); if (!new_disk) goto error; new_disk->disk_specific = new_dvh_disk_data = ped_malloc (sizeof (DVHDiskData)); if (!new_dvh_disk_data) goto error_free_new_disk; new_dvh_disk_data->dev_params = old_dvh_disk_data->dev_params; return new_disk; error_free_new_disk: free (new_disk); error: return NULL; }
void* ped_calloc (size_t size) { void* buf = ped_malloc (size); memset (buf, 0, size); return buf; }
static PedDisk* bsd_alloc (const PedDevice* dev) { PedDisk* disk; BSDDiskData* bsd_specific; BSDRawLabel* label; PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0); disk = _ped_disk_alloc ((PedDevice*)dev, &bsd_disk_type); if (!disk) goto error; disk->disk_specific = bsd_specific = ped_malloc (sizeof (BSDDiskData)); if (!bsd_specific) goto error_free_disk; /* Initialize the first byte to zero, so that the code in bsd_write knows to call _probe_and_add_boot_code. Initializing all of the remaining buffer is a little wasteful, but the alternative is to figure out why a block at offset 340 would otherwise be used uninitialized. */ memset(bsd_specific->boot_code, 0, sizeof (bsd_specific->boot_code)); label = (BSDRawLabel*) (bsd_specific->boot_code + BSD_LABEL_OFFSET); label->d_magic = PED_CPU_TO_LE32 (BSD_DISKMAGIC); label->d_type = PED_CPU_TO_LE16 (BSD_DTYPE_SCSI); label->d_flags = 0; label->d_secsize = PED_CPU_TO_LE16 (dev->sector_size); label->d_nsectors = PED_CPU_TO_LE32 (dev->bios_geom.sectors); label->d_ntracks = PED_CPU_TO_LE32 (dev->bios_geom.heads); label->d_ncylinders = PED_CPU_TO_LE32 (dev->bios_geom.cylinders); label->d_secpercyl = PED_CPU_TO_LE32 (dev->bios_geom.sectors * dev->bios_geom.heads); label->d_secperunit = PED_CPU_TO_LE32 (dev->bios_geom.sectors * dev->bios_geom.heads * dev->bios_geom.cylinders); label->d_rpm = PED_CPU_TO_LE16 (3600); label->d_interleave = PED_CPU_TO_LE16 (1);; label->d_trackskew = 0; label->d_cylskew = 0; label->d_headswitch = 0; label->d_trkseek = 0; label->d_magic2 = PED_CPU_TO_LE32 (BSD_DISKMAGIC); label->d_bbsize = PED_CPU_TO_LE32 (BSD_BBSIZE); label->d_sbsize = PED_CPU_TO_LE32 (BSD_SBSIZE); label->d_npartitions = 0; label->d_checksum = xbsd_dkcksum (label); return disk; error_free_disk: free (disk); error: return NULL; }
static PedDevice* beos_new (const char* path) { struct stat stat_info; PedDevice* dev; PED_ASSERT(path != NULL, return NULL); dev = (PedDevice*) ped_malloc (sizeof (PedDevice)); if (!dev) goto error; dev->path = strdup(path); if (!dev->path) goto error_free_dev; dev->arch_specific = (BEOSSpecific*) ped_malloc(sizeof(BEOSSpecific)); if (dev->arch_specific == NULL) goto error_free_path; dev->open_count = 0; dev->read_only = 0; dev->external_mode = 0; dev->dirty = 0; dev->boot_dirty = 0; if ((dev->type=_device_init(dev)) <= 0) goto error_free_arch_specific; /* All OK! */ return dev; error_free_arch_specific: free (dev->arch_specific); error_free_path: free (dev->path); error_free_dev: free (dev); error: return NULL; }
static struct AmigaIds * _amiga_add_id (uint32_t id, struct AmigaIds *ids) { struct AmigaIds *newid; if ((newid=ped_malloc(sizeof (struct AmigaIds)))==NULL) return 0; newid->ID = id; newid->next = ids; return newid; }
static char* ped_strdup (const char *str) { char *result; result = ped_malloc (strlen (str) + 1); if (!result) return NULL; strcpy (result, str); return result; }
struct AmigaIds * _amiga_add_id (uint32_t id, struct AmigaIds *ids) { struct AmigaIds *newid; if ((newid=ped_malloc(sizeof (struct AmigaIds)))==NULL) { ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("%s : Failed to allocate id list element\n"), __func__); return 0; } newid->ID = id; newid->next = ids; return newid; }
/** * Send a debug message. * Do not call this directly -- use PED_DEBUG() instead. * * level log level, 0 ~= "print definitely" */ void ped_debug ( const int level, const char* file, int line, const char* function, const char* msg, ... ) { va_list arg_list; char* msg_concat = ped_malloc(8192); va_start ( arg_list, msg ); vsnprintf ( msg_concat, 8192, msg, arg_list ); va_end ( arg_list ); debug_handler ( level, file, line, function, msg_concat ); free ( msg_concat ); }
static int amiga_probe (const PedDevice *dev) { struct RigidDiskBlock *rdb; uint32_t found; PED_ASSERT(dev != NULL); if ((rdb=RDSK(ped_malloc(dev->sector_size)))==NULL) return 0; found = _amiga_find_rdb (dev, rdb); free (rdb); return (found == AMIGA_RDB_NOT_FOUND ? 0 : 1); }
int fat_boot_sector_set_boot_code (FatBootSector** bsp, const PedFileSystem* fs) { FatSpecific* fs_info = FAT_SPECIFIC (fs); PED_ASSERT (bsp != NULL); *bsp = ped_malloc (fs->geom->dev->sector_size); FatBootSector *bs = *bsp; PED_ASSERT (bs != NULL); memset (bs, 0, 512); memcpy (bs->boot_jump, FAT_BOOT_JUMP, 3); memcpy (bs->u.fat32.boot_code, FAT_BOOT_CODE, FAT_BOOT_CODE_LENGTH); return 1; }
/** * \brief Creates a timer. * * Context will be passed in the \p context * argument to the \p handler, when it is invoked. * * \return a new PedTimer */ PedTimer* ped_timer_new (PedTimerHandler* handler, void* context) { PedTimer* timer; PED_ASSERT (handler != NULL); timer = (PedTimer*) ped_malloc (sizeof (PedTimer)); if (!timer) return NULL; timer->handler = handler; timer->context = context; ped_timer_reset (timer); return timer; }
/* Open the data fork of a file with its first three extents and its CNID */ HfsPrivateFile* hfs_file_open (PedFileSystem *fs, uint32_t CNID, HfsExtDataRec ext_desc, PedSector sect_nb) { HfsPrivateFile* file; file = (HfsPrivateFile*) ped_malloc (sizeof (HfsPrivateFile)); if (!file) return NULL; file->fs = fs; file->sect_nb = sect_nb; file->CNID = CNID; memcpy(file->first, ext_desc, sizeof (HfsExtDataRec)); file->start_cache = 0; return file; }
static PedDisk* dvh_alloc (const PedDevice* dev) { PedDisk* disk; DVHDiskData* dvh_disk_data; PedPartition* volume_part; PedConstraint* constraint_any; disk = _ped_disk_alloc (dev, &dvh_disk_type); if (!disk) goto error; disk->disk_specific = dvh_disk_data = ped_malloc (sizeof (DVHDiskData)); if (!dvh_disk_data) goto error_free_disk; memset (&dvh_disk_data->dev_params, 0, sizeof (struct device_parameters)); dvh_disk_data->swap = 0; dvh_disk_data->root = 0; dvh_disk_data->boot = 0; volume_part = ped_partition_new (disk, PED_PARTITION_EXTENDED, NULL, 0, PTYPE_VOLHDR_DFLTSZ - 1); if (!volume_part) goto error_free_disk_specific; volume_part->num = PNUM_VOLHDR + 1; constraint_any = ped_constraint_any (dev); if (!ped_disk_add_partition (disk, volume_part, constraint_any)) goto error_destroy_constraint_any; ped_constraint_destroy (constraint_any); return disk; error_destroy_constraint_any: ped_constraint_destroy (constraint_any); ped_partition_destroy (volume_part); error_free_disk_specific: free (disk->disk_specific); error_free_disk: free (disk); error: return NULL; }
/* 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 ! */ }
/** * \brief Creates a new nested timer. * * This function creates a "nested" timer that describes the progress * of a subtask. \p parent is the parent timer, and \p nested_frac is * the estimated proportion (between 0 and 1) of the time that will be * spent doing the nested timer's operation. The timer should only be * constructed immediately prior to starting the nested operation. * (It will be inaccurate, otherwise). * Updates to the progress of the subtask are propagated * back through to the parent task's timer. * * \return nested timer */ PedTimer* ped_timer_new_nested (PedTimer* parent, float nest_frac) { NestedContext* context; if (!parent) return NULL; PED_ASSERT (nest_frac >= 0.0f); PED_ASSERT (nest_frac <= 1.0f); context = (NestedContext*) ped_malloc (sizeof (NestedContext)); if (!context) return NULL; context->parent = parent; context->nest_frac = nest_frac; context->start_frac = parent->frac; return ped_timer_new (_nest_handler, context); }
static PedFileSystem *reiserfs_open(PedGeometry *geom) { PedFileSystem *fs; PedGeometry *fs_geom; dal_t *dal; reiserfs_fs_t *fs_info; PED_ASSERT(geom != NULL); if (!(fs_geom = ped_geometry_duplicate(geom))) goto error; if (! (dal = geom_dal_create(fs_geom, DEFAULT_BLOCK_SIZE, O_RDONLY))) goto error_fs_geom_free; /* We are passing NULL as DAL for journal. Therefore we let libreiserfs know, that journal not available and parted will be working fine for reiserfs with relocated journal too. */ if (!(fs = (PedFileSystem *) ped_malloc(sizeof(PedFileSystem)))) goto error_free_dal; if (!(fs_info = reiserfs_fs_open(dal, NULL))) goto error_free_fs; fs->type = reiserfs_type; fs->geom = fs_geom; fs->type_specific = (void *) fs_info; return fs; error_free_fs: free(fs); error_free_dal: geom_dal_free(dal); error_fs_geom_free: ped_geometry_destroy(fs_geom); error: return NULL; }
int fat_info_sector_generate (FatInfoSector** isp, const PedFileSystem* fs) { FatSpecific* fs_info = FAT_SPECIFIC (fs); PED_ASSERT (isp != NULL); *isp = ped_malloc (fs->geom->dev->sector_size); FatInfoSector *is = *isp; fat_table_count_stats (fs_info->fat); memset (is, 0, 512); is->signature_1 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC1); is->signature_2 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC2); is->free_clusters = PED_CPU_TO_LE32 (fs_info->fat->free_cluster_count); is->next_cluster = PED_CPU_TO_LE32 (fs_info->fat->last_alloc); is->signature_3 = PED_CPU_TO_LE16 (FAT32_INFO_MAGIC3); return 1; }
/** * Convenience wrapper for ped_constraint_init(). * * Allocates a new piece of memory and initializes the constraint. * * \return \c NULL on failure. */ PedConstraint* ped_constraint_new ( const PedAlignment* start_align, const PedAlignment* end_align, const PedGeometry* start_range, const PedGeometry* end_range, PedSector min_size, PedSector max_size) { PedConstraint* constraint; constraint = (PedConstraint*) ped_malloc (sizeof (PedConstraint)); if (!constraint) goto error; if (!ped_constraint_init (constraint, start_align, end_align, start_range, end_range, min_size, max_size)) goto error_free_constraint; return constraint; error_free_constraint: free (constraint); error: return NULL; }
static int hfs_extract (PedFileSystem* fs, PedTimer* timer) { HfsPrivateFSData* priv_data = (HfsPrivateFSData*) fs->type_specific; 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; hfs_extract_mdb(HFS_MDB_FILENAME, fs); hfs_extract_file(HFS_CATALOG_FILENAME, priv_data->catalog_file); hfs_extract_file(HFS_EXTENTS_FILENAME, priv_data->extent_file); hfs_extract_bitmap(HFS_BITMAP_FILENAME, fs); free(extract_buffer); extract_buffer = NULL; return 0; /* nothing has been fixed by us ! */ }
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 = HFS_32_TO_CPU(jh->blhdr_size, is_le) / PED_SECTOR_SIZE_DEFAULT; blhdr = (HfsJBlockListHeader*) ped_malloc (blhdr_nbsect * PED_SECTOR_SIZE_DEFAULT); if (!blhdr) return 0; start = HFS_64_TO_CPU(jh->start, is_le) / 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 = HFS_32_TO_CPU(blhdr->checksum, is_le); 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 = HFS_CPU_TO_32(cksum, is_le); for (i=1; i < HFS_16_TO_CPU(blhdr->num_blocks, is_le); ++i) { size = HFS_32_TO_CPU(blhdr->binfo[i].bsize, is_le); sector = HFS_64_TO_CPU(blhdr->binfo[i].bnum, is_le); 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) { 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; 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 = HFS_CPU_TO_64(start * PED_SECTOR_SIZE_DEFAULT, is_le); free (blhdr); return (ped_geometry_sync (fs->geom)); err_replay: free (blhdr); return 0; }
/* 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; }