/* 1 on succes */ int hfsplus_update_vh (PedFileSystem *fs) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; uint8_t node[PED_SECTOR_SIZE_DEFAULT]; if (!ped_geometry_read (priv_data->plus_geom, node, 2, 1)) return 0; memcpy (node, priv_data->vh, sizeof (HfsPVolumeHeader)); if (!ped_geometry_write (priv_data->plus_geom, node, 2, 1) || !ped_geometry_write (priv_data->plus_geom, node, priv_data->plus_geom->length - 2, 1) || !ped_geometry_sync_fast (priv_data->plus_geom)) return 0; return 1; }
PyObject *py_ped_geometry_sync_fast(PyObject *s, PyObject *args) { int ret = -1; PedGeometry *geom = NULL; geom = _ped_Geometry2PedGeometry(s); if (geom == NULL) { return NULL; } ret = ped_geometry_sync_fast(geom); if (ret == 0) { PyErr_SetString(IOException, "Could not sync"); return NULL; } if (ret) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } }
/* -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_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; }