Example #1
0
/* 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) );
}
Example #2
0
File: hfs.c Project: Excito/parted
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;
}
Example #3
0
File: hfs.c Project: Excito/parted
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 );
}
/* 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;
}
Example #5
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;
}
Example #6
0
/* Used by hfsplus_probe and hfs_probe */
PedGeometry*
hfs_and_wrapper_probe (PedGeometry* geom)
{
	uint8_t		buf[PED_SECTOR_SIZE_DEFAULT];
	HfsMasterDirectoryBlock	*mdb;
	PedGeometry*	geom_ret;
	PedSector	search, max;

	PED_ASSERT (geom != NULL);
	PED_ASSERT (hfsc_can_use_geom (geom));

	mdb = (HfsMasterDirectoryBlock *) buf;

	/* is 5 an intelligent value ? */
	if ((geom->length < 5)
	    || (!ped_geometry_read (geom, buf, 2, 1))
	    || (mdb->signature != PED_CPU_TO_BE16 (HFS_SIGNATURE)) )
		return NULL;

	search = ((PedSector) PED_BE16_TO_CPU (mdb->start_block)
		  + ((PedSector) PED_BE16_TO_CPU (mdb->total_blocks)
		     * (PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT )));
	max = search + (PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT);
	if (!(geom_ret = ped_geometry_new (geom->dev, geom->start, search + 2)))
		return NULL;

	for (; search < max; search++) {
		if (!ped_geometry_set (geom_ret, geom_ret->start, search + 2)
		    || !ped_geometry_read (geom_ret, buf, search, 1))
			break;
		if (mdb->signature == PED_CPU_TO_BE16 (HFS_SIGNATURE))
			return geom_ret;
	}

	ped_geometry_destroy (geom_ret);
	return NULL;
}
Example #7
0
/* 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;
}
Example #8
0
/* 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);
}
Example #9
0
/* 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;
}
Example #10
0
/* 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, return 0);
	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;
}
Example #11
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;
}
Example #12
0
File: hfs.c Project: Excito/parted
/* 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;
}
Example #13
0
File: hfs.c Project: Excito/parted
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;
}
Example #14
0
File: hfs.c Project: Excito/parted
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);
}
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 = PED_BE32_TO_CPU(jh->blhdr_size) / PED_SECTOR_SIZE_DEFAULT;
	blhdr = (HfsJBlockListHeader*)
		  ped_malloc (blhdr_nbsect * PED_SECTOR_SIZE_DEFAULT);
	if (!blhdr) return 0;

	start = PED_BE64_TO_CPU(jh->start) / 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 = PED_BE32_TO_CPU(blhdr->checksum);
		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 = PED_CPU_TO_BE32(cksum);
		
		for (i=1; i < PED_BE16_TO_CPU(blhdr->num_blocks); ++i) {
			size = PED_BE32_TO_CPU(blhdr->binfo[i].bsize);
			sector = PED_BE64_TO_CPU(blhdr->binfo[i].bnum);
			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) {
				ped_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;
			ped_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 = PED_CPU_TO_BE64(start * PED_SECTOR_SIZE_DEFAULT);

	ped_free (blhdr);
	return (ped_geometry_sync (fs->geom));

err_replay:
	ped_free (blhdr);
	return 0;
}
Example #16
0
/* 	     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;
}
Example #17
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;
}
Example #18
0
File: hfs.c Project: Excito/parted
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;
}
Example #19
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;
}
Example #20
0
static int
dvh_read (PedDisk* disk)
{
	DVHDiskData*		dvh_disk_data = disk->disk_specific;
	int			i;
	struct volume_header	vh;
	char			boot_name [BFNAMESIZE + 1];
#ifndef DISCOVER_ONLY
	int			write_back = 0;
#endif

	PED_ASSERT (dvh_disk_data != NULL);

	ped_disk_delete_all (disk);

	void *s0;
	if (!ptt_read_sector (disk->dev, 0, &s0))
		return 0;
	memcpy (&vh, s0, sizeof vh);
	free (s0);

	if (_checksum ((uint32_t*) &vh, sizeof (struct volume_header))) {
		if (ped_exception_throw (
			PED_EXCEPTION_ERROR,
			PED_EXCEPTION_IGNORE_CANCEL,
			_("Checksum is wrong, indicating the partition "
			  "table is corrupt."))
				== PED_EXCEPTION_CANCEL)
			return 0;
	}

	PED_ASSERT (PED_BE32_TO_CPU (vh.vh_magic) == VHMAGIC);

	dvh_disk_data->dev_params = vh.vh_dp;
	strncpy (boot_name, vh.vh_bootfile, BFNAMESIZE);
	boot_name[BFNAMESIZE] = 0;

	/* normal partitions */
	for (i = 0; i < NPARTAB; i++) {
		PedPartition* part;

		if (!vh.vh_pt[i].pt_nblks)
			continue;
		/* Skip the whole-disk partition, parted disklikes overlap */
		if (PED_BE32_TO_CPU (vh.vh_pt[i].pt_type) == PTYPE_VOLUME)
			continue;

		part = _parse_partition (disk, &vh.vh_pt[i]);
		if (!part)
			goto error_delete_all;

		part->fs_type = ped_file_system_probe (&part->geom);
		part->num = i + 1;

		if (PED_BE16_TO_CPU (vh.vh_rootpt) == i)
			ped_partition_set_flag (part, PED_PARTITION_ROOT, 1);
		if (PED_BE16_TO_CPU (vh.vh_swappt) == i)
			ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);

		PedConstraint *constraint_exact
		  = ped_constraint_exact (&part->geom);
		bool ok = ped_disk_add_partition (disk, part, constraint_exact);
		ped_constraint_destroy (constraint_exact);
		if (!ok) {
			ped_partition_destroy (part);
			goto error_delete_all;
		}
	}

	if (!ped_disk_extended_partition (disk)) {
#ifdef DISCOVER_ONLY
		return 1;
#else
		switch (_handle_no_volume_header (disk)) {
			case PED_EXCEPTION_CANCEL:
				return 0;
			case PED_EXCEPTION_IGNORE:
				return 1;
			case PED_EXCEPTION_FIX:
				write_back = 1;
				break;
			default:
				break;
		}
#endif
	}

	/* boot partitions */
	for (i = 0; i < NVDIR; i++) {
		PedPartition* part;

		if (!vh.vh_vd[i].vd_nbytes)
			continue;

		part = _parse_boot_file (disk, &vh.vh_vd[i]);
		if (!part)
			goto error_delete_all;

		part->fs_type = ped_file_system_probe (&part->geom);
		part->num = NPARTAB + i + 1;

		if (!strcmp (boot_name, ped_partition_get_name (part)))
			ped_partition_set_flag (part, PED_PARTITION_BOOT, 1);

		PedConstraint *constraint_exact
		  = ped_constraint_exact (&part->geom);
		bool ok = ped_disk_add_partition (disk, part, constraint_exact);
		ped_constraint_destroy (constraint_exact);
		if (!ok) {
			ped_partition_destroy (part);
			goto error_delete_all;
		}
	}
#ifndef DISCOVER_ONLY
	if (write_back)
		dvh_write (disk);
#endif
	return 1;

error_delete_all:
	ped_disk_delete_all (disk);
	return 0;
}