2 libparted - a library for manipulating disk partitions
3 Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <parted/parted.h>
24 #include <parted/endian.h>
25 #include <parted/debug.h>
30 # define _(String) dgettext (PACKAGE, String)
32 # define _(String) (String)
33 #endif /* ENABLE_NLS */
36 #include "file_plus.h"
37 #include "advfs_plus.h"
41 #include "reloc_plus.h"
43 /* This function moves data of size blocks starting at block *ptr_fblock
44 to block *ptr_to_fblock */
45 /* return new start or -1 on failure */
46 /* -1 is ok because there can only be 2^32-1 blocks, so the max possible
47 last one is 2^32-2 (and anyway it contains Alternate VH), so
48 -1 (== 2^32-1[2^32]) never represent a valid block */
50 hfsplus_effect_move_extent (PedFileSystem *fs, unsigned int *ptr_fblock,
51 unsigned int *ptr_to_fblock, unsigned int size)
53 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
55 unsigned int i, ok = 0;
56 unsigned int next_to_fblock;
57 unsigned int start, stop;
59 PED_ASSERT (hfsp_block != NULL, return -1);
60 PED_ASSERT (*ptr_to_fblock <= *ptr_fblock, return -1);
65 Try to fit the extent AT or _BEFORE_ the wanted place,
66 or then in the gap between dest and source.
67 If failed try to fit the extent after source, for 2 pass relocation
68 The extent is always copied in a non overlapping way
72 /* 1 pass relocation AT or BEFORE *ptr_to_fblock */
73 if (*ptr_to_fblock != *ptr_fblock) {
74 start = stop = *ptr_fblock < *ptr_to_fblock+size ?
75 *ptr_fblock : *ptr_to_fblock+size;
76 while (start && stop-start != size) {
78 if (TST_BLOC_OCCUPATION(priv_data->alloc_map,start))
81 ok = (stop-start == size);
85 /* 1 pass relocation in the gap merged with 2 pass reloc after source */
86 if (!ok && *ptr_to_fblock != *ptr_fblock) {
87 start = stop = *ptr_to_fblock+1;
88 while (stop < PED_BE32_TO_CPU(priv_data->vh->total_blocks)
89 && stop-start != size) {
90 if (TST_BLOC_OCCUPATION(priv_data->alloc_map,stop))
94 ok = (stop-start == size);
97 /* new non overlapping room has been found ? */
100 PedSector abs_sector;
101 unsigned int ai, j, block;
102 unsigned int block_sz = (PED_BE32_TO_CPU (
103 priv_data->vh->block_size)
104 / PED_SECTOR_SIZE_DEFAULT);
106 if (stop > *ptr_to_fblock && stop <= *ptr_fblock)
108 next_to_fblock = stop;
110 /* Before or after the gap */
111 next_to_fblock = *ptr_to_fblock;
114 for (i = 0; i < size; /*i++*/) {
115 j = size - i; j = (j < hfsp_block_count) ?
116 j : hfsp_block_count ;
118 abs_sector = (PedSector) (*ptr_fblock + i) * block_sz;
119 if (!ped_geometry_read (priv_data->plus_geom,
120 hfsp_block, abs_sector,
124 abs_sector = (PedSector) (start + i) * block_sz;
125 if (!ped_geometry_write (priv_data->plus_geom,
126 hfsp_block, abs_sector,
130 for (ai = i+j; i < ai; i++) {
131 /* free source block */
132 block = *ptr_fblock + i;
133 CLR_BLOC_OCCUPATION(priv_data->alloc_map,block);
134 SET_BLOC_OCCUPATION(priv_data->dirty_alloc_map,
135 block/(PED_SECTOR_SIZE_DEFAULT*8));
139 SET_BLOC_OCCUPATION(priv_data->alloc_map,block);
140 SET_BLOC_OCCUPATION(priv_data->dirty_alloc_map,
141 block/(PED_SECTOR_SIZE_DEFAULT*8));
144 if (!ped_geometry_sync_fast (priv_data->plus_geom))
148 *ptr_to_fblock = next_to_fblock;
150 if (*ptr_fblock != *ptr_to_fblock)
151 /* not enough room */
152 ped_exception_throw (PED_EXCEPTION_WARNING,
153 PED_EXCEPTION_IGNORE,
154 _("An extent has not been relocated."));
156 *ptr_fblock = *ptr_to_fblock = start + size;
162 /* Returns 0 on error */
165 hfsplus_update_vh (PedFileSystem *fs)
167 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
169 uint8_t node[PED_SECTOR_SIZE_DEFAULT];
171 if (!ped_geometry_read (priv_data->plus_geom, node, 2, 1))
173 memcpy (node, priv_data->vh, sizeof (HfsPVolumeHeader));
174 if (!ped_geometry_write (priv_data->plus_geom, node, 2, 1)
175 || !ped_geometry_write (priv_data->plus_geom, node,
176 priv_data->plus_geom->length - 2, 1)
177 || !ped_geometry_sync_fast (priv_data->plus_geom))
183 hfsplus_do_move (PedFileSystem* fs, unsigned int *ptr_src,
184 unsigned int *ptr_dest, HfsCPrivateCache* cache,
185 HfsCPrivateExtent* ref)
187 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
189 HfsPPrivateFile* file;
190 HfsPExtDescriptor* extent;
191 HfsCPrivateExtent* move;
194 new_start = hfsplus_effect_move_extent (fs, ptr_src, ptr_dest,
197 if (new_start == -1) return -1;
199 if (ref->ext_start != (unsigned) new_start) {
200 switch (ref->where) {
201 /************ VH ************/
203 priv_data->catalog_file
204 ->first[ref->ref_index].start_block =
205 PED_CPU_TO_BE32(new_start);
208 priv_data->extents_file
209 ->first[ref->ref_index].start_block =
210 PED_CPU_TO_BE32(new_start);
213 priv_data->attributes_file
214 ->first[ref->ref_index].start_block =
215 PED_CPU_TO_BE32(new_start);
218 priv_data->allocation_file
219 ->first[ref->ref_index].start_block =
220 PED_CPU_TO_BE32(new_start);
223 /* No startup file opened */
225 extent = ( HfsPExtDescriptor* )
226 ( (uint8_t*)priv_data->vh + ref->ref_offset );
227 extent[ref->ref_index].start_block =
228 PED_CPU_TO_BE32(new_start);
229 if (!hfsplus_update_vh(fs))
233 /************** BTREE *************/
234 case CR_BTREE_CAT_JIB :
235 if (!hfsj_update_jib(fs, new_start))
239 case CR_BTREE_CAT_JL :
240 if (!hfsj_update_jl(fs, new_start))
246 file = priv_data->catalog_file;
250 file = priv_data->attributes_file;
253 case CR_BTREE_EXT_ATTR :
254 if (priv_data->attributes_file
255 ->cache[ref->ref_index].start_block
256 == PED_CPU_TO_BE32(ref->ext_start))
257 priv_data->attributes_file
258 ->cache[ref->ref_index].start_block =
259 PED_CPU_TO_BE32(new_start);
261 case CR_BTREE_EXT_CAT :
262 if (priv_data->catalog_file
263 ->cache[ref->ref_index].start_block
264 == PED_CPU_TO_BE32(ref->ext_start))
265 priv_data->catalog_file
266 ->cache[ref->ref_index].start_block =
267 PED_CPU_TO_BE32(new_start);
269 case CR_BTREE_EXT_ALLOC :
270 if (priv_data->allocation_file
271 ->cache[ref->ref_index].start_block
272 == PED_CPU_TO_BE32(ref->ext_start))
273 priv_data->allocation_file
274 ->cache[ref->ref_index].start_block =
275 PED_CPU_TO_BE32(new_start);
277 case CR_BTREE_EXT_START :
278 /* No startup file opened */
280 case CR_BTREE_EXT_0 :
281 file = priv_data->extents_file;
284 PED_ASSERT(PED_SECTOR_SIZE_DEFAULT * ref->sect_by_block
285 > ref->ref_offset, return -1 );
286 if (!hfsplus_file_read(file, hfsp_block,
287 (PedSector)ref->ref_block * ref->sect_by_block,
290 extent = ( HfsPExtDescriptor* )
291 ( hfsp_block + ref->ref_offset );
292 extent[ref->ref_index].start_block =
293 PED_CPU_TO_BE32(new_start);
294 if (!hfsplus_file_write(file, hfsp_block,
295 (PedSector)ref->ref_block * ref->sect_by_block,
297 || !ped_geometry_sync_fast (priv_data->plus_geom))
301 /********** BUG *********/
303 ped_exception_throw (
305 PED_EXCEPTION_CANCEL,
306 _("A reference to an extent comes from a place "
307 "it should not. You should check the file "
313 move = hfsc_cache_move_extent(cache, ref->ext_start, new_start);
314 if (!move) return -1;
315 PED_ASSERT(move == ref, return -1);
321 /* save any dirty sector of the allocation bitmap file */
323 hfsplus_save_allocation(PedFileSystem *fs)
325 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
327 unsigned int map_sectors, i, j;
330 map_sectors = ( PED_BE32_TO_CPU (priv_data->vh->total_blocks)
331 + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8);
333 for (i = 0; i < map_sectors;) {
335 (TST_BLOC_OCCUPATION(priv_data->dirty_alloc_map,j));
337 CLR_BLOC_OCCUPATION(priv_data->dirty_alloc_map,j);
339 ret = hfsplus_file_write(priv_data->allocation_file,
340 priv_data->alloc_map + i * PED_SECTOR_SIZE_DEFAULT,
350 /* This function moves an extent starting at block fblock
351 to block to_fblock if there's enough room */
352 /* Return 1 if everything was fine */
353 /* Return -1 if an error occurred */
354 /* Return 0 if no extent was found */
356 hfsplus_move_extent_starting_at (PedFileSystem *fs, unsigned int *ptr_fblock,
357 unsigned int *ptr_to_fblock,
358 HfsCPrivateCache* cache)
360 HfsCPrivateExtent* ref;
361 unsigned int old_start, new_start;
363 ref = hfsc_cache_search_extent(cache, *ptr_fblock);
366 old_start = *ptr_fblock;
367 new_start = hfsplus_do_move(fs, ptr_fblock, ptr_to_fblock, cache, ref);
368 if (new_start == (unsigned)-1) return -1;
369 if (new_start > old_start) {
370 new_start = hfsplus_do_move(fs, &new_start, ptr_to_fblock,
372 if (new_start == (unsigned)-1 || new_start > old_start)
376 hfsplus_save_allocation(fs);
381 hfsplus_cache_from_vh(HfsCPrivateCache* cache, PedFileSystem* fs,
384 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
386 HfsPExtDescriptor* extent;
389 extent = priv_data->vh->allocation_file.extents;
390 for (j = 0; j < HFSP_EXT_NB; ++j) {
391 if (!extent[j].block_count) break;
392 if (!hfsc_cache_add_extent(
394 PED_BE32_TO_CPU(extent[j].start_block),
395 PED_BE32_TO_CPU(extent[j].block_count),
396 0, /* unused for vh */
397 ((uint8_t*)extent) - ((uint8_t*)priv_data->vh),
398 1, /* load / save 1 sector */
405 extent = priv_data->vh->extents_file.extents;
406 for (j = 0; j < HFSP_EXT_NB; ++j) {
407 if (!extent[j].block_count) break;
408 if (!hfsc_cache_add_extent(
410 PED_BE32_TO_CPU(extent[j].start_block),
411 PED_BE32_TO_CPU(extent[j].block_count),
412 0, /* unused for vh */
413 ((uint8_t*)extent) - ((uint8_t*)priv_data->vh),
414 1, /* load / save 1 sector */
421 extent = priv_data->vh->catalog_file.extents;
422 for (j = 0; j < HFSP_EXT_NB; ++j) {
423 if (!extent[j].block_count) break;
424 if (!hfsc_cache_add_extent(
426 PED_BE32_TO_CPU(extent[j].start_block),
427 PED_BE32_TO_CPU(extent[j].block_count),
428 0, /* unused for vh */
429 ((uint8_t*)extent) - ((uint8_t*)priv_data->vh),
430 1, /* load / save 1 sector */
437 extent = priv_data->vh->attributes_file.extents;
438 for (j = 0; j < HFSP_EXT_NB; ++j) {
439 if (!extent[j].block_count) break;
440 if (!hfsc_cache_add_extent(
442 PED_BE32_TO_CPU(extent[j].start_block),
443 PED_BE32_TO_CPU(extent[j].block_count),
444 0, /* unused for vh */
445 ((uint8_t*)extent) - ((uint8_t*)priv_data->vh),
446 1, /* load / save 1 sector */
453 extent = priv_data->vh->startup_file.extents;
454 for (j = 0; j < HFSP_EXT_NB; ++j) {
455 if (!extent[j].block_count) break;
456 if (!hfsc_cache_add_extent(
458 PED_BE32_TO_CPU(extent[j].start_block),
459 PED_BE32_TO_CPU(extent[j].block_count),
460 0, /* unused for vh */
461 ((uint8_t*)extent) - ((uint8_t*)priv_data->vh),
462 1, /* load / save 1 sector */
473 hfsplus_cache_from_catalog(HfsCPrivateCache* cache, PedFileSystem* fs,
476 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
478 uint8_t node_1[PED_SECTOR_SIZE_DEFAULT];
480 HfsPHeaderRecord* header;
481 HfsPCatalogKey* catalog_key;
482 HfsPCatalog* catalog_data;
483 HfsPExtDescriptor* extent;
484 unsigned int leaf_node, record_number;
485 unsigned int i, j, size, bsize;
486 uint32_t jib = priv_data->jib_start_block,
487 jl = priv_data->jl_start_block;
489 if (!priv_data->catalog_file->sect_nb) {
490 ped_exception_throw (
491 PED_EXCEPTION_INFORMATION,
493 _("This HFS+ volume has no catalog file. "
494 "This is very unusual!"));
498 /* Search the extent starting at *ptr_block in the catalog file */
499 if (!hfsplus_file_read_sector (priv_data->catalog_file, node_1, 0))
501 header = (HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC);
502 leaf_node = PED_BE32_TO_CPU (header->first_leaf_node);
503 bsize = PED_BE16_TO_CPU (header->node_size);
504 size = bsize / PED_SECTOR_SIZE_DEFAULT;
505 PED_ASSERT(size < 256, return 0);
507 node = (uint8_t*) ped_malloc(bsize);
509 HfsPNodeDescriptor *desc = (HfsPNodeDescriptor*) node;
511 for (; leaf_node; leaf_node = PED_BE32_TO_CPU (desc->next)) {
512 if (!hfsplus_file_read (priv_data->catalog_file, node,
513 (PedSector) leaf_node * size, size)) {
517 record_number = PED_BE16_TO_CPU (desc->rec_nb);
518 for (i = 1; i <= record_number; i++) {
522 catalog_key = (HfsPCatalogKey*)
523 ( node + PED_BE16_TO_CPU (*((uint16_t *)
524 (node+(bsize - 2*i)))) );
525 skip = ( 2 + PED_BE16_TO_CPU (catalog_key->key_length)
527 catalog_data = (HfsPCatalog*)
528 (((uint8_t*)catalog_key) + skip);
529 /* check for obvious error in FS */
530 if (((uint8_t*)catalog_key - node < HFS_FIRST_REC)
531 || ((uint8_t*)catalog_data - node
533 - 2 * (signed)(record_number+1))) {
534 ped_exception_throw (
536 PED_EXCEPTION_CANCEL,
537 _("The file system contains errors."));
542 if (PED_BE16_TO_CPU(catalog_data->type)!=HFS_CAT_FILE)
545 extent = catalog_data->sel.file.data_fork.extents;
546 for (j = 0; j < HFSP_EXT_NB; ++j) {
547 if (!extent[j].block_count) break;
548 where = CR_BTREE_CAT;
549 if ( PED_BE32_TO_CPU(extent[j].start_block)
552 where = CR_BTREE_CAT_JIB;
554 if ( PED_BE32_TO_CPU(extent[j].start_block)
557 where = CR_BTREE_CAT_JL;
559 if (!hfsc_cache_add_extent(
561 PED_BE32_TO_CPU(extent[j].start_block),
562 PED_BE32_TO_CPU(extent[j].block_count),
564 (uint8_t*)extent - node,
574 extent = catalog_data->sel.file.res_fork.extents;
575 for (j = 0; j < HFSP_EXT_NB; ++j) {
576 if (!extent[j].block_count) break;
577 if (!hfsc_cache_add_extent(
579 PED_BE32_TO_CPU(extent[j].start_block),
580 PED_BE32_TO_CPU(extent[j].block_count),
582 (uint8_t*)extent - node,
599 hfsplus_cache_from_extent(HfsCPrivateCache* cache, PedFileSystem* fs,
602 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
604 uint8_t node_1[PED_SECTOR_SIZE_DEFAULT];
606 HfsPHeaderRecord* header;
607 HfsPExtentKey* extent_key;
608 HfsPExtDescriptor* extent;
609 unsigned int leaf_node, record_number;
610 unsigned int i, j, size, bsize;
612 if (!priv_data->extents_file->sect_nb) {
613 ped_exception_throw (
614 PED_EXCEPTION_INFORMATION,
616 _("This HFS+ volume has no extents overflow "
617 "file. This is quite unusual!"));
621 if (!hfsplus_file_read_sector (priv_data->extents_file, node_1, 0))
623 header = ((HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC));
624 leaf_node = PED_BE32_TO_CPU (header->first_leaf_node);
625 bsize = PED_BE16_TO_CPU (header->node_size);
626 size = bsize / PED_SECTOR_SIZE_DEFAULT;
627 PED_ASSERT(size < 256, return 0);
629 node = (uint8_t*) ped_malloc (bsize);
630 if (!node) return -1;
631 HfsPNodeDescriptor *desc = (HfsPNodeDescriptor*) node;
633 for (; leaf_node; leaf_node = PED_BE32_TO_CPU (desc->next)) {
634 if (!hfsplus_file_read (priv_data->extents_file, node,
635 (PedSector) leaf_node * size, size)) {
639 record_number = PED_BE16_TO_CPU (desc->rec_nb);
640 for (i = 1; i <= record_number; i++) {
642 extent_key = (HfsPExtentKey*)
643 (node + PED_BE16_TO_CPU(*((uint16_t *)
644 (node+(bsize - 2*i)))));
645 extent = (HfsPExtDescriptor*)
646 (((uint8_t*)extent_key) + sizeof (HfsPExtentKey));
647 /* check for obvious error in FS */
648 if (((uint8_t*)extent_key - node < HFS_FIRST_REC)
649 || ((uint8_t*)extent - node
651 - 2 * (signed)(record_number+1))) {
652 ped_exception_throw (
654 PED_EXCEPTION_CANCEL,
655 _("The file system contains errors."));
660 switch (extent_key->file_ID) {
661 case PED_CPU_TO_BE32 (HFS_XTENT_ID) :
662 if (ped_exception_throw (
663 PED_EXCEPTION_WARNING,
664 PED_EXCEPTION_IGNORE_CANCEL,
665 _("The extents overflow file should not"
666 " contain its own extents! You should "
667 "check the file system."))
668 != PED_EXCEPTION_IGNORE)
670 where = CR_BTREE_EXT_EXT;
672 case PED_CPU_TO_BE32 (HFS_CATALOG_ID) :
673 where = CR_BTREE_EXT_CAT;
675 case PED_CPU_TO_BE32 (HFSP_ALLOC_ID) :
676 where = CR_BTREE_EXT_ALLOC;
678 case PED_CPU_TO_BE32 (HFSP_STARTUP_ID) :
679 where = CR_BTREE_EXT_START;
681 case PED_CPU_TO_BE32 (HFSP_ATTRIB_ID) :
682 where = CR_BTREE_EXT_ATTR;
685 where = CR_BTREE_EXT_0;
689 for (j = 0; j < HFSP_EXT_NB; ++j) {
690 if (!extent[j].block_count) break;
691 if (!hfsc_cache_add_extent(
693 PED_BE32_TO_CPU(extent[j].start_block),
694 PED_BE32_TO_CPU(extent[j].block_count),
696 (uint8_t*)extent - node,
713 hfsplus_cache_from_attributes(HfsCPrivateCache* cache, PedFileSystem* fs,
716 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
718 uint8_t node_1[PED_SECTOR_SIZE_DEFAULT];
720 HfsPHeaderRecord* header;
721 HfsPPrivateGenericKey* generic_key;
722 HfsPForkDataAttr* fork_ext_data;
723 HfsPExtDescriptor* extent;
724 unsigned int leaf_node, record_number;
725 unsigned int i, j, size, bsize;
727 /* attributes file is facultative */
728 if (!priv_data->attributes_file->sect_nb)
731 /* Search the extent starting at *ptr_block in the catalog file */
732 if (!hfsplus_file_read_sector (priv_data->attributes_file, node_1, 0))
734 header = ((HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC));
735 leaf_node = PED_BE32_TO_CPU (header->first_leaf_node);
736 bsize = PED_BE16_TO_CPU (header->node_size);
737 size = bsize / PED_SECTOR_SIZE_DEFAULT;
738 PED_ASSERT(size < 256, return 0);
740 node = (uint8_t*) ped_malloc(bsize);
742 HfsPNodeDescriptor *desc = (HfsPNodeDescriptor*) node;
744 for (; leaf_node; leaf_node = PED_BE32_TO_CPU (desc->next)) {
745 if (!hfsplus_file_read (priv_data->attributes_file, node,
746 (PedSector) leaf_node * size, size)) {
750 record_number = PED_BE16_TO_CPU (desc->rec_nb);
751 for (i = 1; i <= record_number; i++) {
753 generic_key = (HfsPPrivateGenericKey*)
754 (node + PED_BE16_TO_CPU(*((uint16_t *)
755 (node+(bsize - 2*i)))));
756 skip = ( 2 + PED_BE16_TO_CPU (generic_key->key_length)
758 fork_ext_data = (HfsPForkDataAttr*)
759 (((uint8_t*)generic_key) + skip);
760 /* check for obvious error in FS */
761 if (((uint8_t*)generic_key - node < HFS_FIRST_REC)
762 || ((uint8_t*)fork_ext_data - node
764 - 2 * (signed)(record_number+1))) {
765 ped_exception_throw (
767 PED_EXCEPTION_CANCEL,
768 _("The file system contains errors."));
773 if (fork_ext_data->record_type
774 == PED_CPU_TO_BE32 ( HFSP_ATTR_FORK ) ) {
775 extent = fork_ext_data->fork_res.fork.extents;
776 for (j = 0; j < HFSP_EXT_NB; ++j) {
777 if (!extent[j].block_count) break;
778 if (!hfsc_cache_add_extent(
781 extent[j].start_block ),
783 extent[j].block_count ),
785 (uint8_t*)extent-node,
794 } else if (fork_ext_data->record_type
795 == PED_CPU_TO_BE32 ( HFSP_ATTR_EXTENTS ) ) {
796 extent = fork_ext_data->fork_res.extents;
797 for (j = 0; j < HFSP_EXT_NB; ++j) {
798 if (!extent[j].block_count) break;
799 if (!hfsc_cache_add_extent(
802 extent[j].start_block ),
804 extent[j].block_count ),
806 (uint8_t*)extent-node,
823 static HfsCPrivateCache*
824 hfsplus_cache_extents(PedFileSystem* fs, PedTimer* timer)
826 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
828 HfsCPrivateCache* ret;
829 unsigned int file_number, block_number;
831 file_number = PED_BE32_TO_CPU(priv_data->vh->file_count);
832 block_number = PED_BE32_TO_CPU(priv_data->vh->total_blocks);
833 ret = hfsc_new_cache(block_number, file_number);
834 if (!ret) return NULL;
836 if (!hfsplus_cache_from_vh(ret, fs, timer) ||
837 !hfsplus_cache_from_catalog(ret, fs, timer) ||
838 !hfsplus_cache_from_extent(ret, fs, timer) ||
839 !hfsplus_cache_from_attributes(ret, fs, timer)) {
842 PED_EXCEPTION_CANCEL,
843 _("Could not cache the file system in memory."));
844 hfsc_delete_cache(ret);
851 /* This function moves file's data to compact used and free space,
852 starting at fblock block */
853 /* return 0 on error */
855 hfsplus_pack_free_space_from_block (PedFileSystem *fs, unsigned int fblock,
856 PedTimer* timer, unsigned int to_free)
858 PedSector bytes_buff;
859 HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*)
861 HfsPVolumeHeader* vh = priv_data->vh;
862 HfsCPrivateCache* cache;
863 unsigned int to_fblock = fblock;
864 unsigned int start = fblock;
865 unsigned int divisor = PED_BE32_TO_CPU (vh->total_blocks)
866 + 1 - start - to_free;
869 PED_ASSERT (!hfsp_block, return 0);
871 cache = hfsplus_cache_extents (fs, timer);
875 /* Calculate the size of the copy buffer :
876 * Takes BLOCK_MAX_BUFF HFS blocks, but if > BYTES_MAX_BUFF
877 * takes the maximum number of HFS blocks so that the buffer
878 * will remain smaller than or equal to BYTES_MAX_BUFF, with
879 * a minimum of 1 HFS block */
880 bytes_buff = PED_BE32_TO_CPU (priv_data->vh->block_size)
881 * (PedSector) BLOCK_MAX_BUFF;
882 if (bytes_buff > BYTES_MAX_BUFF) {
883 hfsp_block_count = BYTES_MAX_BUFF
884 / PED_BE32_TO_CPU (priv_data->vh->block_size);
885 if (!hfsp_block_count)
886 hfsp_block_count = 1;
887 bytes_buff = (PedSector) hfsp_block_count
888 * PED_BE32_TO_CPU (priv_data->vh->block_size);
890 hfsp_block_count = BLOCK_MAX_BUFF;
892 /* If the cache code requests more space, give it to him */
893 if (bytes_buff < hfsc_cache_needed_buffer (cache))
894 bytes_buff = hfsc_cache_needed_buffer (cache);
896 hfsp_block = (uint8_t*) ped_malloc (bytes_buff);
900 if (!hfsplus_read_bad_blocks (fs)) {
901 ped_exception_throw (
903 PED_EXCEPTION_CANCEL,
904 _("Bad blocks list could not be loaded."));
908 while ( fblock < ( priv_data->plus_geom->length - 2 )
909 / ( PED_BE32_TO_CPU (vh->block_size)
910 / PED_SECTOR_SIZE_DEFAULT ) ) {
911 if (TST_BLOC_OCCUPATION (priv_data->alloc_map, fblock)
912 && (!hfsplus_is_bad_block (fs, fblock))) {
913 if (!(ret = hfsplus_move_extent_starting_at (fs,
914 &fblock, &to_fblock, cache)))
915 to_fblock = ++fblock;
916 else if (ret == -1) {
917 ped_exception_throw (
919 PED_EXCEPTION_CANCEL,
920 _("An error occurred during extent "
928 ped_timer_update(timer, (float)(to_fblock - start) / divisor);
931 free (hfsp_block); hfsp_block = NULL; hfsp_block_count = 0;
932 hfsc_delete_cache (cache);
936 free (hfsp_block); hfsp_block = NULL; hfsp_block_count = 0;
938 hfsc_delete_cache (cache);
942 #endif /* !DISCOVER_ONLY */