Ejemplo n.º 1
0
static PedGeometry*
xfs_probe (PedGeometry* geom)
{
	PedSector	block_size;
	PedSector	block_count;
	union {
		struct xfs_sb	sb;
		char		bytes [512];
	} buf;

	if (geom->length < XFS_SB_DADDR + 1)
		return NULL;
	if (!ped_geometry_read (geom, &buf, XFS_SB_DADDR, 1))
		return NULL;

	if (PED_LE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) {
		block_size = PED_LE32_TO_CPU (buf.sb.sb_blocksize) / 512;
		block_count = PED_LE64_TO_CPU (buf.sb.sb_dblocks);

		return ped_geometry_new (geom->dev, geom->start,
					 block_size * block_count);
	}

	if (PED_BE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) {
		block_size = PED_BE32_TO_CPU (buf.sb.sb_blocksize) / 512;
		block_count = PED_BE64_TO_CPU (buf.sb.sb_dblocks);

		return ped_geometry_new (geom->dev, geom->start,
					 block_size * block_count);
	}

	return NULL;
}
Ejemplo n.º 2
0
Archivo: hfs.c Proyecto: Excito/parted
/* 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 ! */
}
Ejemplo n.º 3
0
/* 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;
}
Ejemplo n.º 4
0
Archivo: hfs.c Proyecto: 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;
}
Ejemplo n.º 5
0
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;
}