PyObject *py_ped_geometry_test_equal(PyObject *s, PyObject *args) { int ret = -1; PyObject *in_b = NULL; PedGeometry *out_a = NULL, *out_b = NULL; if (!PyArg_ParseTuple(args, "O!", &_ped_Geometry_Type_obj, &in_b)) { return NULL; } out_a = _ped_Geometry2PedGeometry(s); if (out_a == NULL) { return NULL; } out_b = _ped_Geometry2PedGeometry(in_b); if (out_b == NULL) { return NULL; } ret = ped_geometry_test_equal(out_a, out_b); if (ret) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } }
int hfsplus_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) { HfsPPrivateFSData* priv_data; PedTimer* timer_plus; PedGeometry* embedded_geom; PedSector hgms; /* check preconditions */ PED_ASSERT (fs != NULL); PED_ASSERT (fs->geom != NULL); PED_ASSERT (geom != NULL); PED_ASSERT (fs->geom->dev == geom->dev); #ifdef DEBUG PED_ASSERT ((hgms = hfsplus_get_min_size (fs)) != 0); #else if ((hgms = hfsplus_get_min_size (fs)) == 0) return 0; #endif if (ped_geometry_test_equal(fs->geom, geom)) return 1; priv_data = (HfsPPrivateFSData*) fs->type_specific; if (fs->geom->start != geom->start || geom->length > fs->geom->length || geom->length < hgms) { ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_CANCEL, _("Sorry, HFS+ cannot be resized that way yet.")); return 0; } if (priv_data->wrapper) { PedSector red, hgee; 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; /* There is a wrapper so we must calculate the new geometry of the embedded HFS+ volume */ red = ( (fs->geom->length - geom->length + hfs_sect_block - 1) / hfs_sect_block ) * hfs_sect_block; /* Can't we shrink the hfs+ volume by the desired size ? */ hgee = hfsplus_get_empty_end (fs); if (!hgee) return 0; if (red > priv_data->plus_geom->length - hgee) { /* No, shrink hfs+ by the greatest possible value */ hgee = ((hgee + hfs_sect_block - 1) / hfs_sect_block) * hfs_sect_block; red = priv_data->plus_geom->length - hgee; } embedded_geom = ped_geometry_new (geom->dev, priv_data->plus_geom->start, priv_data->plus_geom->length - red); /* There is a wrapper so the resize process is a two stages process (embedded resizing then wrapper resizing) : we create a sub timer */ ped_timer_reset (timer); ped_timer_set_state_name (timer, _("shrinking embedded HFS+ volume")); ped_timer_update(timer, 0.0); timer_plus = ped_timer_new_nested (timer, 0.98); } else { /* No wrapper : the desired geometry is the desired HFS+ volume geometry */ embedded_geom = geom; timer_plus = timer; } /* Resize the HFS+ volume */ if (!hfsplus_volume_resize (fs, embedded_geom, timer_plus)) { if (timer_plus != timer) ped_timer_destroy_nested (timer_plus); ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Resizing the HFS+ volume has failed.")); return 0; } if (priv_data->wrapper) { ped_geometry_destroy (embedded_geom); ped_timer_destroy_nested (timer_plus); ped_timer_set_state_name(timer, _("shrinking HFS wrapper")); timer_plus = ped_timer_new_nested (timer, 0.02); /* There's a wrapper : second stage = resizing it */ if (!hfsplus_wrapper_update (fs) || !hfs_resize (priv_data->wrapper, geom, timer_plus)) { ped_timer_destroy_nested (timer_plus); ped_exception_throw ( PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, _("Updating the HFS wrapper has failed.")); return 0; } ped_timer_destroy_nested (timer_plus); } ped_timer_update(timer, 1.0); return 1; }
int hfs_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; unsigned int nblock, nfree; unsigned int block, to_free; HfsPrivateFSData* priv_data; HfsMasterDirectoryBlock* mdb; int resize = 1; unsigned int hfs_sect_block; PedSector hgee; /* check preconditions */ PED_ASSERT (fs != NULL); PED_ASSERT (fs->geom != NULL); PED_ASSERT (geom != NULL); #ifdef DEBUG PED_ASSERT ((hgee = hfs_get_empty_end(fs)) != 0); #else if ((hgee = hfs_get_empty_end(fs)) == 0) return 0; #endif PED_ASSERT ((hgee = hfs_get_empty_end(fs)) != 0); if (ped_geometry_test_equal(fs->geom, geom)) return 1; priv_data = (HfsPrivateFSData*) fs->type_specific; mdb = priv_data->mdb; hfs_sect_block = PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT; if (fs->geom->start != geom->start || geom->length > fs->geom->length || geom->length < hgee + 2) { ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_CANCEL, _("Sorry, HFS cannot be resized that way yet.")); return 0; } /* Flush caches */ if (!ped_geometry_sync(fs->geom)) return 0; /* Clear the unmounted bit */ mdb->volume_attributes &= PED_CPU_TO_BE16 (~( 1 << HFS_UNMOUNTED )); if (!ped_geometry_read (fs->geom, buf, 2, 1)) return 0; memcpy (buf, mdb, sizeof (HfsMasterDirectoryBlock)); if ( !ped_geometry_write (fs->geom, buf, 2, 1) || !ped_geometry_sync (fs->geom)) return 0; ped_timer_reset (timer); ped_timer_set_state_name(timer, _("shrinking")); ped_timer_update(timer, 0.0); /* relocate data */ to_free = ( fs->geom->length - geom->length + hfs_sect_block - 1 ) / hfs_sect_block ; block = hfs_find_start_pack (fs, to_free); if (!hfs_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_MDB; } /* Calculate new block number and other MDB field */ nblock = ( geom->length - (PED_BE16_TO_CPU (mdb->start_block) + 2) ) / hfs_sect_block; nfree = PED_BE16_TO_CPU (mdb->free_blocks) - ( PED_BE16_TO_CPU (mdb->total_blocks) - nblock ); /* Check that all block after future end are really free */ for (block = nblock; block < PED_BE16_TO_CPU (mdb->total_blocks); 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 in the end " "of the volume.")); goto write_MDB; } } /* Mark out of volume blocks as used (broken implementations compatibility) */ for ( block = nblock; block < (1 << 16); ++block) SET_BLOC_OCCUPATION(priv_data->alloc_map,block); /* save the allocation map I do not write until start of allocation blocks but only until pre-resize end of bitmap blocks because the specifications do _not_ assert that everything until allocation blocks is boot, mdb and alloc */ ped_geometry_write(fs->geom, priv_data->alloc_map, PED_BE16_TO_CPU (priv_data->mdb->volume_bitmap_block), ( PED_BE16_TO_CPU (priv_data->mdb->total_blocks) + PED_SECTOR_SIZE_DEFAULT * 8 - 1) / (PED_SECTOR_SIZE_DEFAULT * 8)); /* Update geometry */ if (resize) { /* update in fs structure */ if (PED_BE16_TO_CPU (mdb->next_allocation) >= nblock) mdb->next_allocation = PED_CPU_TO_BE16 (0); mdb->total_blocks = PED_CPU_TO_BE16 (nblock); mdb->free_blocks = PED_CPU_TO_BE16 (nfree); /* update parted structure */ fs->geom->length = geom->length; fs->geom->end = fs->geom->start + geom->length - 1; } /* Set the unmounted bit */ mdb->volume_attributes |= PED_CPU_TO_BE16 ( 1 << HFS_UNMOUNTED ); /* Effective write */ write_MDB: ped_timer_set_state_name(timer,_("writing HFS Master Directory Block")); if (!hfs_update_mdb(fs)) { ped_geometry_sync(geom); return 0; } if (!ped_geometry_sync(geom)) return 0; ped_timer_update(timer, 1.0); return (resize); }