Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}