2
libparted - a library for manipulating disk partitions
3
Copyright (C) 2004-2005, 2007, 2009-2012 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);
60
PED_ASSERT (*ptr_to_fblock <= *ptr_fblock);
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
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);
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);
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);
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);
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);
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 */