diff options
author | Jim Meyering <meyering@redhat.com> | 2011-05-16 14:21:44 +0200 |
---|---|---|
committer | Jim Meyering <meyering@redhat.com> | 2011-05-27 17:07:45 +0200 |
commit | 71cc20bc9a6dbd31ebaa962c41be76fddb80d045 (patch) | |
tree | 22a50b1413773bd56b1a838a48b05b91ba9eaf2f | |
parent | 4ac1b368a5f5e77aac5f18d38871326caf9c1f13 (diff) | |
download | parted-71cc20bc9a6dbd31ebaa962c41be76fddb80d045.tar.gz |
hfs: remove all-but-probe FS-related code
-rw-r--r-- | libparted/fs/hfs/Makefile.am | 11 | ||||
-rw-r--r-- | libparted/fs/hfs/advfs.c | 328 | ||||
-rw-r--r-- | libparted/fs/hfs/advfs.h | 48 | ||||
-rw-r--r-- | libparted/fs/hfs/advfs_plus.c | 382 | ||||
-rw-r--r-- | libparted/fs/hfs/advfs_plus.h | 51 | ||||
-rw-r--r-- | libparted/fs/hfs/cache.c | 238 | ||||
-rw-r--r-- | libparted/fs/hfs/cache.h | 117 | ||||
-rw-r--r-- | libparted/fs/hfs/file.c | 228 | ||||
-rw-r--r-- | libparted/fs/hfs/file.h | 41 | ||||
-rw-r--r-- | libparted/fs/hfs/file_plus.c | 273 | ||||
-rw-r--r-- | libparted/fs/hfs/file_plus.h | 60 | ||||
-rw-r--r-- | libparted/fs/hfs/hfs.c | 1173 | ||||
-rw-r--r-- | libparted/fs/hfs/journal.c | 389 | ||||
-rw-r--r-- | libparted/fs/hfs/journal.h | 44 | ||||
-rw-r--r-- | libparted/fs/hfs/reloc.c | 669 | ||||
-rw-r--r-- | libparted/fs/hfs/reloc.h | 35 | ||||
-rw-r--r-- | libparted/fs/hfs/reloc_plus.c | 942 | ||||
-rw-r--r-- | libparted/fs/hfs/reloc_plus.h | 36 |
18 files changed, 2 insertions, 5063 deletions
diff --git a/libparted/fs/hfs/Makefile.am b/libparted/fs/hfs/Makefile.am index 053bce1..f85493c 100644 --- a/libparted/fs/hfs/Makefile.am +++ b/libparted/fs/hfs/Makefile.am @@ -1,16 +1,9 @@ +AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS) partedincludedir = -I$(top_srcdir)/include noinst_LTLIBRARIES = libhfs.la libhfs_la_SOURCES = hfs.c hfs.h \ - probe.c probe.h \ - cache.c cache.h \ - advfs.c advfs.h \ - file.c file.h \ - reloc.c reloc.h \ - advfs_plus.c advfs_plus.h \ - file_plus.c file_plus.h \ - reloc_plus.c reloc_plus.h \ - journal.c journal.h + probe.c probe.h INCLUDES = $(partedincludedir) $(INTLINCS) diff --git a/libparted/fs/hfs/advfs.c b/libparted/fs/hfs/advfs.c deleted file mode 100644 index a8adfb3..0000000 --- a/libparted/fs/hfs/advfs.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef DISCOVER_ONLY - -#include <config.h> - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> -#include <stdint.h> - -#if ENABLE_NLS -# include <libintl.h> -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "file.h" - -#include "advfs.h" - -/* - if a < b, 0 if a == b, + if a > b */ -/* Comparaison is done in the following order : */ -/* CNID, then fork type, then start block */ -/* Note that HFS implementation in linux has a bug */ -/* in this function */ -static int -hfs_extent_key_cmp(HfsPrivateGenericKey* a, HfsPrivateGenericKey* b) -{ - HfsExtentKey* key1 = (HfsExtentKey*) a; - HfsExtentKey* key2 = (HfsExtentKey*) b; - - /* do NOT use a substraction, because */ - /* 0xFFFFFFFF - 1 = 0xFFFFFFFE so this */ - /* would return -2, despite the fact */ - /* 0xFFFFFFFF > 1 !!! (this is the 2.4 bug) */ - if (key1->file_ID != key2->file_ID) - return PED_BE32_TO_CPU(key1->file_ID) < - PED_BE32_TO_CPU(key2->file_ID) ? - -1 : +1; - - if (key1->type != key2->type) - return (int)(key1->type - key2->type); - - if (key1->start == key2->start) - return 0; - /* the whole thing wont work with 16 bits ints */ - /* anyway */ - return (int)( PED_BE16_TO_CPU(key1->start) - - PED_BE16_TO_CPU(key2->start) ); -} - -/* do a B-Tree lookup */ -/* read the first record immediatly inferior or egal to the given key */ -/* return 0 on error */ -/* record_out _must_ be large enough to receive record_size bytes */ -/* WARNING : the compare function called only handle Extents BTree */ -/* so modify this function if you want to do lookup in */ -/* other BTrees has well */ -int -hfs_btree_search (HfsPrivateFile* b_tree_file, HfsPrivateGenericKey* key, - void *record_out, unsigned int record_size, - HfsCPrivateLeafRec* record_ref) -{ - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsHeaderRecord* header; - HfsNodeDescriptor* desc = (HfsNodeDescriptor*) node; - HfsPrivateGenericKey* record_key = NULL; - unsigned int node_number, record_number; - int i; - - /* Read the header node */ - if (!hfs_file_read_sector(b_tree_file, node, 0)) - return 0; - header = ((HfsHeaderRecord*) (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(PED_SECTOR_SIZE_DEFAULT-2)))))); - - /* Get the node number of the root */ - node_number = PED_BE32_TO_CPU(header->root_node); - if (!node_number) - return 0; - - /* Read the root node */ - if (!hfs_file_read_sector(b_tree_file, node, node_number)) - return 0; - - /* Follow the white rabbit */ - while (1) { - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = record_number; i; i--) { - record_key = (HfsPrivateGenericKey*) - (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(PED_SECTOR_SIZE_DEFAULT - 2*i))))); - /* check for obvious error in FS */ - if (((uint8_t*)record_key - node < HFS_FIRST_REC) - || ((uint8_t*)record_key - node - >= PED_SECTOR_SIZE_DEFAULT - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - return 0; - } - if (hfs_extent_key_cmp(record_key, key) <= 0) - break; - } - if (!i) return 0; - if (desc->type == HFS_IDX_NODE) { - unsigned int skip; - - skip = (1 + record_key->key_length + 1) & ~1; - node_number = PED_BE32_TO_CPU (*((uint32_t *) - (((uint8_t *) record_key) + skip))); - if (!hfs_file_read_sector(b_tree_file, node, - node_number)) - return 0; - } else - break; - } - - /* copy the result if needed */ - if (record_size) - memcpy (record_out, record_key, record_size); - - /* send record reference if needed */ - if (record_ref) { - record_ref->node_size = 1; /* in sectors */ - record_ref->node_number = node_number; - record_ref->record_pos = (uint8_t*)record_key - node; - record_ref->record_number = i; - } - - /* success */ - return 1; -} - -/* free the bad blocks linked list */ -void -hfs_free_bad_blocks_list(HfsPrivateLinkExtent* first) -{ - HfsPrivateLinkExtent* next; - - while (first) { - next = first->next; - free (first); - first = next; - } -} - -/* This function reads bad blocks extents in the extents file - and store it in f.s. specific data of fs */ -int -hfs_read_bad_blocks (const PedFileSystem *fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - - if (priv_data->bad_blocks_loaded) - return 1; - - { - uint8_t record[sizeof (HfsExtentKey) - + sizeof (HfsExtDataRec)]; - HfsExtentKey search; - HfsExtentKey* ret_key = (HfsExtentKey*) record; - HfsExtDescriptor* ret_cache = (HfsExtDescriptor*) - (record + sizeof (HfsExtentKey)); - unsigned int block, last_start, first_pass = 1; - - search.key_length = sizeof (HfsExtentKey) - 1; - search.type = HFS_DATA_FORK; - search.file_ID = PED_CPU_TO_BE32 (HFS_BAD_BLOCK_ID); - - last_start = -1; block = 0; - while (1) { - int i; - - search.start = PED_CPU_TO_BE16 (block); - if (!hfs_btree_search (priv_data->extent_file, - (HfsPrivateGenericKey*) &search, - record, sizeof (record), NULL) - || ret_key->file_ID != search.file_ID - || ret_key->type != search.type) { - if (first_pass) - break; - else - goto errbb; - } - if (PED_BE16_TO_CPU (ret_key->start) == last_start) - break; - - last_start = PED_BE16_TO_CPU (ret_key->start); - for (i = 0; i < HFS_EXT_NB; i++) { - if (ret_cache[i].block_count) { - HfsPrivateLinkExtent* new_xt = - (HfsPrivateLinkExtent*) ped_malloc ( - sizeof (HfsPrivateLinkExtent)); - if (!new_xt) - goto errbb; - new_xt->next = priv_data->bad_blocks_xtent_list; - memcpy(&(new_xt->extent), ret_cache+i, - sizeof (HfsExtDescriptor)); - priv_data->bad_blocks_xtent_list = new_xt; - priv_data->bad_blocks_xtent_nb++; - block += PED_BE16_TO_CPU ( - ret_cache[i].block_count); - } - } - first_pass = 0; - } - - priv_data->bad_blocks_loaded = 1; - return 1;} - -errbb: hfs_free_bad_blocks_list(priv_data->bad_blocks_xtent_list); - priv_data->bad_blocks_xtent_list=NULL; - priv_data->bad_blocks_xtent_nb=0; - return 0; -} - -/* This function check if fblock is a bad block */ -int -hfs_is_bad_block (const PedFileSystem *fs, unsigned int fblock) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsPrivateLinkExtent* walk; - - for (walk = priv_data->bad_blocks_xtent_list; walk; walk = walk->next) { - /* Won't compile without the strange cast ! gcc bug ? */ - /* or maybe C subtilties... */ - if ((fblock >= PED_BE16_TO_CPU (walk->extent.start_block)) && - (fblock < (unsigned int) (PED_BE16_TO_CPU ( - walk->extent.start_block) - + PED_BE16_TO_CPU ( - walk->extent.block_count)))) - return 1; - } - - return 0; -} - -/* This function returns the first sector of the last free block of an - HFS volume we can get after a hfs_pack_free_space_from_block call */ -/* On error this function returns 0 */ -PedSector -hfs_get_empty_end (const PedFileSystem *fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsMasterDirectoryBlock* mdb = priv_data->mdb; - unsigned int block, last_bad, end_free_blocks; - - /* find the next block to the last bad block of the volume */ - if (!hfs_read_bad_blocks (fs)) - return 0; - - HfsPrivateLinkExtent* l; - last_bad = 0; - for (l = priv_data->bad_blocks_xtent_list; l; l = l->next) { - if ((unsigned int) PED_BE16_TO_CPU (l->extent.start_block) - + PED_BE16_TO_CPU (l->extent.block_count) > last_bad) - last_bad = PED_BE16_TO_CPU (l->extent.start_block) - + PED_BE16_TO_CPU (l->extent.block_count); - } - - /* Count the free blocks from last_bad to the end of the volume */ - end_free_blocks = 0; - for (block = last_bad; - block < PED_BE16_TO_CPU (mdb->total_blocks); - block++) { - if (!TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - end_free_blocks++; - } - - /* Calculate the block that will by the first free at the - end of the volume */ - block = PED_BE16_TO_CPU (mdb->total_blocks) - end_free_blocks; - - return (PedSector) PED_BE16_TO_CPU (mdb->start_block) - + (PedSector) block * (PED_BE32_TO_CPU (mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT); -} - -/* return the block which should be used to pack data to have at - least free fblock blocks at the end of the volume */ -unsigned int -hfs_find_start_pack (const PedFileSystem *fs, unsigned int fblock) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - unsigned int block; - - for (block = PED_BE16_TO_CPU (priv_data->mdb->total_blocks) - 1; - block && fblock; - block--) { - if (!TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - fblock--; - } - - while (block && !TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - block--; - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - block++; - - return block; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/libparted/fs/hfs/advfs.h b/libparted/fs/hfs/advfs.h deleted file mode 100644 index aff503e..0000000 --- a/libparted/fs/hfs/advfs.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _ADVFS_H -#define _ADVFS_H - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> - -#include "hfs.h" - -int -hfs_btree_search (HfsPrivateFile* b_tree_file, HfsPrivateGenericKey* key, - void *record_out, unsigned int record_size, - HfsCPrivateLeafRec* record_ref); - -void -hfs_free_bad_blocks_list(HfsPrivateLinkExtent* first); - -int -hfs_read_bad_blocks (const PedFileSystem *fs); - -int -hfs_is_bad_block (const PedFileSystem *fs, unsigned int fblock); - -PedSector -hfs_get_empty_end (const PedFileSystem *fs); - -unsigned int -hfs_find_start_pack (const PedFileSystem *fs, unsigned int fblock); - -#endif /* _ADVFS_H */ diff --git a/libparted/fs/hfs/advfs_plus.c b/libparted/fs/hfs/advfs_plus.c deleted file mode 100644 index 08d2f61..0000000 --- a/libparted/fs/hfs/advfs_plus.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef DISCOVER_ONLY - -#include <config.h> - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> - -#if ENABLE_NLS -# include <libintl.h> -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "advfs.h" -#include "file_plus.h" - -#include "advfs_plus.h" - -/* - if a < b, 0 if a == b, + if a > b */ -/* Comparaison is done in the following order : */ -/* CNID, then fork type, then start block */ -static int -hfsplus_extent_key_cmp(HfsPPrivateGenericKey* a, HfsPPrivateGenericKey* b) -{ - HfsPExtentKey* key1 = (HfsPExtentKey*) a; - HfsPExtentKey* key2 = (HfsPExtentKey*) b; - - if (key1->file_ID != key2->file_ID) - return PED_BE32_TO_CPU(key1->file_ID) < - PED_BE32_TO_CPU(key2->file_ID) ? - -1 : +1; - - if (key1->type != key2->type) - return (int)(key1->type - key2->type); - - if (key1->start == key2->start) - return 0; - return PED_BE32_TO_CPU(key1->start) < - PED_BE32_TO_CPU(key2->start) ? - -1 : +1; -} - -/* do a B-Tree lookup */ -/* read the first record immediatly inferior or egal to the given key */ -/* return 0 on error */ -/* record_out _must_ be large enough to receive the whole record (key + data) */ -/* WARNING : the search function called only handle Extents BTree */ -/* so modify this function if you want to do lookup in */ -/* other BTrees has well */ -int -hfsplus_btree_search (HfsPPrivateFile* b_tree_file, HfsPPrivateGenericKey* key, - void *record_out, unsigned int record_size, - HfsCPrivateLeafRec* record_ref) -{ - uint8_t node_1[PED_SECTOR_SIZE_DEFAULT]; - uint8_t* node; - HfsPHeaderRecord* header; - HfsPPrivateGenericKey* record_key = NULL; - unsigned int node_number, record_number, size, bsize; - int i; - - /* Read the header node */ - if (!hfsplus_file_read_sector(b_tree_file, node_1, 0)) - return 0; - header = (HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC); - - /* Get the node number of the root */ - node_number = PED_BE32_TO_CPU (header->root_node); - if (!node_number) - return 0; - - /* Get the size of a node in sectors and allocate buffer */ - size = (bsize = PED_BE16_TO_CPU (header->node_size)) / PED_SECTOR_SIZE_DEFAULT; - node = (uint8_t*) ped_malloc (bsize); - if (!node) - return 0; - HfsPNodeDescriptor *desc = (HfsPNodeDescriptor*) node; - - /* Read the root node */ - if (!hfsplus_file_read (b_tree_file, node, - (PedSector) node_number * size, size)) - return 0; - - /* Follow the white rabbit */ - while (1) { - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = record_number; i; i--) { - record_key = (HfsPPrivateGenericKey*) - (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(bsize - 2*i))))); - /* check for obvious error in FS */ - if (((uint8_t*)record_key - node < HFS_FIRST_REC) - || ((uint8_t*)record_key - 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 (hfsplus_extent_key_cmp(record_key, key) <= 0) - break; - } - if (!i) { free (node); return 0; } - if (desc->type == HFS_IDX_NODE) { - unsigned int skip; - - skip = ( 2 + PED_BE16_TO_CPU (record_key->key_length) - + 1 ) & ~1; - node_number = PED_BE32_TO_CPU (*((uint32_t *) - (((uint8_t *) record_key) + skip))); - if (!hfsplus_file_read(b_tree_file, node, - (PedSector) node_number * size, - size)) { - free (node); - return 0; - } - } else - break; - } - - /* copy the result if needed */ - if (record_size) - memcpy (record_out, record_key, record_size); - - /* send record reference if needed */ - if (record_ref) { - record_ref->node_size = size; /* in sectors */ - record_ref->node_number = node_number; - record_ref->record_pos = (uint8_t*)record_key - node; - record_ref->record_number = i; - } - - /* success */ - free (node); - return 1; -} - -/* free the bad blocks linked list */ -void -hfsplus_free_bad_blocks_list(HfsPPrivateLinkExtent* first) -{ - HfsPPrivateLinkExtent* next; - - while (first) { - next = first->next; - free (first); - first = next; - } -} - -/* This function reads bad blocks extents in the extents file - and store it in f.s. specific data of fs */ -int -hfsplus_read_bad_blocks (const PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - - if (priv_data->bad_blocks_loaded) - return 1; - - { - uint8_t record[sizeof (HfsPExtentKey) - + sizeof (HfsPExtDataRec)]; - HfsPExtentKey search; - HfsPExtentKey* ret_key = (HfsPExtentKey*) record; - HfsPExtDescriptor* ret_cache = (HfsPExtDescriptor*) - (record + sizeof (HfsPExtentKey)); - int block, first_pass = 1; - unsigned int last_start; - - search.key_length = sizeof (HfsExtentKey) - 2; - search.type = HFS_DATA_FORK; - search.pad = 0; - search.file_ID = PED_CPU_TO_BE32 (HFS_BAD_BLOCK_ID); - - last_start = -1; block = 0; - while (1) { - int i; - - search.start = PED_CPU_TO_BE32 (block); - if (!hfsplus_btree_search (priv_data->extents_file, - (HfsPPrivateGenericKey*) &search, - record, sizeof (record), NULL) - || ret_key->file_ID != search.file_ID - || ret_key->type != search.type) { - if (first_pass) - break; - else - goto errbbp; - } - if (PED_BE32_TO_CPU (ret_key->start) == last_start) - break; - - last_start = PED_BE32_TO_CPU (ret_key->start); - for (i = 0; i < HFSP_EXT_NB; i++) { - if (ret_cache[i].block_count) { - HfsPPrivateLinkExtent* new_xt = - (HfsPPrivateLinkExtent*) ped_malloc ( - sizeof (HfsPPrivateLinkExtent)); - if (!new_xt) - goto errbbp; - new_xt->next = priv_data->bad_blocks_xtent_list; - memcpy (&(new_xt->extent), ret_cache+i, - sizeof (HfsPExtDescriptor)); - priv_data->bad_blocks_xtent_list = new_xt; - priv_data->bad_blocks_xtent_nb++; - block += PED_BE32_TO_CPU ( - ret_cache[i].block_count); - } - } - first_pass = 0; - } - - priv_data->bad_blocks_loaded = 1; - return 1;} - -errbbp: hfsplus_free_bad_blocks_list(priv_data->bad_blocks_xtent_list); - priv_data->bad_blocks_xtent_list=NULL; - priv_data->bad_blocks_xtent_nb=0; - return 0; -} - -/* This function check if fblock is a bad block */ -int -hfsplus_is_bad_block (const PedFileSystem *fs, unsigned int fblock) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPPrivateLinkExtent* walk; - - for (walk = priv_data->bad_blocks_xtent_list; walk; walk = walk->next) { - /* Won't compile without the strange cast ! gcc bug ? */ - /* or maybe C subtilties... */ - if ((fblock >= PED_BE32_TO_CPU (walk->extent.start_block)) && - (fblock < (unsigned int)(PED_BE32_TO_CPU ( - walk->extent.start_block) - + PED_BE32_TO_CPU (walk->extent.block_count)))) - return 1; - } - - return 0; -} - -/* This function returns the first sector of the last free block of - an HFS+ volume we can get after a hfsplus_pack_free_space_from_block call */ -PedSector -hfsplus_get_empty_end (const PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPVolumeHeader* vh = priv_data->vh; - unsigned int block, last_bad, end_free_blocks; - - /* find the next block to the last bad block of the volume */ - if (!hfsplus_read_bad_blocks (fs)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Bad blocks could not be read.")); - return 0; - } - - HfsPPrivateLinkExtent* l; - last_bad = 0; - for (l = priv_data->bad_blocks_xtent_list; l; l = l->next) { - if ((unsigned int) PED_BE32_TO_CPU (l->extent.start_block) - + PED_BE32_TO_CPU (l->extent.block_count) > last_bad) - last_bad = PED_BE32_TO_CPU (l->extent.start_block) - + PED_BE32_TO_CPU (l->extent.block_count); - } - - /* Count the free blocks from last_bad to the end of the volume */ - end_free_blocks = 0; - for (block = last_bad; - block < PED_BE32_TO_CPU (vh->total_blocks); - block++) { - if (!TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - end_free_blocks++; - } - - /* Calculate the block that will by the first free at - the end of the volume */ - block = PED_BE32_TO_CPU (vh->total_blocks) - end_free_blocks; - - return (PedSector) block * ( PED_BE32_TO_CPU (vh->block_size) - / PED_SECTOR_SIZE_DEFAULT ); -} - -/* On error, returns 0 */ -PedSector -hfsplus_get_min_size (const PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - PedSector min_size; - - /* don't need to add anything because every sector - can be part of allocation blocks in HFS+, and - the last block _must_ be reserved */ - min_size = hfsplus_get_empty_end(fs); - if (!min_size) return 0; - - if (priv_data->wrapper) { - HfsPrivateFSData* hfs_priv_data = (HfsPrivateFSData*) - priv_data->wrapper->type_specific; - unsigned int hfs_sect_block; - PedSector hgee; - hfs_sect_block = - PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT; - /* - * if hfs+ is embedded in an hfs wrapper then the new size is : - * the new size of the hfs+ volume rounded up to the size - * of hfs blocks - * + the minimum size of the hfs wrapper without any hfs+ - * modification - * - the current size of the hfs+ volume in the hfs wrapper - */ - hgee = hfs_get_empty_end(priv_data->wrapper); - if (!hgee) return 0; - min_size = ((min_size + hfs_sect_block - 1) / hfs_sect_block) - * hfs_sect_block - + hgee + 2 - - (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb - ->old_new.embedded - .location.block_count ) - * hfs_sect_block; - } - - return min_size; -} - -/* return the block which should be used to pack data to have - at least free fblock blocks at the end of the volume */ -unsigned int -hfsplus_find_start_pack (const PedFileSystem *fs, unsigned int fblock) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - unsigned int block; - - for (block = PED_BE32_TO_CPU (priv_data->vh->total_blocks) - 1; - block && fblock; - block--) { - if (!TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - fblock--; - } - - while (block && !TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - block--; - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - block++; - - return block; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/libparted/fs/hfs/advfs_plus.h b/libparted/fs/hfs/advfs_plus.h deleted file mode 100644 index fdf61c6..0000000 --- a/libparted/fs/hfs/advfs_plus.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _ADVFS_PLUS_H -#define _ADVFS_PLUS_H - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> - -#include "hfs.h" - -int -hfsplus_btree_search (HfsPPrivateFile* b_tree_file, HfsPPrivateGenericKey* key, - void *record_out, unsigned int record_size, - HfsCPrivateLeafRec* record_ref); - -void -hfsplus_free_bad_blocks_list(HfsPPrivateLinkExtent* first); - -int -hfsplus_read_bad_blocks (const PedFileSystem *fs); - -int -hfsplus_is_bad_block (const PedFileSystem *fs, unsigned int fblock); - -PedSector -hfsplus_get_empty_end (const PedFileSystem *fs); - -PedSector -hfsplus_get_min_size (const PedFileSystem *fs); - -unsigned int -hfsplus_find_start_pack (const PedFileSystem *fs, unsigned int fblock); - -#endif /* _ADVFS_PLUS_H */ diff --git a/libparted/fs/hfs/cache.c b/libparted/fs/hfs/cache.c deleted file mode 100644 index 97dcca7..0000000 --- a/libparted/fs/hfs/cache.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef DISCOVER_ONLY - -#include <config.h> - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> -#include <stdint.h> - -#if ENABLE_NLS -# include <libintl.h> -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" - -#include "cache.h" - -static HfsCPrivateCacheTable* -hfsc_new_cachetable(unsigned int size) -{ - HfsCPrivateCacheTable* ret; - - ret = (HfsCPrivateCacheTable*) ped_malloc(sizeof(*ret)); - if (!ret) return NULL; - - ret->next_cache = NULL; - ret->table_size = size; - ret->table_first_free = 0; - - ret->table = ped_malloc(sizeof(*ret->table)*size); - if (!ret->table) { free(ret); return NULL; } - memset(ret->table, 0, sizeof(*ret->table)*size); - - return ret; -} - -HfsCPrivateCache* -hfsc_new_cache(unsigned int block_number, unsigned int file_number) -{ - unsigned int cachetable_size, i; - HfsCPrivateCache* ret; - - ret = (HfsCPrivateCache*) ped_malloc(sizeof(*ret)); - if (!ret) return NULL; - ret->block_number = block_number; - /* following code avoid integer overflow */ - ret->linked_ref_size = block_number > block_number + ((1<<CR_SHIFT)-1) ? - ( block_number >> CR_SHIFT ) + 1 : - ( block_number + ((1<<CR_SHIFT)-1) ) >> CR_SHIFT - ; - - ret->linked_ref = (HfsCPrivateExtent**) - ped_malloc( sizeof(*ret->linked_ref) - * ret->linked_ref_size ); - if (!ret->linked_ref) { free(ret); return NULL; } - - cachetable_size = file_number + file_number / CR_OVER_DIV + CR_ADD_CST; - if (cachetable_size < file_number) cachetable_size = (unsigned) -1; - ret->first_cachetable_size = cachetable_size; - ret->table_list = hfsc_new_cachetable(cachetable_size); - if (!ret->table_list) { - free(ret->linked_ref); - free(ret); - return NULL; - } - ret->last_table = ret->table_list; - - for (i = 0; i < ret->linked_ref_size; ++i) - ret->linked_ref[i] = NULL; - - ret->needed_alloc_size = 0; - - return ret; -} - -static void -hfsc_delete_cachetable(HfsCPrivateCacheTable* list) -{ - HfsCPrivateCacheTable* next; - - while (list) { - free (list->table); - next = list->next_cache; - free (list); - list = next; - } -} - -void -hfsc_delete_cache(HfsCPrivateCache* cache) -{ - hfsc_delete_cachetable(cache->table_list); - free(cache->linked_ref); - free(cache); -} - -HfsCPrivateExtent* -hfsc_cache_add_extent(HfsCPrivateCache* cache, uint32_t start, uint32_t length, - uint32_t block, uint16_t offset, uint8_t sbb, - uint8_t where, uint8_t ref_index) -{ - HfsCPrivateExtent* ext; - unsigned int idx = start >> CR_SHIFT; - - PED_ASSERT(idx < cache->linked_ref_size); - - for (ext = cache->linked_ref[idx]; - ext && start != ext->ext_start; - ext = ext->next); - - if (ext) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to register an extent starting at block " - "0x%X, but another one already exists at this " - "position. You should check the file system!"), - start); - return NULL; - } - - if ( cache->last_table->table_first_free - == cache->last_table->table_size ) { - cache->last_table->next_cache = - hfsc_new_cachetable( ( cache->first_cachetable_size - / CR_NEW_ALLOC_DIV ) - + CR_ADD_CST ); - if (!cache->last_table->next_cache) - return NULL; - cache->last_table = cache->last_table->next_cache; - } - - ext = cache->last_table->table+(cache->last_table->table_first_free++); - - ext->ext_start = start; - ext->ext_length = length; - ext->ref_block = block; - ext->ref_offset = offset; - ext->sect_by_block = sbb; - ext->where = where; - ext->ref_index = ref_index; - - ext->next = cache->linked_ref[idx]; - cache->linked_ref[idx] = ext; - - cache->needed_alloc_size = cache->needed_alloc_size > - (unsigned) PED_SECTOR_SIZE_DEFAULT * sbb ? - cache->needed_alloc_size : - (unsigned) PED_SECTOR_SIZE_DEFAULT * sbb; - - return ext; -} - -HfsCPrivateExtent* -hfsc_cache_search_extent(HfsCPrivateCache* cache, uint32_t start) -{ - HfsCPrivateExtent* ret; - unsigned int idx = start >> CR_SHIFT; - - PED_ASSERT(idx < cache->linked_ref_size); - - for (ret = cache->linked_ref[idx]; - ret && start != ret->ext_start; - ret = ret->next); - - return ret; -} - -/* Can't fail if extent begining at old_start exists */ -/* Returns 0 if no such extent, or on error */ -HfsCPrivateExtent* -hfsc_cache_move_extent(HfsCPrivateCache* cache, uint32_t old_start, - uint32_t new_start) -{ - HfsCPrivateExtent** ppext; - HfsCPrivateExtent* pext; - - unsigned int idx1 = old_start >> CR_SHIFT; - unsigned int idx2 = new_start >> CR_SHIFT; - - PED_ASSERT(idx1 < cache->linked_ref_size); - PED_ASSERT(idx2 < cache->linked_ref_size); - - for (pext = cache->linked_ref[idx2]; - pext && new_start != pext->ext_start; - pext = pext->next); - - if (pext) { - ped_exception_throw ( - PED_EXCEPTION_BUG, - PED_EXCEPTION_CANCEL, - _("Trying to move an extent from block Ox%X to block " - "Ox%X, but another one already exists at this " - "position. This should not happen!"), - old_start, new_start); - return NULL; - } - - for (ppext = &(cache->linked_ref[idx1]); - (*ppext) && old_start != (*ppext)->ext_start; - ppext = &((*ppext)->next)); - - if (!(*ppext)) return NULL; - - /* removing the extent from the cache */ - pext = *ppext; - (*ppext) = pext->next; - - /* change ext_start and insert the extent again */ - pext->ext_start = new_start; - pext->next = cache->linked_ref[idx2]; - cache->linked_ref[idx2] = pext; - - return pext; -} - -#endif /* DISCOVER_ONLY */ diff --git a/libparted/fs/hfs/cache.h b/libparted/fs/hfs/cache.h deleted file mode 100644 index e0c73e0..0000000 --- a/libparted/fs/hfs/cache.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _CACHE_H -#define _CACHE_H - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> - -#include "hfs.h" - -/* CR => CACHE REF */ -#define CR_NULL 0 /* reserved */ -#define CR_PRIM_CAT 1 -#define CR_PRIM_EXT 2 -#define CR_PRIM_ATTR 3 -#define CR_PRIM_ALLOC 4 -#define CR_PRIM_START 5 -#define CR_BTREE_CAT 6 -#define CR_BTREE_ATTR 7 -#define CR_BTREE_EXT_0 8 -#define CR_BTREE_EXT_CAT 9 -#define CR_BTREE_EXT_EXT 10 /* should not happen ! */ -#define CR_BTREE_EXT_ATTR 11 -#define CR_BTREE_EXT_ALLOC 12 -#define CR_BTREE_EXT_START 13 /* unneeded in current code */ -#define CR_BTREE_CAT_JIB 14 /* journal info block */ -#define CR_BTREE_CAT_JL 15 /* journal */ -/* 16 -> 31 || high order bit */ /* reserved */ - -/* tuning */ -#define CR_SHIFT 8 /* number of bits to shift start_block by */ - /* to get the index of the linked list */ -#define CR_OVER_DIV 16 /* alloc a table for (1+1/CR_OVER_DIV) * - file_number + CR_ADD_CST */ -#define CR_ADD_CST 16 -#define CR_NEW_ALLOC_DIV 4 /* divide the size of the first alloc table - by this value to allocate next tables */ - -/* See DOC for an explaination of this structure */ -/* Access read only from outside cache.c */ -struct _HfsCPrivateExtent { - struct _HfsCPrivateExtent* next; - uint32_t ext_start; - uint32_t ext_length; - uint32_t ref_block; - uint16_t ref_offset; - uint8_t sect_by_block; - unsigned where : 5; - unsigned ref_index : 3; /* 0 -> 7 */ -}; -typedef struct _HfsCPrivateExtent HfsCPrivateExtent; - -/* Internaly used by cache.c for custom memory managment only */ -struct _HfsCPrivateCacheTable { - struct _HfsCPrivateCacheTable* next_cache; - HfsCPrivateExtent* table; - unsigned int table_size; - unsigned int table_first_free; - /* first_elemt ? */ -}; -typedef struct _HfsCPrivateCacheTable HfsCPrivateCacheTable; - -/* Internaly used by cache.c for custom memory managment - and cache handling only */ -struct _HfsCPrivateCache { - HfsCPrivateCacheTable* table_list; - HfsCPrivateCacheTable* last_table; - HfsCPrivateExtent** linked_ref; - unsigned int linked_ref_size; - unsigned int block_number; - unsigned int first_cachetable_size; - unsigned int needed_alloc_size; -}; -typedef struct _HfsCPrivateCache HfsCPrivateCache; - -HfsCPrivateCache* -hfsc_new_cache(unsigned int block_number, unsigned int file_number); - -void -hfsc_delete_cache(HfsCPrivateCache* cache); - -HfsCPrivateExtent* -hfsc_cache_add_extent(HfsCPrivateCache* cache, uint32_t start, uint32_t length, - uint32_t block, uint16_t offset, uint8_t sbb, - uint8_t where, uint8_t index); - -HfsCPrivateExtent* -hfsc_cache_search_extent(HfsCPrivateCache* cache, uint32_t start); - -HfsCPrivateExtent* -hfsc_cache_move_extent(HfsCPrivateCache* cache, uint32_t old_start, - uint32_t new_start); - -static __inline__ unsigned int -hfsc_cache_needed_buffer(HfsCPrivateCache* cache) -{ - return cache->needed_alloc_size; -} - -#endif /* _CACHE_H */ diff --git a/libparted/fs/hfs/file.c b/libparted/fs/hfs/file.c deleted file mode 100644 index 9fc501b..0000000 --- a/libparted/fs/hfs/file.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef DISCOVER_ONLY - -#include <config.h> - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> -#include <stdint.h> - -#if ENABLE_NLS -# include <libintl.h> -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "advfs.h" - -#include "file.h" - -/* 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; -} - -/* Close an HFS file */ -void -hfs_file_close (HfsPrivateFile* file) -{ - free (file); -} - -/* warning : only works on data forks */ -static int -hfs_get_extent_containing (HfsPrivateFile* file, unsigned int block, - HfsExtDataRec cache, uint16_t* ptr_start_cache) -{ - uint8_t record[sizeof (HfsExtentKey) - + sizeof (HfsExtDataRec)]; - HfsExtentKey search; - HfsExtentKey* ret_key = (HfsExtentKey*) record; - HfsExtDescriptor* ret_cache = (HfsExtDescriptor*) - (record + sizeof (HfsExtentKey)); - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - file->fs->type_specific; - - search.key_length = sizeof (HfsExtentKey) - 1; - search.type = HFS_DATA_FORK; - search.file_ID = file->CNID; - search.start = PED_CPU_TO_BE16 (block); - - if (!hfs_btree_search (priv_data->extent_file, - (HfsPrivateGenericKey*) &search, - record, sizeof (record), NULL)) - return 0; - - if (ret_key->file_ID != search.file_ID || ret_key->type != search.type) - return 0; - - memcpy (cache, ret_cache, sizeof(HfsExtDataRec)); - *ptr_start_cache = PED_BE16_TO_CPU (ret_key->start); - - return 1; -} - -/* find and return the nth sector of a file */ -/* return 0 on error */ -static PedSector -hfs_file_find_sector (HfsPrivateFile* file, PedSector sector) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - file->fs->type_specific; - unsigned int sect_by_block = PED_BE32_TO_CPU ( - priv_data->mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT; - unsigned int i, s, vol_block; - unsigned int block = sector / sect_by_block; - unsigned int offset = sector % sect_by_block; - - /* in the three first extent */ - for (s = 0, i = 0; i < HFS_EXT_NB; i++) { - if ((block >= s) && ( block < s + PED_BE16_TO_CPU ( - file->first[i].block_count))) { - vol_block = (block - s) + PED_BE16_TO_CPU ( - file->first[i].start_block); - goto sector_found; - } - s += PED_BE16_TO_CPU (file->first[i].block_count); - } - - /* in the three cached extent */ - if (file->start_cache && block >= file->start_cache) - for (s = file->start_cache, i = 0; i < HFS_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE16_TO_CPU ( - file->cache[i].block_count))) { - vol_block = (block - s) + PED_BE16_TO_CPU ( - file->cache[i].start_block); - goto sector_found; - } - s += PED_BE16_TO_CPU (file->cache[i].block_count); - } - - /* update cache */ - if (!hfs_get_extent_containing (file, block, file->cache, - &(file->start_cache))) { - ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_CANCEL, - _("Could not update the extent cache for HFS file with " - "CNID %X."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - /* in the three cached extent */ - PED_ASSERT(file->start_cache && block >= file->start_cache); - for (s = file->start_cache, i = 0; i < HFS_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE16_TO_CPU ( - file->cache[i].block_count))) { - vol_block = (block - s) + PED_BE16_TO_CPU ( - file->cache[i].start_block); - goto sector_found; - } - s += PED_BE16_TO_CPU (file->cache[i].block_count); - } - - return 0; - - sector_found: - return (PedSector) PED_BE16_TO_CPU (priv_data->mdb->start_block) - + (PedSector) vol_block * sect_by_block - + offset; -} - -/* Read the nth sector of a file */ -/* return 0 on error */ -int -hfs_file_read_sector (HfsPrivateFile* file, void *buf, PedSector sector) -{ - PedSector abs_sector; - - if (sector >= file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to read HFS file with CNID %X behind EOF."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - abs_sector = hfs_file_find_sector (file, sector); - if (!abs_sector) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not find sector %lli of HFS file with " - "CNID %X."), - sector, PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - return ped_geometry_read (file->fs->geom, buf, abs_sector, 1); -} - -/* Write the nth sector of a file */ -/* return 0 on error */ -int -hfs_file_write_sector (HfsPrivateFile* file, void *buf, PedSector sector) -{ - PedSector abs_sector; - - if (sector >= file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to write HFS file with CNID %X behind EOF."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - abs_sector = hfs_file_find_sector (file, sector); - if (!abs_sector) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not find sector %lli of HFS file with " - "CNID %X."), - sector, PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - return ped_geometry_write (file->fs->geom, buf, abs_sector, 1); -} - -#endif /* !DISCOVER_ONLY */ diff --git a/libparted/fs/hfs/file.h b/libparted/fs/hfs/file.h deleted file mode 100644 index a16f835..0000000 --- a/libparted/fs/hfs/file.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _FILE_H -#define _FILE_H - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> - -#include "hfs.h" - -HfsPrivateFile* -hfs_file_open (PedFileSystem *fs, uint32_t CNID, - HfsExtDataRec ext_desc, PedSector sect_nb); - -void -hfs_file_close (HfsPrivateFile* file); - -int -hfs_file_read_sector (HfsPrivateFile* file, void *buf, PedSector sector); - -int -hfs_file_write_sector (HfsPrivateFile* file, void *buf, PedSector sector); - -#endif /* _FILE_H */ diff --git a/libparted/fs/hfs/file_plus.c b/libparted/fs/hfs/file_plus.c deleted file mode 100644 index acacc93..0000000 --- a/libparted/fs/hfs/file_plus.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef DISCOVER_ONLY - -#include <config.h> - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> -#include <stdint.h> - -#if ENABLE_NLS -# include <libintl.h> -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "advfs_plus.h" - -#include "file_plus.h" - -/* Open the data fork of a file with its first eight extents and its CNID */ -/* CNID and ext_desc must be in disc order, sect_nb in CPU order */ -/* return null on failure */ -HfsPPrivateFile* -hfsplus_file_open (PedFileSystem *fs, HfsPNodeID CNID, - HfsPExtDataRec ext_desc, PedSector sect_nb) -{ - HfsPPrivateFile* file; - - file = (HfsPPrivateFile*) ped_malloc (sizeof (HfsPPrivateFile)); - if (!file) return NULL; - - file->fs = fs; - file->sect_nb = sect_nb; - file->CNID = CNID; - memcpy(file->first, ext_desc, sizeof (HfsPExtDataRec)); - file->start_cache = 0; - - return file; -} - -/* Close an HFS+ file */ -void -hfsplus_file_close (HfsPPrivateFile* file) -{ - free (file); -} - -/* warning : only works on data forks */ -static int -hfsplus_get_extent_containing (HfsPPrivateFile* file, unsigned int block, - HfsPExtDataRec cache, uint32_t* ptr_start_cache) -{ - uint8_t record[sizeof (HfsPExtentKey) - + sizeof (HfsPExtDataRec)]; - HfsPExtentKey search; - HfsPExtentKey* ret_key = (HfsPExtentKey*) record; - HfsPExtDescriptor* ret_cache = (HfsPExtDescriptor*) - (record + sizeof (HfsPExtentKey)); - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - file->fs->type_specific; - - search.key_length = PED_CPU_TO_BE16 (sizeof (HfsPExtentKey) - 2); - search.type = HFS_DATA_FORK; - search.pad = 0; - search.file_ID = file->CNID; - search.start = PED_CPU_TO_BE32 (block); - - if (!hfsplus_btree_search (priv_data->extents_file, - (HfsPPrivateGenericKey*) &search, - record, sizeof (record), NULL)) - return 0; - - if (ret_key->file_ID != search.file_ID || ret_key->type != search.type) - return 0; - - memcpy (cache, ret_cache, sizeof(HfsPExtDataRec)); - *ptr_start_cache = PED_BE32_TO_CPU (ret_key->start); - - return 1; -} - -/* find a sub extent contained in the desired area */ -/* and with the same starting point */ -/* return 0 in sector_count on error, or the physical area */ -/* on the volume corresponding to the logical area in the file */ -static HfsPPrivateExtent -hfsplus_file_find_extent (HfsPPrivateFile* file, PedSector sector, - unsigned int nb) -{ - HfsPPrivateExtent ret = {0,0}; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - file->fs->type_specific; - unsigned int sect_by_block = PED_BE32_TO_CPU ( - priv_data->vh->block_size) - / PED_SECTOR_SIZE_DEFAULT; - unsigned int i, s, vol_block, size; - PedSector sect_size; - unsigned int block = sector / sect_by_block; - unsigned int offset = sector % sect_by_block; - - /* in the 8 first extent */ - for (s = 0, i = 0; i < HFSP_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE32_TO_CPU ( - file->first[i].block_count))) { - vol_block = (block - s) - + PED_BE32_TO_CPU (file->first[i] - .start_block); - size = PED_BE32_TO_CPU (file->first[i].block_count) - + s - block; - goto plus_sector_found; - } - s += PED_BE32_TO_CPU (file->first[i].block_count); - } - - /* in the 8 cached extent */ - if (file->start_cache && block >= file->start_cache) - for (s = file->start_cache, i = 0; i < HFSP_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE32_TO_CPU ( - file->cache[i].block_count))) { - vol_block = (block - s) - + PED_BE32_TO_CPU (file->cache[i] - .start_block); - size = PED_BE32_TO_CPU (file->cache[i].block_count) - + s - block; - goto plus_sector_found; - } - s += PED_BE32_TO_CPU (file->cache[i].block_count); - } - - /* update cache */ - if (!hfsplus_get_extent_containing (file, block, file->cache, - &(file->start_cache))) { - ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_CANCEL, - _("Could not update the extent cache for HFS+ file " - "with CNID %X."), - PED_BE32_TO_CPU(file->CNID)); - return ret; /* ret == {0,0} */ - } - - /* ret == {0,0} */ - PED_ASSERT(file->start_cache && block >= file->start_cache); - - for (s = file->start_cache, i = 0; i < HFSP_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE32_TO_CPU ( - file->cache[i].block_count))) { - vol_block = (block - s) - + PED_BE32_TO_CPU (file->cache[i] - .start_block); - size = PED_BE32_TO_CPU (file->cache[i].block_count) - + s - block; - goto plus_sector_found; - } - s += PED_BE32_TO_CPU (file->cache[i].block_count); - } - - return ret; - -plus_sector_found: - sect_size = (PedSector) size * sect_by_block - offset; - ret.start_sector = vol_block * sect_by_block + offset; - ret.sector_count = (sect_size < nb) ? sect_size : nb; - return ret; -} - -int -hfsplus_file_read(HfsPPrivateFile* file, void *buf, PedSector sector, - unsigned int nb) -{ - HfsPPrivateExtent phy_area; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - file->fs->type_specific; - char *b = buf; - - if (sector+nb < sector /* detect overflow */ - || sector+nb > file->sect_nb) /* out of file */ { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to read HFS+ file with CNID %X behind EOF."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - while (nb) { - phy_area = hfsplus_file_find_extent(file, sector, nb); - if (phy_area.sector_count == 0) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not find sector %lli of HFS+ file " - "with CNID %X."), - sector, PED_BE32_TO_CPU(file->CNID)); - return 0; - } - if (!ped_geometry_read(priv_data->plus_geom, b, - phy_area.start_sector, - phy_area.sector_count)) - return 0; - - nb -= phy_area.sector_count; /* < nb anyway ... */ - sector += phy_area.sector_count; - b += phy_area.sector_count * PED_SECTOR_SIZE_DEFAULT; - } - - return 1; -} - -int -hfsplus_file_write(HfsPPrivateFile* file, void *buf, PedSector sector, - unsigned int nb) -{ - HfsPPrivateExtent phy_area; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - file->fs->type_specific; - char *b = buf; - - if (sector+nb < sector /* detect overflow */ - || sector+nb > file->sect_nb) /* out of file */ { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to write HFS+ file with CNID %X behind EOF."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - while (nb) { - phy_area = hfsplus_file_find_extent(file, sector, nb); - if (phy_area.sector_count == 0) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not find sector %lli of HFS+ file " - "with CNID %X."), - sector, PED_BE32_TO_CPU(file->CNID)); - return 0; - } - if (!ped_geometry_write(priv_data->plus_geom, b, - phy_area.start_sector, - phy_area.sector_count)) - return 0; - - nb -= phy_area.sector_count; /* < nb anyway ... */ - sector += phy_area.sector_count; - b += phy_area.sector_count * PED_SECTOR_SIZE_DEFAULT; - } - - return 1; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/libparted/fs/hfs/file_plus.h b/libparted/fs/hfs/file_plus.h deleted file mode 100644 index e2dcbd2..0000000 --- a/libparted/fs/hfs/file_plus.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _FILE_PLUS_H -#define _FILE_PLUS_H - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> - -#include "hfs.h" - -HfsPPrivateFile* -hfsplus_file_open (PedFileSystem *fs, HfsPNodeID CNID, - HfsPExtDataRec ext_desc, PedSector sect_nb); - -void -hfsplus_file_close (HfsPPrivateFile* file); - -int -hfsplus_file_read(HfsPPrivateFile* file, void *buf, - PedSector sector, unsigned int nb); - -int -hfsplus_file_write(HfsPPrivateFile* file, void *buf, - PedSector sector, unsigned int nb); - -/* Read the nth sector of a file */ -/* return 0 on error */ -static __inline__ int -hfsplus_file_read_sector (HfsPPrivateFile* file, void *buf, PedSector sector) -{ - return hfsplus_file_read(file, buf, sector, 1); -} - -/* Write the nth sector of a file */ -/* return 0 on error */ -static __inline__ int -hfsplus_file_write_sector (HfsPPrivateFile* file, void *buf, PedSector sector) -{ - return hfsplus_file_write(file, buf, sector, 1); -} - - -#endif /* _FILE_PLUS_H */ diff --git a/libparted/fs/hfs/hfs.c b/libparted/fs/hfs/hfs.c index a2d4d07..275bc24 100644 --- a/libparted/fs/hfs/hfs.c +++ b/libparted/fs/hfs/hfs.c @@ -48,1179 +48,6 @@ unsigned hfsp_block_count; #define HFSP_BLOCK_SIZES ((int[2]){512, 0}) #define HFSX_BLOCK_SIZES ((int[2]){512, 0}) -#ifndef DISCOVER_ONLY -#include "file.h" -#include "reloc.h" -#include "advfs.h" - -static PedFileSystemType hfs_type; -static PedFileSystemType hfsplus_type; - - -/* ----- HFS ----- */ - -/* This is a very unundoable operation */ -/* Maybe I shouldn't touch the alternate MDB ? */ -/* Anyway clobber is call before other fs creation */ -/* So this is a non-issue */ -static int -hfs_clobber (PedGeometry* geom) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - - memset (buf, 0, PED_SECTOR_SIZE_DEFAULT); - - /* destroy boot blocks, mdb, alternate mdb ... */ - return (!!ped_geometry_write (geom, buf, 0, 1)) & - (!!ped_geometry_write (geom, buf, 1, 1)) & - (!!ped_geometry_write (geom, buf, 2, 1)) & - (!!ped_geometry_write (geom, buf, geom->length - 2, 1)) & - (!!ped_geometry_write (geom, buf, geom->length - 1, 1)) & - (!!ped_geometry_sync (geom)); -} - -static PedFileSystem* -hfs_open (PedGeometry* geom) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - PedFileSystem* fs; - HfsMasterDirectoryBlock* mdb; - HfsPrivateFSData* priv_data; - - if (!hfsc_can_use_geom (geom)) - return NULL; - - /* Read MDB */ - if (!ped_geometry_read (geom, buf, 2, 1)) - return NULL; - - /* Allocate memory */ - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) goto ho; - mdb = (HfsMasterDirectoryBlock*) - ped_malloc (sizeof (HfsMasterDirectoryBlock)); - if (!mdb) goto ho_fs; - priv_data = (HfsPrivateFSData*) - ped_malloc (sizeof (HfsPrivateFSData)); - if (!priv_data) goto ho_mdb; - - memcpy (mdb, buf, sizeof (HfsMasterDirectoryBlock)); - - /* init structures */ - priv_data->mdb = mdb; - priv_data->bad_blocks_loaded = 0; - priv_data->bad_blocks_xtent_nb = 0; - priv_data->bad_blocks_xtent_list = NULL; - priv_data->extent_file = - hfs_file_open (fs, PED_CPU_TO_BE32 (HFS_XTENT_ID), - mdb->extents_file_rec, - PED_CPU_TO_BE32 (mdb->extents_file_size) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->extent_file) goto ho_pd; - priv_data->catalog_file = - hfs_file_open (fs, PED_CPU_TO_BE32 (HFS_CATALOG_ID), - mdb->catalog_file_rec, - PED_CPU_TO_BE32 (mdb->catalog_file_size) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->catalog_file) goto ho_ce; - /* Read allocation blocks */ - if (!ped_geometry_read(geom, priv_data->alloc_map, - PED_BE16_TO_CPU (mdb->volume_bitmap_block), - ( PED_BE16_TO_CPU (mdb->total_blocks) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8) ) ) - goto ho_cf; - - fs->type = &hfs_type; - fs->geom = ped_geometry_duplicate (geom); - if (!fs->geom) goto ho_cf; - fs->type_specific = (void*) priv_data; - fs->checked = ( PED_BE16_TO_CPU (mdb->volume_attributes) - >> HFS_UNMOUNTED ) & 1; - - return fs; - -/*--- clean error handling ---*/ -ho_cf: hfs_file_close(priv_data->catalog_file); -ho_ce: hfs_file_close(priv_data->extent_file); -ho_pd: free(priv_data); -ho_mdb: free(mdb); -ho_fs: free(fs); -ho: return NULL; -} - -static int -hfs_close (PedFileSystem *fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) fs->type_specific; - - hfs_file_close (priv_data->extent_file); - hfs_file_close (priv_data->catalog_file); - if (priv_data->bad_blocks_loaded) - hfs_free_bad_blocks_list (priv_data->bad_blocks_xtent_list); - free (priv_data->mdb); - free (priv_data); - ped_geometry_destroy (fs->geom); - free (fs); - - return 1; -} - -static PedConstraint* -hfs_get_resize_constraint (const PedFileSystem *fs) -{ - PedDevice* dev = fs->geom->dev; - PedAlignment start_align; - PedGeometry start_sector; - PedGeometry full_dev; - PedSector min_size; - - if (!ped_alignment_init (&start_align, fs->geom->start, 0)) - return NULL; - if (!ped_geometry_init (&start_sector, dev, fs->geom->start, 1)) - return NULL; - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - /* 2 = last two sectors (alternate MDB and unused sector) */ - min_size = hfs_get_empty_end(fs) + 2; - if (min_size == 2) return NULL; - - return ped_constraint_new (&start_align, ped_alignment_any, - &start_sector, &full_dev, min_size, - fs->geom->length); -} - -static 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); -} - -/* ----- HFS+ ----- */ - -#include "file_plus.h" -#include "advfs_plus.h" -#include "reloc_plus.h" -#include "journal.h" - -static int -hfsplus_clobber (PedGeometry* geom) -{ - unsigned int i = 1; - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - HfsMasterDirectoryBlock *mdb; - - mdb = (HfsMasterDirectoryBlock *) buf; - - if (!ped_geometry_read (geom, buf, 2, 1)) - return 0; - - if (PED_BE16_TO_CPU (mdb->signature) == HFS_SIGNATURE) { - /* embedded hfs+ */ - PedGeometry *embedded; - - i = PED_BE32_TO_CPU(mdb->block_size) / PED_SECTOR_SIZE_DEFAULT; - embedded = ped_geometry_new ( - geom->dev, - (PedSector) geom->start - + PED_BE16_TO_CPU (mdb->start_block) - + (PedSector) PED_BE16_TO_CPU ( - mdb->old_new.embedded.location.start_block ) * i, - (PedSector) PED_BE16_TO_CPU ( - mdb->old_new.embedded.location.block_count ) * i ); - if (!embedded) i = 0; - else { - i = hfs_clobber (embedded); - ped_geometry_destroy (embedded); - } - } - - /* non-embedded or envelop destroy as hfs */ - return ( hfs_clobber (geom) && i ); -} - -static int -hfsplus_close (PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - - if (priv_data->bad_blocks_loaded) - hfsplus_free_bad_blocks_list(priv_data->bad_blocks_xtent_list); - free(priv_data->alloc_map); - free(priv_data->dirty_alloc_map); - hfsplus_file_close (priv_data->allocation_file); - hfsplus_file_close (priv_data->attributes_file); - hfsplus_file_close (priv_data->catalog_file); - hfsplus_file_close (priv_data->extents_file); - if (priv_data->free_geom) ped_geometry_destroy (priv_data->plus_geom); - if (priv_data->wrapper) hfs_close(priv_data->wrapper); - ped_geometry_destroy (fs->geom); - free(priv_data->vh); - free(priv_data); - free(fs); - - return 1; -} - -static PedFileSystem* -hfsplus_open (PedGeometry* geom) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - PedFileSystem* fs; - HfsPVolumeHeader* vh; - HfsPPrivateFSData* priv_data; - PedGeometry* wrapper_geom; - unsigned int map_sectors; - - if (!hfsc_can_use_geom (geom)) - return NULL; - - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) goto hpo; - vh = (HfsPVolumeHeader*) ped_malloc (sizeof (HfsPVolumeHeader)); - if (!vh) goto hpo_fs; - priv_data = (HfsPPrivateFSData*)ped_malloc (sizeof (HfsPPrivateFSData)); - if (!priv_data) goto hpo_vh; - - fs->geom = ped_geometry_duplicate (geom); - if (!fs->geom) goto hpo_pd; - fs->type_specific = (void*) priv_data; - - if ((wrapper_geom = hfs_and_wrapper_probe (geom))) { - HfsPrivateFSData* hfs_priv_data; - PedSector abs_sect, length; - unsigned int bs; - - ped_geometry_destroy (wrapper_geom); - priv_data->wrapper = hfs_open(geom); - if (!priv_data->wrapper) goto hpo_gm; - hfs_priv_data = (HfsPrivateFSData*) - priv_data->wrapper->type_specific; - bs = PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT; - abs_sect = (PedSector) geom->start - + (PedSector) PED_BE16_TO_CPU ( - hfs_priv_data->mdb->start_block) - + (PedSector) PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new - .embedded.location.start_block ) - * bs; - length = (PedSector) PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new - .embedded.location.block_count) - * bs; - priv_data->plus_geom = ped_geometry_new (geom->dev, abs_sect, - length); - if (!priv_data->plus_geom) goto hpo_wr; - priv_data->free_geom = 1; - } else { - priv_data->wrapper = NULL; - priv_data->plus_geom = fs->geom; - priv_data->free_geom = 0; - } - - if (!ped_geometry_read (priv_data->plus_geom, buf, 2, 1)) goto hpo_pg; - memcpy (vh, buf, sizeof (HfsPVolumeHeader)); - priv_data->vh = vh; - - if (vh->signature != PED_CPU_TO_BE16(HFSP_SIGNATURE) - && vh->signature != PED_CPU_TO_BE16(HFSX_SIGNATURE)) { - ped_exception_throw ( - PED_EXCEPTION_BUG, - PED_EXCEPTION_CANCEL, - _("No valid HFS[+X] signature has been found while " - "opening.")); - goto hpo_pg; - } - - if (vh->signature == PED_CPU_TO_BE16(HFSP_SIGNATURE) - && vh->version != PED_CPU_TO_BE16(HFSP_VERSION)) { - if (ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_IGNORE_CANCEL, - _("Version %d of HFS+ isn't supported."), - PED_BE16_TO_CPU(vh->version)) - != PED_EXCEPTION_IGNORE) - goto hpo_pg; - } - - if (vh->signature == PED_CPU_TO_BE16(HFSX_SIGNATURE) - && vh->version != PED_CPU_TO_BE16(HFSX_VERSION)) { - if (ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_IGNORE_CANCEL, - _("Version %d of HFSX isn't supported."), - PED_BE16_TO_CPU(vh->version)) - != PED_EXCEPTION_IGNORE) - goto hpo_pg; - } - - priv_data->jib_start_block = 0; - priv_data->jl_start_block = 0; - if (vh->attributes & PED_CPU_TO_BE32(1<<HFSP_JOURNALED)) { - if (!hfsj_replay_journal(fs)) - goto hpo_pg; - } - - priv_data->bad_blocks_loaded = 0; - priv_data->bad_blocks_xtent_nb = 0; - priv_data->bad_blocks_xtent_list = NULL; - priv_data->extents_file = - hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_XTENT_ID), - vh->extents_file.extents, - PED_BE64_TO_CPU ( - vh->extents_file.logical_size ) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->extents_file) goto hpo_pg; - priv_data->catalog_file = - hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_CATALOG_ID), - vh->catalog_file.extents, - PED_BE64_TO_CPU ( - vh->catalog_file.logical_size ) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->catalog_file) goto hpo_ce; - priv_data->attributes_file = - hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ATTRIB_ID), - vh->attributes_file.extents, - PED_BE64_TO_CPU ( - vh->attributes_file.logical_size) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->attributes_file) goto hpo_cc; - - map_sectors = ( PED_BE32_TO_CPU (vh->total_blocks) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8); - priv_data->dirty_alloc_map = (uint8_t*) - ped_malloc ((map_sectors + 7) / 8); - if (!priv_data->dirty_alloc_map) goto hpo_cl; - memset(priv_data->dirty_alloc_map, 0, (map_sectors + 7) / 8); - priv_data->alloc_map = (uint8_t*) - ped_malloc (map_sectors * PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->alloc_map) goto hpo_dm; - - priv_data->allocation_file = - hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ALLOC_ID), - vh->allocation_file.extents, - PED_BE64_TO_CPU ( - vh->allocation_file.logical_size) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->allocation_file) goto hpo_am; - if (!hfsplus_file_read (priv_data->allocation_file, - priv_data->alloc_map, 0, map_sectors)) { - hfsplus_close(fs); - return NULL; - } - - fs->type = &hfsplus_type; - fs->checked = ((PED_BE32_TO_CPU (vh->attributes) >> HFS_UNMOUNTED) & 1) - && !((PED_BE32_TO_CPU (vh->attributes) >> HFSP_INCONSISTENT) & 1); - - return fs; - -/*--- clean error handling ---*/ -hpo_am: free(priv_data->alloc_map); -hpo_dm: free(priv_data->dirty_alloc_map); -hpo_cl: hfsplus_file_close (priv_data->attributes_file); -hpo_cc: hfsplus_file_close (priv_data->catalog_file); -hpo_ce: hfsplus_file_close (priv_data->extents_file); -hpo_pg: if (priv_data->free_geom) ped_geometry_destroy (priv_data->plus_geom); -hpo_wr: if (priv_data->wrapper) hfs_close(priv_data->wrapper); -hpo_gm: ped_geometry_destroy (fs->geom); -hpo_pd: free(priv_data); -hpo_vh: free(vh); -hpo_fs: free(fs); -hpo: return NULL; -} - -static PedConstraint* -hfsplus_get_resize_constraint (const PedFileSystem *fs) -{ - PedDevice* dev = fs->geom->dev; - PedAlignment start_align; - PedGeometry start_sector; - PedGeometry full_dev; - PedSector min_size; - - if (!ped_alignment_init (&start_align, fs->geom->start, 0)) - return NULL; - if (!ped_geometry_init (&start_sector, dev, fs->geom->start, 1)) - return NULL; - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - - min_size = hfsplus_get_min_size (fs); - if (!min_size) return NULL; - - return ped_constraint_new (&start_align, ped_alignment_any, - &start_sector, &full_dev, min_size, - fs->geom->length); -} - -static int -hfsplus_volume_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - unsigned int nblock, nfree, mblock; - unsigned int block, to_free, old_blocks; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPVolumeHeader* vh = priv_data->vh; - int resize = 1; - unsigned int hfsp_sect_block = - ( PED_BE32_TO_CPU (vh->block_size) - / PED_SECTOR_SIZE_DEFAULT ); - unsigned int map_sectors; - - old_blocks = PED_BE32_TO_CPU (vh->total_blocks); - - /* Flush caches */ - if (!ped_geometry_sync(priv_data->plus_geom)) - return 0; - - /* Clear the unmounted bit */ - /* and set the implementation code (Apple Creator Code) */ - vh->attributes &= PED_CPU_TO_BE32 (~( 1 << HFS_UNMOUNTED )); - vh->last_mounted_version = PED_CPU_TO_BE32(HFSP_IMPL_Shnk); - if (!ped_geometry_read (priv_data->plus_geom, buf, 2, 1)) - return 0; - memcpy (buf, vh, sizeof (HfsPVolumeHeader)); - if ( !ped_geometry_write (priv_data->plus_geom, buf, 2, 1) - || !ped_geometry_sync (priv_data->plus_geom)) - return 0; - - ped_timer_reset (timer); - ped_timer_set_state_name(timer, _("shrinking")); - ped_timer_update(timer, 0.0); - /* relocate data */ - to_free = ( priv_data->plus_geom->length - - geom->length + hfsp_sect_block - - 1 ) / hfsp_sect_block; - block = hfsplus_find_start_pack (fs, to_free); - if (!hfsplus_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_VH; - } - - /* Calculate new block number and other VH field */ - /* nblock must be rounded _down_ */ - nblock = geom->length / hfsp_sect_block; - nfree = PED_BE32_TO_CPU (vh->free_blocks) - - (old_blocks - nblock); - /* free block readjustement is only needed when incorrect nblock - was used by my previous implementation, so detect the case */ - if (priv_data->plus_geom->length < old_blocks - * ( PED_BE32_TO_CPU (vh->block_size) - / PED_SECTOR_SIZE_DEFAULT) ) { - if (priv_data->plus_geom->length % hfsp_sect_block == 1) - nfree++; - } - - /* Check that all block after future end are really free */ - mblock = ( priv_data->plus_geom->length - 2 ) - / hfsp_sect_block; - if (mblock > old_blocks - 1) - mblock = old_blocks - 1; - for ( block = nblock; - block < mblock; - 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 at the end " - "of the volume.")); - goto write_VH; - } - } - - /* Mark out of volume blocks as used */ - map_sectors = ( ( old_blocks + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8) ) - * (PED_SECTOR_SIZE_DEFAULT * 8); - for ( block = nblock; block < map_sectors; ++block) - SET_BLOC_OCCUPATION(priv_data->alloc_map, block); - - /* Update geometry */ - if (resize) { - /* update in fs structure */ - if (PED_BE32_TO_CPU (vh->next_allocation) >= nblock) - vh->next_allocation = PED_CPU_TO_BE32 (0); - vh->total_blocks = PED_CPU_TO_BE32 (nblock); - vh->free_blocks = PED_CPU_TO_BE32 (nfree); - /* update parted structure */ - priv_data->plus_geom->length = geom->length; - priv_data->plus_geom->end = priv_data->plus_geom->start - + geom->length - 1; - } - - /* Effective write */ - write_VH: - /* lasts two sectors are allocated by the alternate VH - and a reserved sector, and last block is always reserved */ - block = (priv_data->plus_geom->length - 1) / hfsp_sect_block; - if (block < PED_BE32_TO_CPU (vh->total_blocks)) - SET_BLOC_OCCUPATION(priv_data->alloc_map, block); - block = (priv_data->plus_geom->length - 2) / hfsp_sect_block; - if (block < PED_BE32_TO_CPU (vh->total_blocks)) - SET_BLOC_OCCUPATION(priv_data->alloc_map, block); - SET_BLOC_OCCUPATION(priv_data->alloc_map, - PED_BE32_TO_CPU (vh->total_blocks) - 1); - - /* Write the _old_ area to set out of volume blocks as used */ - map_sectors = ( old_blocks + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8); - if (!hfsplus_file_write (priv_data->allocation_file, - priv_data->alloc_map, 0, map_sectors)) { - resize = 0; - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Error while writing the allocation file.")); - } else { - /* Write remaining part of allocation bitmap */ - /* This is necessary to handle pre patch-11 and third party */ - /* implementations */ - memset(buf, 0xFF, PED_SECTOR_SIZE_DEFAULT); - for (block = map_sectors; - block < priv_data->allocation_file->sect_nb; - ++block) { - if (!hfsplus_file_write_sector ( - priv_data->allocation_file, - buf, block)) { - ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE, - _("Error while writing the " - "compatibility part of the " - "allocation file.")); - break; - } - } - } - ped_geometry_sync (priv_data->plus_geom); - - if (resize) { - /* Set the unmounted bit and clear the inconsistent bit */ - vh->attributes |= PED_CPU_TO_BE32 ( 1 << HFS_UNMOUNTED ); - vh->attributes &= ~ PED_CPU_TO_BE32 ( 1 << HFSP_INCONSISTENT ); - } - - ped_timer_set_state_name(timer, _("writing HFS+ Volume Header")); - if (!hfsplus_update_vh(fs)) { - ped_geometry_sync(priv_data->plus_geom); - return 0; - } - - if (!ped_geometry_sync(priv_data->plus_geom)) - return 0; - - ped_timer_update(timer, 1.0); - - return (resize); -} - -/* Update the HFS wrapper mdb and bad blocks file to reflect - the new geometry of the embedded HFS+ volume */ -static int -hfsplus_wrapper_update (PedFileSystem* fs) -{ - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsCPrivateLeafRec ref; - HfsExtentKey key; - HfsNodeDescriptor* node_desc = (HfsNodeDescriptor*) node; - HfsExtentKey* ret_key; - HfsExtDescriptor* ret_data; - unsigned int i; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - 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 ; - PedSector hfsplus_sect = (PedSector) - PED_BE32_TO_CPU (priv_data->vh->total_blocks) - * ( PED_BE32_TO_CPU (priv_data->vh->block_size) - / PED_SECTOR_SIZE_DEFAULT ); - unsigned int hfs_blocks_embedded = - (hfsplus_sect + hfs_sect_block - 1) - / hfs_sect_block; - unsigned int hfs_blocks_embedded_old; - - /* update HFS wrapper MDB */ - hfs_blocks_embedded_old = PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new - .embedded.location.block_count ); - hfs_priv_data->mdb->old_new.embedded.location.block_count = - PED_CPU_TO_BE16 (hfs_blocks_embedded); - /* maybe macOS will boot with this */ - /* update : yes it does \o/ :) */ - hfs_priv_data->mdb->free_blocks = - PED_CPU_TO_BE16 ( PED_BE16_TO_CPU (hfs_priv_data->mdb->free_blocks) - + hfs_blocks_embedded_old - - hfs_blocks_embedded ); - - if (!hfs_update_mdb(priv_data->wrapper)) - return 0; - - /* force reload bad block list */ - if (hfs_priv_data->bad_blocks_loaded) { - hfs_free_bad_blocks_list (hfs_priv_data->bad_blocks_xtent_list); - hfs_priv_data->bad_blocks_xtent_list = NULL; - hfs_priv_data->bad_blocks_xtent_nb = 0; - hfs_priv_data->bad_blocks_loaded = 0; - } - - /* clean HFS wrapper allocation map */ - for (i = PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new.embedded - .location.start_block ) - + hfs_blocks_embedded; - i < PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new.embedded - .location.start_block ) - + hfs_blocks_embedded_old; - i++ ) { - CLR_BLOC_OCCUPATION(hfs_priv_data->alloc_map, i); - } - /* and save it */ - if (!ped_geometry_write (fs->geom, hfs_priv_data->alloc_map, - PED_BE16_TO_CPU ( - hfs_priv_data->mdb->volume_bitmap_block ), - ( PED_BE16_TO_CPU ( - hfs_priv_data->mdb->total_blocks ) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8))) - return 0; - if (!ped_geometry_sync (fs->geom)) - return 0; - - /* search and update the bad blocks file */ - key.key_length = sizeof(key) - 1; - key.type = HFS_DATA_FORK; - key.file_ID = PED_CPU_TO_BE32 (HFS_BAD_BLOCK_ID); - key.start = 0; - if (!hfs_btree_search (hfs_priv_data->extent_file, - (HfsPrivateGenericKey*) &key, NULL, 0, &ref)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("An error occurred while looking for the mandatory " - "bad blocks file.")); - return 0; - } - if (!hfs_file_read_sector (hfs_priv_data->extent_file, node, - ref.node_number)) - return 0; - ret_key = (HfsExtentKey*) (node + ref.record_pos); - ret_data = (HfsExtDescriptor*) ( node + ref.record_pos - + sizeof (HfsExtentKey) ); - - while (ret_key->type == key.type && ret_key->file_ID == key.file_ID) { - for (i = 0; i < HFS_EXT_NB; i++) { - if ( ret_data[i].start_block - == hfs_priv_data->mdb->old_new - .embedded.location.start_block) { - ret_data[i].block_count = - hfs_priv_data->mdb->old_new - .embedded.location.block_count; - /* found ! : update */ - if (!hfs_file_write_sector ( - hfs_priv_data->extent_file, - node, ref.node_number) - || !ped_geometry_sync(fs->geom)) - return 0; - return 1; - } - } - - if (ref.record_number < PED_BE16_TO_CPU (node_desc->rec_nb)) { - ref.record_number++; - } else { - ref.node_number = PED_BE32_TO_CPU (node_desc->next); - if (!ref.node_number - || !hfs_file_read_sector(hfs_priv_data->extent_file, - node, ref.node_number)) - goto bb_not_found; - ref.record_number = 1; - } - - ref.record_pos = - PED_BE16_TO_CPU (*((uint16_t *) - (node + (PED_SECTOR_SIZE_DEFAULT - - 2*ref.record_number)))); - ret_key = (HfsExtentKey*) (node + ref.record_pos); - ret_data = (HfsExtDescriptor*) ( node + ref.record_pos - + sizeof (HfsExtentKey) ); - } - -bb_not_found: - /* not found : not a valid hfs+ wrapper : failure */ - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("It seems there is an error in the HFS wrapper: the bad " - "blocks file doesn't contain the embedded HFS+ volume.")); - return 0; -} - -static 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; -} - -#ifdef HFS_EXTRACT_FS -/* The following is for debugging purpose only, NOT for packaging */ - -#include <stdio.h> - -uint8_t* extract_buffer = NULL; - -static int -hfs_extract_file(const char* filename, HfsPrivateFile* hfs_file) -{ - FILE* fout; - PedSector sect; - - fout = fopen(filename, "w"); - if (!fout) return 0; - - for (sect = 0; sect < hfs_file->sect_nb; ++sect) { - if (!hfs_file_read_sector(hfs_file, extract_buffer, sect)) - goto err_close; - if (!fwrite(extract_buffer, PED_SECTOR_SIZE_DEFAULT, 1, fout)) - goto err_close; - } - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -static int -hfs_extract_bitmap(const char* filename, PedFileSystem* fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsMasterDirectoryBlock* mdb = priv_data->mdb; - unsigned int count; - FILE* fout; - PedSector sect; - - fout = fopen(filename, "w"); - if (!fout) return 0; - - for (sect = PED_BE16_TO_CPU(mdb->volume_bitmap_block); - sect < PED_BE16_TO_CPU(mdb->start_block); - sect += count) { - uint16_t st_block = PED_BE16_TO_CPU(mdb->start_block); - count = (st_block-sect) < BLOCK_MAX_BUFF ? - (st_block-sect) : BLOCK_MAX_BUFF; - if (!ped_geometry_read(fs->geom, extract_buffer, sect, count)) - goto err_close; - if (!fwrite (extract_buffer, count * PED_SECTOR_SIZE_DEFAULT, - 1, fout)) - goto err_close; - } - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -static int -hfs_extract_mdb (const char* filename, PedFileSystem* fs) -{ - FILE* fout; - - fout = fopen(filename, "w"); - if (!fout) return 0; - - if (!ped_geometry_read(fs->geom, extract_buffer, 2, 1)) - goto err_close; - if (!fwrite(extract_buffer, PED_SECTOR_SIZE_DEFAULT, 1, fout)) - goto err_close; - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -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 -hfsplus_extract_file(const char* filename, HfsPPrivateFile* hfsp_file) -{ - FILE* fout; - unsigned int cp_sect; - PedSector rem_sect; - - fout = fopen(filename, "w"); - if (!fout) return 0; - - for (rem_sect = hfsp_file->sect_nb; rem_sect; rem_sect -= cp_sect) { - cp_sect = rem_sect < BLOCK_MAX_BUFF ? rem_sect : BLOCK_MAX_BUFF; - if (!hfsplus_file_read(hfsp_file, extract_buffer, - hfsp_file->sect_nb - rem_sect, cp_sect)) - goto err_close; - if (!fwrite (extract_buffer, cp_sect * PED_SECTOR_SIZE_DEFAULT, - 1, fout)) - goto err_close; - } - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -static int -hfsplus_extract_vh (const char* filename, PedFileSystem* fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - FILE* fout; - PedGeometry* geom = priv_data->plus_geom; - - - fout = fopen(filename, "w"); - if (!fout) return 0; - - if (!ped_geometry_read(geom, extract_buffer, 2, 1)) - goto err_close; - if (!fwrite(extract_buffer, PED_SECTOR_SIZE_DEFAULT, 1, fout)) - goto err_close; - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -/* TODO : use the timer to report what is happening */ -/* 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 ! */ -} -#endif /* HFS_EXTRACT_FS */ - -#endif /* !DISCOVER_ONLY */ - static PedFileSystemOps hfs_ops = { probe: hfs_probe, }; diff --git a/libparted/fs/hfs/journal.c b/libparted/fs/hfs/journal.c deleted file mode 100644 index 6e5c267..0000000 --- a/libparted/fs/hfs/journal.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef DISCOVER_ONLY - -#include <config.h> - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> -#include <stdint.h> - -#if ENABLE_NLS -# include <libintl.h> -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "reloc_plus.h" - -#include "journal.h" - -static int hfsj_vh_replayed = 0; -static int is_le = 0; - -static uint32_t -hfsj_calc_checksum(uint8_t *ptr, int len) -{ - int i; - uint32_t cksum=0; - - for (i=0; i < len; i++, ptr++) { - cksum = (cksum << 8) ^ (cksum + *ptr); - } - - return (~cksum); -} - -int -hfsj_update_jib(PedFileSystem* fs, uint32_t block) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - - priv_data->vh->journal_info_block = PED_CPU_TO_BE32(block); - - if (!hfsplus_update_vh (fs)) - return 0; - - priv_data->jib_start_block = block; - return 1; -} - -int -hfsj_update_jl(PedFileSystem* fs, uint32_t block) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - PedSector sector; - uint64_t offset; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsJJournalInfoBlock* jib; - int binsect; - - binsect = HFS_32_TO_CPU(priv_data->vh->block_size, is_le) / PED_SECTOR_SIZE_DEFAULT; - sector = (PedSector) priv_data->jib_start_block * binsect; - if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) - return 0; - jib = (HfsJJournalInfoBlock*) buf; - - offset = (uint64_t)block * PED_SECTOR_SIZE_DEFAULT * binsect; - jib->offset = HFS_CPU_TO_64(offset, is_le); - - if (!ped_geometry_write(priv_data->plus_geom, buf, sector, 1) - || !ped_geometry_sync(priv_data->plus_geom)) - return 0; - - priv_data->jl_start_block = block; - return 1; -} - -/* Return the sector in the journal that is after the area read */ -/* or 0 on error */ -static PedSector -hfsj_journal_read(PedGeometry* geom, HfsJJournalHeader* jh, - PedSector journ_sect, PedSector journ_length, - PedSector read_sect, unsigned int nb_sect, - void* buf) -{ - int r; - - while (nb_sect--) { - r = ped_geometry_read(geom, buf, journ_sect + read_sect, 1); - if (!r) return 0; - - buf = ((uint8_t*)buf) + PED_SECTOR_SIZE_DEFAULT; - read_sect++; - if (read_sect == journ_length) - read_sect = 1; /* skip journal header - which is asserted to be - 1 sector long */ - } - - return read_sect; -} - -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; -} - -/* 0 => Failure, don't continue to open ! */ -/* 1 => Success, the journal has been completly replayed, or don't need to */ -int -hfsj_replay_journal(PedFileSystem* fs) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - PedSector sector, length; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsJJournalInfoBlock* jib; - HfsJJournalHeader* jh; - int binsect; - uint32_t cksum; - - binsect = PED_BE32_TO_CPU(priv_data->vh->block_size) / PED_SECTOR_SIZE_DEFAULT; - priv_data->jib_start_block = - PED_BE32_TO_CPU(priv_data->vh->journal_info_block); - sector = (PedSector) priv_data->jib_start_block * binsect; - if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) - return 0; - jib = (HfsJJournalInfoBlock*) buf; - - if ( (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_IN_FS)) - && !(jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_OTHER_DEV)) ) { - priv_data->jl_start_block = HFS_64_TO_CPU(jib->offset, is_le) - / ( PED_SECTOR_SIZE_DEFAULT * binsect ); - } - - if (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_NEED_INIT)) - return 1; - - if ( !(jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_IN_FS)) - || (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_OTHER_DEV)) ) { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Journal stored outside of the volume are " - "not supported. Try to desactivate the " - "journal and run Parted again.")); - return 0; - } - - if ( (PED_BE64_TO_CPU(jib->offset) % PED_SECTOR_SIZE_DEFAULT) - || (PED_BE64_TO_CPU(jib->size) % PED_SECTOR_SIZE_DEFAULT) ) { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Journal offset or size is not multiple of " - "the sector size.")); - return 0; - } - - sector = PED_BE64_TO_CPU(jib->offset) / PED_SECTOR_SIZE_DEFAULT; - length = PED_BE64_TO_CPU(jib->size) / PED_SECTOR_SIZE_DEFAULT; - - jib = NULL; - if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) - return 0; - jh = (HfsJJournalHeader*) buf; - - if (jh->endian == PED_LE32_TO_CPU(HFSJ_ENDIAN_MAGIC)) - is_le = 1; - - if ( (jh->magic != HFS_32_TO_CPU(HFSJ_HEADER_MAGIC, is_le)) - || (jh->endian != HFS_32_TO_CPU(HFSJ_ENDIAN_MAGIC, is_le)) ) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Incorrect magic values in the journal header.")); - return 0; - } - - if ( (HFS_64_TO_CPU(jh->size, is_le)%PED_SECTOR_SIZE_DEFAULT) - || (HFS_64_TO_CPU(jh->size, is_le)/PED_SECTOR_SIZE_DEFAULT - != (uint64_t)length) ) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Journal size mismatch between journal info block " - "and journal header.")); - return 0; - } - - if ( (HFS_64_TO_CPU(jh->start, is_le) % PED_SECTOR_SIZE_DEFAULT) - || (HFS_64_TO_CPU(jh->end, is_le) % PED_SECTOR_SIZE_DEFAULT) - || (HFS_32_TO_CPU(jh->blhdr_size, is_le) % PED_SECTOR_SIZE_DEFAULT) - || (HFS_32_TO_CPU(jh->jhdr_size, is_le) % PED_SECTOR_SIZE_DEFAULT) ) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Some header fields are not multiple of the sector " - "size.")); - return 0; - } - - if (HFS_32_TO_CPU(jh->jhdr_size, is_le) != PED_SECTOR_SIZE_DEFAULT) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The sector size stored in the journal is not 512 " - "bytes. Parted only supports 512 bytes length " - "sectors.")); - return 0; - } - - cksum = HFS_32_TO_CPU(jh->checksum, is_le); - jh->checksum = 0; - if (cksum != hfsj_calc_checksum((uint8_t*)jh, sizeof(*jh))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Bad journal checksum.")); - return 0; - } - jh->checksum = HFS_CPU_TO_32(cksum, is_le); - - /* The 2 following test are in the XNU Darwin source code */ - /* so I assume they're needed */ - if (jh->start == jh->size) - jh->start = HFS_CPU_TO_64(PED_SECTOR_SIZE_DEFAULT, is_le); - if (jh->end == jh->size) - jh->start = HFS_CPU_TO_64(PED_SECTOR_SIZE_DEFAULT, is_le); - - if (jh->start == jh->end) - return 1; - - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL, - _("The journal is not empty. Parted must replay the " - "transactions before opening the file system. This will " - "modify the file system.")) - != PED_EXCEPTION_FIX) - return 0; - - while (jh->start != jh->end) { - /* Replay one complete transaction */ - if (!hfsj_replay_transaction(fs, jh, sector, length)) - return 0; - - /* Recalculate cksum of the journal header */ - jh->checksum = 0; /* need to be 0 while calculating the cksum */ - cksum = hfsj_calc_checksum((uint8_t*)jh, sizeof(*jh)); - jh->checksum = HFS_CPU_TO_32(cksum, is_le); - - /* Update the Journal Header */ - if (!ped_geometry_write(priv_data->plus_geom, buf, sector, 1) - || !ped_geometry_sync(priv_data->plus_geom)) - return 0; - } - - if (hfsj_vh_replayed) { - /* probe could have reported incorrect info ! */ - /* is there a way to ask parted to quit ? */ - ped_exception_throw( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_OK, - _("The volume header or the master directory block has " - "changed while replaying the journal. You should " - "restart Parted.")); - return 0; - } - - return 1; -} - -#endif /* DISCOVER_ONLY */ diff --git a/libparted/fs/hfs/journal.h b/libparted/fs/hfs/journal.h deleted file mode 100644 index 4a40e02..0000000 --- a/libparted/fs/hfs/journal.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _JOURNAL_H -#define _JOURNAL_H - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> - -#include "hfs.h" - -int -hfsj_replay_journal(PedFileSystem* fs); - -int -hfsj_update_jib(PedFileSystem* fs, uint32_t block); - -int -hfsj_update_jl(PedFileSystem* fs, uint32_t block); - -#define HFS_16_TO_CPU(x, is_little_endian) ((is_little_endian) ? (uint16_t)PED_LE16_TO_CPU(x) : (uint16_t)PED_BE16_TO_CPU(x)) -#define HFS_32_TO_CPU(x, is_little_endian) ((is_little_endian) ? (uint32_t)PED_LE32_TO_CPU(x) : (uint32_t)PED_BE32_TO_CPU(x)) -#define HFS_64_TO_CPU(x, is_little_endian) ((is_little_endian) ? (uint64_t)PED_LE64_TO_CPU(x) : (uint64_t)PED_BE64_TO_CPU(x)) -#define HFS_CPU_TO_16(x, is_little_endian) ((is_little_endian) ? (uint16_t)PED_CPU_TO_LE16(x) : (uint16_t)PED_CPU_TO_BE16(x)) -#define HFS_CPU_TO_32(x, is_little_endian) ((is_little_endian) ? (uint32_t)PED_CPU_TO_LE32(x) : (uint32_t)PED_CPU_TO_BE32(x)) -#define HFS_CPU_TO_64(x, is_little_endian) ((is_little_endian) ? (uint64_t)PED_CPU_TO_LE64(x) : (uint64_t)PED_CPU_TO_BE64(x)) - -#endif /* _JOURNAL_H */ diff --git a/libparted/fs/hfs/reloc.c b/libparted/fs/hfs/reloc.c deleted file mode 100644 index 81d1057..0000000 --- a/libparted/fs/hfs/reloc.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef DISCOVER_ONLY - -#include <config.h> - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> -#include <stdint.h> - -#if ENABLE_NLS -# include <libintl.h> -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "file.h" -#include "advfs.h" -#include "cache.h" - -#include "reloc.h" - -/* This function moves data of size blocks starting - at block *ptr_fblock to block *ptr_to_fblock */ -/* return new start or -1 on failure */ -static int -hfs_effect_move_extent (PedFileSystem *fs, unsigned int *ptr_fblock, - unsigned int *ptr_to_fblock, unsigned int size) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - unsigned int i, ok = 0; - unsigned int next_to_fblock; - unsigned int start, stop; - - PED_ASSERT (hfs_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_BE16_TO_CPU(priv_data->mdb->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 */ - unsigned int j; - unsigned int start_block = - PED_BE16_TO_CPU (priv_data->mdb->start_block ); - unsigned int block_sz = - (PED_BE32_TO_CPU (priv_data->mdb->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*/) { - PedSector abs_sector; - unsigned int ai; - - j = size - i; j = (j < hfs_block_count) ? - j : hfs_block_count ; - - abs_sector = start_block - + (PedSector) (*ptr_fblock + i) * block_sz; - if (!ped_geometry_read (fs->geom, hfs_block, abs_sector, - block_sz * j)) - return -1; - - abs_sector = start_block - + (PedSector) (start + i) * block_sz; - if (!ped_geometry_write (fs->geom,hfs_block,abs_sector, - block_sz * j)) - return -1; - - for (ai = i+j; i < ai; i++) { - /* free source block */ - CLR_BLOC_OCCUPATION(priv_data->alloc_map, - *ptr_fblock + i); - - /* set dest block */ - SET_BLOC_OCCUPATION(priv_data->alloc_map, - start + i); - } - } - if (!ped_geometry_sync_fast (fs->geom)) - return -1; - - *ptr_fblock += size; - *ptr_to_fblock = next_to_fblock; - } else { - if (*ptr_fblock != *ptr_to_fblock) - /* not enough room, but try to continue */ - 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; -} - -/* Update MDB */ -/* Return 0 if an error occurred */ -/* Return 1 if everything ok */ -int -hfs_update_mdb (PedFileSystem *fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - - if (!ped_geometry_read (fs->geom, node, 2, 1)) - return 0; - memcpy (node, priv_data->mdb, sizeof (HfsMasterDirectoryBlock)); - if ( !ped_geometry_write (fs->geom, node, 2, 1) - || !ped_geometry_write (fs->geom, node, fs->geom->length - 2, 1) - || !ped_geometry_sync_fast (fs->geom)) - return 0; - return 1; -} - -/* Generic relocator */ -/* replace previous hfs_do_move_* */ -static int -hfs_do_move (PedFileSystem* fs, unsigned int *ptr_src, - unsigned int *ptr_dest, HfsCPrivateCache* cache, - HfsCPrivateExtent* ref) -{ - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsPrivateFile* file; - HfsExtDescriptor* extent; - HfsCPrivateExtent* move; - int new_start; - - new_start = hfs_effect_move_extent (fs, ptr_src, ptr_dest, - ref->ext_length); - if (new_start == -1) return -1; - - if (ref->ext_start != (unsigned) new_start) { - /* Load, modify & save */ - switch (ref->where) { - /******** MDB *********/ - case CR_PRIM_CAT : - priv_data->catalog_file - ->first[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - goto CR_PRIM; - case CR_PRIM_EXT : - priv_data->extent_file - ->first[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - CR_PRIM : - extent = ( HfsExtDescriptor* ) - ( (uint8_t*)priv_data->mdb + ref->ref_offset ); - extent[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - if (!hfs_update_mdb(fs)) return -1; - break; - - /********* BTREE *******/ - case CR_BTREE_EXT_CAT : - if (priv_data->catalog_file - ->cache[ref->ref_index].start_block - == PED_CPU_TO_BE16(ref->ext_start)) - priv_data->catalog_file - ->cache[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - case CR_BTREE_EXT_0 : - file = priv_data->extent_file; - goto CR_BTREE; - case CR_BTREE_CAT : - file = priv_data->catalog_file; - CR_BTREE: - PED_ASSERT(ref->sect_by_block == 1 - && ref->ref_offset < PED_SECTOR_SIZE_DEFAULT); - if (!hfs_file_read_sector(file, node, ref->ref_block)) - return -1; - extent = ( HfsExtDescriptor* ) (node + ref->ref_offset); - extent[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - if (!hfs_file_write_sector(file, node, ref->ref_block) - || !ped_geometry_sync_fast (fs->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; - } - - /* Update the cache */ - move = hfsc_cache_move_extent(cache, ref->ext_start, new_start); - if (!move) return -1; /* "cleanly" fail */ - PED_ASSERT(move == ref); /* generate a bug */ - } - - return new_start; -} - -/* 0 error, 1 ok */ -static int -hfs_save_allocation(PedFileSystem* fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - unsigned int map_sectors; - - map_sectors = ( PED_BE16_TO_CPU (priv_data->mdb->total_blocks) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8); - return ( ped_geometry_write (fs->geom, priv_data->alloc_map, - PED_BE16_TO_CPU (priv_data->mdb->volume_bitmap_block), - map_sectors) ); -} - -/* This function moves an extent starting at block fblock to block to_fblock - if there's enough room */ -/* Return 1 if everything was fine */ -/* Return -1 if an error occurred */ -/* Return 0 if no extent was found */ -/* Generic search thanks to the file system cache */ -static int -hfs_move_extent_starting_at (PedFileSystem *fs, unsigned int *ptr_fblock, - unsigned int *ptr_to_fblock, - HfsCPrivateCache* cache) -{ - HfsCPrivateExtent* ref; - unsigned int old_start, new_start; - - /* Reference search powered by the cache... */ - /* This is the optimisation secret :) */ - ref = hfsc_cache_search_extent(cache, *ptr_fblock); - if (!ref) return 0; /* not found */ - - old_start = *ptr_fblock; - new_start = hfs_do_move(fs, ptr_fblock, ptr_to_fblock, cache, ref); - if (new_start == (unsigned int) -1) return -1; - if (new_start > old_start) { /* detect 2 pass reloc */ - new_start = hfs_do_move(fs,&new_start,ptr_to_fblock,cache,ref); - if (new_start == (unsigned int) -1 || new_start > old_start) - return -1; - } - - /* allocation bitmap save is not atomic with data relocation */ - /* so we only do it a few times, and without syncing */ - /* The unmounted bit protect us anyway */ - hfs_save_allocation(fs); - return 1; -} - -static int -hfs_cache_from_mdb(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsExtDescriptor* extent; - unsigned int j; - - extent = priv_data->mdb->extents_file_rec; - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - 0, /* unused for mdb */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->mdb), - 1, /* load/save only 1 sector */ - CR_PRIM_EXT, - j ) - ) - return 0; - } - - extent = priv_data->mdb->catalog_file_rec; - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - 0, - ((uint8_t*)extent) - ((uint8_t*)priv_data->mdb), - 1, - CR_PRIM_CAT, - j ) - ) - return 0; - } - - return 1; -} - -static int -hfs_cache_from_catalog(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsHeaderRecord* header; - HfsNodeDescriptor* desc = (HfsNodeDescriptor*) node; - HfsCatalogKey* catalog_key; - HfsCatalog* catalog_data; - HfsExtDescriptor* extent; - unsigned int leaf_node, record_number; - unsigned int i, j; - - if (!priv_data->catalog_file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - _("This HFS volume has no catalog file. " - "This is very unusual!")); - return 1; - } - - if (!hfs_file_read_sector (priv_data->catalog_file, node, 0)) - return 0; - header = (HfsHeaderRecord*)(node + PED_BE16_TO_CPU(*((uint16_t*) - (node+(PED_SECTOR_SIZE_DEFAULT-2))))); - - for (leaf_node = PED_BE32_TO_CPU (header->first_leaf_node); - leaf_node; - leaf_node = PED_BE32_TO_CPU (desc->next)) { - if (!hfs_file_read_sector (priv_data->catalog_file, - node, leaf_node)) - return 0; - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = 1; i <= record_number; ++i) { - /* undocumented alignement */ - unsigned int skip; - catalog_key = (HfsCatalogKey*) (node + PED_BE16_TO_CPU( - *((uint16_t*)(node+(PED_SECTOR_SIZE_DEFAULT - 2*i))))); - skip = (1 + catalog_key->key_length + 1) & ~1; - catalog_data = (HfsCatalog*)( ((uint8_t*)catalog_key) - + skip ); - /* check for obvious error in FS */ - if (((uint8_t*)catalog_key - node < HFS_FIRST_REC) - || ((uint8_t*)catalog_data - node - >= PED_SECTOR_SIZE_DEFAULT - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - return 0; - } - - if (catalog_data->type != HFS_CAT_FILE) continue; - - extent = catalog_data->sel.file.extents_data; - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - leaf_node, - (uint8_t*)extent - node, - 1, /* hfs => btree block = 512 b */ - CR_BTREE_CAT, - j ) - ) - return 0; - } - - extent = catalog_data->sel.file.extents_res; - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - leaf_node, - (uint8_t*)extent - node, - 1, /* hfs => btree block = 512 b */ - CR_BTREE_CAT, - j ) - ) - return 0; - } - } - } - - return 1; -} - -static int -hfs_cache_from_extent(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsHeaderRecord* header; - HfsNodeDescriptor* desc = (HfsNodeDescriptor*) node; - HfsExtentKey* extent_key; - HfsExtDescriptor* extent; - unsigned int leaf_node, record_number; - unsigned int i, j; - - if (!priv_data->extent_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 (!hfs_file_read_sector (priv_data->extent_file, node, 0)) - return 0; - header = ((HfsHeaderRecord*) (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(PED_SECTOR_SIZE_DEFAULT-2)))))); - - for (leaf_node = PED_BE32_TO_CPU (header->first_leaf_node); - leaf_node; - leaf_node = PED_BE32_TO_CPU (desc->next)) { - if (!hfs_file_read_sector (priv_data->extent_file, node, - leaf_node)) - return 0; - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = 1; i <= record_number; i++) { - uint8_t where; - extent_key = (HfsExtentKey*) - (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(PED_SECTOR_SIZE_DEFAULT - 2*i))))); - /* size is cst */ - extent = (HfsExtDescriptor*)(((uint8_t*)extent_key) - + sizeof (HfsExtentKey)); - /* check for obvious error in FS */ - if (((uint8_t*)extent_key - node < HFS_FIRST_REC) - || ((uint8_t*)extent - node - >= PED_SECTOR_SIZE_DEFAULT - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - return 0; - } - - 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; - default : - where = CR_BTREE_EXT_0; - break; - } - - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - leaf_node, - (uint8_t*)extent - node, - 1, /* hfs => btree block = 512 b */ - where, - j ) - ) - return 0; - } - } - } - - return 1; -} - -/* This function cache every extents start and length stored in any - fs structure into the adt defined in cache.[ch] - Returns NULL on failure */ -static HfsCPrivateCache* -hfs_cache_extents(PedFileSystem *fs, PedTimer* timer) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsCPrivateCache* ret; - unsigned int file_number, block_number; - - file_number = PED_BE32_TO_CPU(priv_data->mdb->file_count); - block_number = PED_BE16_TO_CPU(priv_data->mdb->total_blocks); - ret = hfsc_new_cache(block_number, file_number); - if (!ret) return NULL; - - if (!hfs_cache_from_mdb(ret, fs, timer) || - !hfs_cache_from_catalog(ret, fs, timer) || - !hfs_cache_from_extent(ret, fs, timer)) { - ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not cache the file system in memory.")); - hfsc_delete_cache(ret); - return NULL; - } - - return ret; -} - -/* This function moves file's data to compact used and free space, - starting at fblock block */ -/* return 0 on error */ -int -hfs_pack_free_space_from_block (PedFileSystem *fs, unsigned int fblock, - PedTimer* timer, unsigned int to_free) -{ - PedSector bytes_buff; - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsMasterDirectoryBlock* mdb = priv_data->mdb; - HfsCPrivateCache* cache; - unsigned int to_fblock = fblock; - unsigned int start = fblock; - unsigned int divisor = PED_BE16_TO_CPU (mdb->total_blocks) - + 1 - start - to_free; - int ret; - - PED_ASSERT (!hfs_block); - - cache = hfs_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->mdb->block_size) - * (PedSector) BLOCK_MAX_BUFF; - if (bytes_buff > BYTES_MAX_BUFF) { - hfs_block_count = BYTES_MAX_BUFF - / PED_BE32_TO_CPU (priv_data->mdb->block_size); - if (!hfs_block_count) - hfs_block_count = 1; - bytes_buff = (PedSector) hfs_block_count - * PED_BE32_TO_CPU (priv_data->mdb->block_size); - } else - hfs_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); - - hfs_block = (uint8_t*) ped_malloc (bytes_buff); - if (!hfs_block) - goto error_cache; - - if (!hfs_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 < PED_BE16_TO_CPU (mdb->total_blocks)) { - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,fblock) - && (!hfs_is_bad_block (fs, fblock))) { - if (!(ret = hfs_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 (hfs_block); hfs_block = NULL; hfs_block_count = 0; - hfsc_delete_cache (cache); - return 1; - -error_alloc: - free (hfs_block); hfs_block = NULL; hfs_block_count = 0; -error_cache: - hfsc_delete_cache (cache); - return 0; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/libparted/fs/hfs/reloc.h b/libparted/fs/hfs/reloc.h deleted file mode 100644 index 536c071..0000000 --- a/libparted/fs/hfs/reloc.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _RELOC_H -#define _RELOC_H - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> - -#include "hfs.h" - -int -hfs_update_mdb (PedFileSystem *fs); - -int -hfs_pack_free_space_from_block (PedFileSystem *fs, unsigned int fblock, - PedTimer* timer, unsigned int to_free); - -#endif /* _RELOC_H */ diff --git a/libparted/fs/hfs/reloc_plus.c b/libparted/fs/hfs/reloc_plus.c deleted file mode 100644 index 750927f..0000000 --- a/libparted/fs/hfs/reloc_plus.c +++ /dev/null @@ -1,942 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004-2005, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef DISCOVER_ONLY - -#include <config.h> - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> -#include <stdint.h> - -#if ENABLE_NLS -# include <libintl.h> -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "file_plus.h" -#include "advfs_plus.h" -#include "cache.h" -#include "journal.h" - -#include "reloc_plus.h" - -/* This function moves data of size blocks starting at block *ptr_fblock - to block *ptr_to_fblock */ -/* return new start or -1 on failure */ -/* -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; -} - -/* Returns 0 on error */ -/* 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; -} - -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; -} - -/* save any dirty sector of the allocation bitmap file */ -static int -hfsplus_save_allocation(PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - unsigned int map_sectors, i, j; - int ret = 1; - - map_sectors = ( PED_BE32_TO_CPU (priv_data->vh->total_blocks) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8); - - for (i = 0; i < map_sectors;) { - for (j = i; - (TST_BLOC_OCCUPATION(priv_data->dirty_alloc_map,j)); - ++j) - CLR_BLOC_OCCUPATION(priv_data->dirty_alloc_map,j); - if (j-i) { - ret = hfsplus_file_write(priv_data->allocation_file, - priv_data->alloc_map + i * PED_SECTOR_SIZE_DEFAULT, - i, j-i) && ret; - i = j; - } else - ++i; - } - - return ret; -} - -/* This function moves an extent starting at block fblock - to block to_fblock if there's enough room */ -/* Return 1 if everything was fine */ -/* Return -1 if an error occurred */ -/* Return 0 if no extent was found */ -static int -hfsplus_move_extent_starting_at (PedFileSystem *fs, unsigned int *ptr_fblock, - unsigned int *ptr_to_fblock, - HfsCPrivateCache* cache) -{ - HfsCPrivateExtent* ref; - unsigned int old_start, new_start; - - ref = hfsc_cache_search_extent(cache, *ptr_fblock); - if (!ref) return 0; - - old_start = *ptr_fblock; - new_start = hfsplus_do_move(fs, ptr_fblock, ptr_to_fblock, cache, ref); - if (new_start == (unsigned)-1) return -1; - if (new_start > old_start) { - new_start = hfsplus_do_move(fs, &new_start, ptr_to_fblock, - cache, ref); - if (new_start == (unsigned)-1 || new_start > old_start) - return -1; - } - - hfsplus_save_allocation(fs); - return 1; -} - -static int -hfsplus_cache_from_vh(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPExtDescriptor* extent; - unsigned int j; - - extent = priv_data->vh->allocation_file.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), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_ALLOC, - j ) - ) - return 0; - } - - extent = priv_data->vh->extents_file.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), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_EXT, - j ) - ) - return 0; - } - - extent = priv_data->vh->catalog_file.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), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_CAT, - j ) - ) - return 0; - } - - extent = priv_data->vh->attributes_file.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), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_ATTR, - j ) - ) - return 0; - } - - extent = priv_data->vh->startup_file.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), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_START, - j ) - ) - return 0; - } - - return 1; -} - -static int -hfsplus_cache_from_catalog(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; - HfsPCatalogKey* catalog_key; - HfsPCatalog* catalog_data; - HfsPExtDescriptor* extent; - unsigned int leaf_node, record_number; - unsigned int i, j, size, bsize; - uint32_t jib = priv_data->jib_start_block, - jl = priv_data->jl_start_block; - - if (!priv_data->catalog_file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - _("This HFS+ volume has no catalog file. " - "This is very unusual!")); - return 1; - } - - /* Search the extent starting at *ptr_block in the catalog file */ - if (!hfsplus_file_read_sector (priv_data->catalog_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->catalog_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; - uint8_t where; - - catalog_key = (HfsPCatalogKey*) - ( node + PED_BE16_TO_CPU (*((uint16_t *) - (node+(bsize - 2*i)))) ); - skip = ( 2 + PED_BE16_TO_CPU (catalog_key->key_length) - + 1) & ~1; - catalog_data = (HfsPCatalog*) - (((uint8_t*)catalog_key) + skip); - /* check for obvious error in FS */ - if (((uint8_t*)catalog_key - node < HFS_FIRST_REC) - || ((uint8_t*)catalog_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 (PED_BE16_TO_CPU(catalog_data->type)!=HFS_CAT_FILE) - continue; - - extent = catalog_data->sel.file.data_fork.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - where = CR_BTREE_CAT; - if ( PED_BE32_TO_CPU(extent[j].start_block) - == jib ) { - jib = 0; - where = CR_BTREE_CAT_JIB; - } else - if ( PED_BE32_TO_CPU(extent[j].start_block) - == jl ) { - jl = 0; - where = CR_BTREE_CAT_JL; - } - 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; - } - } - - extent = catalog_data->sel.file.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_CAT, - j ) - ) { - free (node); - return 0; - } - } - } - } - - 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; -} - -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 HfsCPrivateCache* -hfsplus_cache_extents(PedFileSystem* fs, PedTimer* timer) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsCPrivateCache* ret; - unsigned int file_number, block_number; - - file_number = PED_BE32_TO_CPU(priv_data->vh->file_count); - block_number = PED_BE32_TO_CPU(priv_data->vh->total_blocks); - ret = hfsc_new_cache(block_number, file_number); - if (!ret) return NULL; - - if (!hfsplus_cache_from_vh(ret, fs, timer) || - !hfsplus_cache_from_catalog(ret, fs, timer) || - !hfsplus_cache_from_extent(ret, fs, timer) || - !hfsplus_cache_from_attributes(ret, fs, timer)) { - ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not cache the file system in memory.")); - hfsc_delete_cache(ret); - return NULL; - } - - return ret; -} - -/* This function moves file's data to compact used and free space, - starting at fblock block */ -/* 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; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/libparted/fs/hfs/reloc_plus.h b/libparted/fs/hfs/reloc_plus.h deleted file mode 100644 index 2b2e12c..0000000 --- a/libparted/fs/hfs/reloc_plus.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007, 2009-2011 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _RELOC_PLUS_H -#define _RELOC_PLUS_H - -#include <parted/parted.h> -#include <parted/endian.h> -#include <parted/debug.h> - -#include "hfs.h" - -int -hfsplus_update_vh (PedFileSystem *fs); - -int -hfsplus_pack_free_space_from_block (PedFileSystem *fs, unsigned int fblock, - PedTimer* timer, unsigned int to_free); - - -#endif /* _RELOC_PLUS_H */ |