Example #1
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 );
}
Example #2
0
static PedGeometry*
jfs_probe (PedGeometry* geom)
{
	union {
		struct superblock	sb;
		char			bytes[512];
	} buf;

        /* FIXME: for now, don't even try to deal with larger sector size.  */
	if (geom->dev->sector_size != PED_SECTOR_SIZE_DEFAULT)
		return NULL;

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

	if (strncmp (buf.sb.s_magic, JFS_MAGIC, 4) == 0) {
		PedSector block_size = PED_LE32_TO_CPU (buf.sb.s_pbsize) / 512;
		PedSector block_count = PED_LE64_TO_CPU (buf.sb.s_size);

		return ped_geometry_new (geom->dev, geom->start,
					 block_size * block_count);
	} else {
		return NULL;
	}
}
Example #3
0
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;
}
Example #4
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 #5
0
File: ufs.c Project: Excito/parted
static PedGeometry*
ufs_probe_sun (PedGeometry* geom)
{
	int8_t buf[512 * 3];
	struct ufs_super_block *sb;

	if (geom->length < 5)
		return 0;
	if (!ped_geometry_read (geom, buf, 16, 3))
		return 0;

	sb = (struct ufs_super_block *)buf;

	if (PED_BE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) {
		PedSector block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512;
		PedSector block_count = PED_BE32_TO_CPU(sb->fs_size);
		return ped_geometry_new (geom->dev, geom->start,
					 block_size * block_count);
	}
	if (PED_LE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) {
		PedSector block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512;
		PedSector block_count = PED_LE32_TO_CPU(sb->fs_size);
		return ped_geometry_new (geom->dev, geom->start,
					 block_size * block_count);
	}
	return NULL;
}
Example #6
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;
}
/* 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);
}
Example #8
0
static PedGeometry *reiserfs_probe(PedGeometry *geom)
{
	int i;
	reiserfs_super_block_t sb;

	PED_ASSERT(geom != NULL);

	for (i = 0; reiserfs_super_offset[i] != -1; i++) {
		if (reiserfs_super_offset[i] >= geom->length)
			continue;
		if (!ped_geometry_read (geom, &sb, reiserfs_super_offset[i], 1))
			continue;

		if (strncmp(REISERFS_SIGNATURE, sb.s_magic,
		            strlen(REISERFS_SIGNATURE)) == 0
		    || strncmp(REISER2FS_SIGNATURE, sb.s_magic,
			       strlen(REISER2FS_SIGNATURE)) == 0
		    || strncmp(REISER3FS_SIGNATURE, sb.s_magic,
			       strlen(REISER3FS_SIGNATURE)) == 0) {
			PedSector block_size;
			PedSector block_count;

			block_size = PED_LE16_TO_CPU(sb.s_blocksize)
					/ PED_SECTOR_SIZE_DEFAULT;
			block_count = PED_LE32_TO_CPU(sb.s_block_count);

			return ped_geometry_new(geom->dev, geom->start,
						block_size * block_count);
		}
	}
	return NULL;
}
Example #9
0
/* copies the "hidden" sectors, between the boot sector and the FAT.  Required,
 * for the Windows 98 FAT32 boot loader
 */
int
_copy_hidden_sectors (FatOpContext* ctx)
{
	FatSpecific*    old_fs_info = FAT_SPECIFIC (ctx->old_fs);
	FatSpecific*    new_fs_info = FAT_SPECIFIC (ctx->new_fs);
	PedSector       first = 1;
	PedSector       last;
	PedSector       count;

	/* nothing to copy for FAT16 */
	if (old_fs_info->fat_type == FAT_TYPE_FAT16
			|| new_fs_info->fat_type == FAT_TYPE_FAT16)
		return 1;

	last = PED_MIN (old_fs_info->fat_offset, new_fs_info->fat_offset) - 1;
	count = last - first + 1;

	PED_ASSERT (count < BUFFER_SIZE);

	if (!ped_geometry_read (ctx->old_fs->geom, old_fs_info->buffer,
				first, count))
		return 0;
	if (!ped_geometry_write (ctx->new_fs->geom, old_fs_info->buffer,
				 first, count))
		return 0;
	return 1;
}
Example #10
0
FatTraverseInfo*
fat_traverse_begin (PedFileSystem* fs, FatCluster start_cluster,
		    const char* dir_name)
{
	FatSpecific*		fs_info = FAT_SPECIFIC (fs);
	FatTraverseInfo*	trav_info;

	trav_info = (FatTraverseInfo*) ped_malloc (sizeof (FatTraverseInfo));
	if (!trav_info)
		goto error;

	trav_info->dir_name = strdup (dir_name);
	if (!trav_info->dir_name)
		goto error_free_trav_info;

	trav_info->fs = fs;
	trav_info->is_legacy_root_dir
		= (fs_info->fat_type == FAT_TYPE_FAT16) && (start_cluster == 0);
	trav_info->dirty = 0;
	trav_info->eof = 0;
	trav_info->current_entry = -1;

	if (trav_info->is_legacy_root_dir) {
		trav_info->buffer_size = 512 * fs_info->root_dir_sector_count;
	} else {
		trav_info->next_buffer = start_cluster;
		trav_info->buffer_size = fs_info->cluster_size;
	}

	trav_info->dir_entries
		= (FatDirEntry*) ped_malloc (trav_info->buffer_size);
	if (!trav_info->dir_entries)
		goto error_free_dir_name;

	if (trav_info->is_legacy_root_dir) {
		if (!ped_geometry_read (fs->geom, trav_info->dir_entries,
					fs_info->root_dir_offset,
					fs_info->root_dir_sector_count))
			goto error_free_dir_entries;
	} else {
		if (!read_next_dir_buffer (trav_info))
			goto error_free_dir_entries;
	}

	return trav_info;

error_free_dir_entries:
	free (trav_info->dir_entries);
error_free_dir_name:
	free (trav_info->dir_name);
error_free_trav_info:
	free (trav_info);
error:
	return NULL;
}
Example #11
0
static int
ufs_clobber (PedGeometry* geom)
{
	char	buf[1536];

	if (!ped_geometry_read (geom, buf, 16, 3))
		return 0;

	memset (buf, 0, sizeof(struct ufs_super_block));

	return ped_geometry_write (geom, buf, 16, 3);
}
Example #12
0
/* Reads in the boot sector (superblock), and does a minimum of sanity
 * checking.  The goals are:
 *	- to detect fat file systems, even if they are damaged [i.e. not
 * return an error / throw an exception]
 *	- to fail detection if there's not enough information for
 * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero)
 */
int
fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom)
{
	PED_ASSERT (bs != NULL);
	PED_ASSERT (geom != NULL);

	if (!ped_geometry_read (geom, bs, 0, 1))
		return 0;

	if (PED_LE16_TO_CPU (bs->boot_sign) != 0xAA55) {
		ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
			_("File system has an invalid signature for a FAT "
			  "file system."));
		return 0;
	}

	if (!bs->system_id[0]) {
		ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
			_("File system has an invalid signature for a FAT "
			  "file system."));
		return 0;
	}

	if (!bs->sector_size
            || PED_LE16_TO_CPU (bs->sector_size) % PED_SECTOR_SIZE_DEFAULT) {
		ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
			_("File system has an invalid sector size for a FAT "
			  "file system."));
		return 0;
	}

	if (!bs->cluster_size) {
		ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
			_("File system has an invalid cluster size for a FAT "
			  "file system."));
		return 0;
	}

	if (!bs->reserved) {
		ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
			_("File system has an invalid number of reserved "
			  "sectors for a FAT file system."));
		return 0;
	}

	if (bs->fats < 1 || bs->fats > 4) {
		ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
			_("File system has an invalid number of FATs."));
		return 0;
	}

	return 1;
}
Example #13
0
int
fat_read_fragments (PedFileSystem* fs, char* buf, FatFragment frag,
                    FatFragment count)
{
    FatSpecific*	fs_info = FAT_SPECIFIC (fs);
    PedSector	sector = fat_frag_to_sector (fs, frag);
    PedSector	sector_count = count * fs_info->frag_sectors;

    PED_ASSERT (frag >= 0 && frag < fs_info->frag_count);

    return ped_geometry_read (fs->geom, buf, sector, sector_count);
}
Example #14
0
int
fat_read_clusters (PedFileSystem* fs, char *buf, FatCluster cluster,
                   FatCluster count)
{
    FatSpecific*	fs_info = FAT_SPECIFIC (fs);
    PedSector	sector = fat_cluster_to_sector (fs, cluster);
    PedSector	sector_count = count * fs_info->cluster_sectors;

    PED_ASSERT (cluster >= 2
                && cluster + count - 1 < fs_info->cluster_count + 2);

    return ped_geometry_read (fs->geom, buf, sector, sector_count);
}
Example #15
0
PyObject *py_ped_geometry_read(PyObject *s, PyObject *args) {
    PyObject *ret = NULL;
    PedGeometry *geom = NULL;
    char *out_buf = NULL;
    PedSector offset, count;

    if (!PyArg_ParseTuple(args, "LL", &offset, &count)) {
        return NULL;
    }

    geom = _ped_Geometry2PedGeometry(s);
    if (geom == NULL) {
        return NULL;
    }

    /* py_device_read will ASSERT if the device isn't open yet. */
    if (geom->dev->open_count <= 0) {
        PyErr_SetString(IOException, "Attempting to read from a unopened device");
        return NULL;
    }

    /* And then py_geometry_read will ASSERT on these things too. */
    if (offset < 0 || count < 0) {
        PyErr_SetString(IOException, "offset and count cannot be negative.");
        return NULL;
    }

    if ((out_buf = malloc(geom->dev->sector_size * count)) == NULL) {
        return PyErr_NoMemory();
    }

    if (ped_geometry_read(geom, out_buf, offset, count) == 0) {
        if (partedExnRaised) {
            partedExnRaised = 0;

            if (!PyErr_ExceptionMatches(PartedException) &&
                    !PyErr_ExceptionMatches(PyExc_NotImplementedError))
                PyErr_SetString(IOException, partedExnMessage);
        }
        else
            PyErr_SetString(IOException, "Could not read from given region");

        free(out_buf);
        return NULL;
    }

    ret = PyString_FromString(out_buf);
    free(out_buf);

    return ret;
}
Example #16
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 #17
0
static PedGeometry*
ntfs_probe (PedGeometry* geom)
{
    char	buf[512];

    if (!ped_geometry_read (geom, buf, 0, 1))
        return 0;

    if (strncmp (NTFS_SIGNATURE, buf + 3, strlen (NTFS_SIGNATURE)) == 0)
        return ped_geometry_new (geom->dev, geom->start,
                                 PED_LE64_TO_CPU (*(uint64_t*)
                                         (buf + 0x28)));
    else
        return NULL;
}
Example #18
0
/*         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;
}
Example #19
0
File: hfs.c Project: Excito/parted
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;
}
Example #20
0
static int
duplicate_legacy_root_dir (FatOpContext* ctx)
{
	FatSpecific*		old_fs_info = FAT_SPECIFIC (ctx->old_fs);
	FatSpecific*		new_fs_info = FAT_SPECIFIC (ctx->new_fs);

	PED_ASSERT (old_fs_info->root_dir_sector_count
			== new_fs_info->root_dir_sector_count);

	if (!ped_geometry_read (ctx->old_fs->geom, old_fs_info->buffer,
				old_fs_info->root_dir_offset,
				old_fs_info->root_dir_sector_count))
		return 0;

	if (!ped_geometry_write (ctx->new_fs->geom, old_fs_info->buffer,
				 new_fs_info->root_dir_offset,
				 new_fs_info->root_dir_sector_count))
		return 0;

	return 1;
}
Example #21
0
/* 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;
}
Example #22
0
File: ufs.c Project: Excito/parted
static PedGeometry*
ufs_probe_hp (PedGeometry* geom)
{
	int8_t buf[1536];
	struct ufs_super_block *sb;
	PedSector block_size;
	PedSector block_count;

	if (geom->length < 5)
		return 0;
	if (!ped_geometry_read (geom, buf, 16, 3))
		return 0;

	sb = (struct ufs_super_block *)buf;

	/* Try sane bytesex */
	switch (PED_BE32_TO_CPU(sb->fs_magic)) {
		case UFS_MAGIC_LFN:
		case UFS_MAGIC_FEA:
		case UFS_MAGIC_4GB:
			block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512;
			block_count = PED_BE32_TO_CPU(sb->fs_size);
			return ped_geometry_new (geom->dev, geom->start,
						 block_size * block_count);
	}

	/* Try perverted bytesex */
	switch (PED_LE32_TO_CPU(sb->fs_magic)) {
		case UFS_MAGIC_LFN:
		case UFS_MAGIC_FEA:
		case UFS_MAGIC_4GB:
			block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512;
			block_count = PED_LE32_TO_CPU(sb->fs_size);
			return ped_geometry_new (geom->dev, geom->start,
						 block_size * block_count);
	}
	return NULL;
}
Example #23
0
int
fat_info_sector_read (FatInfoSector* is, const PedFileSystem* fs)
{
	FatSpecific*	fs_info = FAT_SPECIFIC (fs);
	int		status;

	PED_ASSERT (is != NULL);

	if (!ped_geometry_read (fs->geom, is, fs_info->info_sector_offset, 1))
		return 0;

	if (PED_LE32_TO_CPU (is->signature_2) != FAT32_INFO_MAGIC2) {
		status = ped_exception_throw (PED_EXCEPTION_WARNING,
				PED_EXCEPTION_IGNORE_CANCEL,
				_("The information sector has the wrong "
				"signature (%x).  Select cancel for now, "
				"and send in a bug report.  If you're "
				"desperate, it's probably safe to ignore."),
				PED_LE32_TO_CPU (is->signature_2));
		if (status == PED_EXCEPTION_CANCEL) return 0;
	}
	return 1;
}
Example #24
0
static PedGeometry*
jfs_probe (PedGeometry* geom)
{
	union {
		struct superblock	sb;
		char			bytes[512];
	} buf;

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

	if (strncmp (buf.sb.s_magic, JFS_MAGIC, 4) == 0) {
		PedSector block_size = PED_LE32_TO_CPU (buf.sb.s_pbsize) / 512;
		PedSector block_count = PED_LE64_TO_CPU (buf.sb.s_size);

		return ped_geometry_new (geom->dev, geom->start,
					 block_size * block_count);
	} else {
		return NULL;
	}
}
Example #25
0
File: hfs.c Project: Excito/parted
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;
}
Example #26
0
/* -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;
}
Example #27
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 #28
0
File: hfs.c Project: Excito/parted
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);
}
Example #29
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;
}
Example #30
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;
}