コード例 #1
0
ファイル: rdb.c プロジェクト: inteos/WBSAirback
static struct AmigaBlock *
_amiga_read_block (const PedDevice *dev, struct AmigaBlock *blk,
                   PedSector block, struct AmigaIds *ids)
{
	if (!ped_device_read (dev, blk, block, 1))
		return NULL;
	if (ids && !_amiga_id_in_list(PED_BE32_TO_CPU(blk->amiga_ID), ids))
		return NULL;
	if (_amiga_checksum (blk) != 0) {
		switch (ped_exception_throw(PED_EXCEPTION_ERROR,
			PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL,
			_("%s : Bad checksum on block %llu of type %s."),
			__func__, block, _amiga_block_id(PED_BE32_TO_CPU(blk->amiga_ID))))
		{
			case PED_EXCEPTION_CANCEL :
				return NULL;
			case PED_EXCEPTION_FIX :
				_amiga_calculate_checksum(AMIGA(blk));
				if (!ped_device_write ((PedDevice*)dev, blk, block, 1))
					return NULL;
			case PED_EXCEPTION_IGNORE :
			case PED_EXCEPTION_UNHANDLED :
			default :
				return blk;
		}
	}
	return blk;
}
コード例 #2
0
ファイル: rdb.c プロジェクト: inteos/WBSAirback
static int
_amiga_find_free_blocks(const PedDisk *disk, uint32_t *table,
	struct LinkedBlock *block, uint32_t first, uint32_t type)
{
	PedSector next;

	PED_ASSERT(disk != NULL);
	PED_ASSERT(disk->dev != NULL);

	for (next = first; next != LINK_END; next = PED_BE32_TO_CPU(block->lk_Next)) {
		if (table[next] != IDNAME_FREE) {
			switch (ped_exception_throw(PED_EXCEPTION_ERROR,
				PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL,
				_("%s : Loop detected at block %d."), __func__, next))
			{
				case PED_EXCEPTION_CANCEL :
					return 0;
				case PED_EXCEPTION_FIX :
					/* TODO : Need to add fixing code */
				case PED_EXCEPTION_IGNORE :
				case PED_EXCEPTION_UNHANDLED :
				default :
					return 1;
			}
		}

		if (!_amiga_read_block (disk->dev, AMIGA(block), next, NULL)) {
			return 0;
		}
		if (PED_BE32_TO_CPU(block->lk_ID) != type) {
			switch (ped_exception_throw(PED_EXCEPTION_ERROR,
				PED_EXCEPTION_CANCEL,
				_("%s : The %s list seems bad at block %s."),
				__func__, _amiga_block_id(PED_BE32_TO_CPU(block->lk_ID)), next))
			{
				/* TODO : to more subtile things here */
				case PED_EXCEPTION_CANCEL :
				case PED_EXCEPTION_UNHANDLED :
				default :
					return 0;
			}
		}
		table[next] = type;
		if (PED_BE32_TO_CPU(block->lk_ID) == IDNAME_FILESYSHEADER) {
			if (_amiga_find_free_blocks(disk, table, block,
				PED_BE32_TO_CPU(LNK2(block)->lk2_Linked),
				IDNAME_LOADSEG) == 0) return 0;
		}
	}
	return 1;
}
コード例 #3
0
ファイル: amiga.c プロジェクト: NekPoN/parted
static uint32_t
_amiga_find_rdb (PedDevice *dev, struct RigidDiskBlock *rdb) {
	int i;
	struct AmigaIds *ids;

	ids = _amiga_add_id (IDNAME_RIGIDDISK, NULL);

	for (i = 0; i<RDB_LOCATION_LIMIT; i++) {
		if (!_amiga_read_block (dev, AMIGA(rdb), i, ids)) {
			continue;
		}
		if (PED_BE32_TO_CPU (rdb->rdb_ID) == IDNAME_RIGIDDISK) {
			_amiga_free_ids (ids);
			return i;
		}
	}
	_amiga_free_ids (ids);
	return AMIGA_RDB_NOT_FOUND;
}
コード例 #4
0
ファイル: rdb.c プロジェクト: inteos/WBSAirback
static int
amiga_write (const PedDisk* disk)
{
	struct RigidDiskBlock *rdb;
	struct LinkedBlock *block;
	struct PartitionBlock *partition;
	PedPartition *part, *next_part;
	PedSector cylblocks, first_hb, last_hb;
	uint32_t * table;
	uint32_t i;
	uint32_t rdb_num, part_num, block_num, next_num;

	PED_ASSERT (disk != NULL);
	PED_ASSERT (disk->dev != NULL);
	PED_ASSERT (disk->disk_specific != NULL);

	if (!(rdb = ped_malloc (disk->dev->sector_size)))
		return 0;

	/* Let's read the rdb */
	if ((rdb_num = _amiga_find_rdb (disk->dev, rdb)) == AMIGA_RDB_NOT_FOUND) {
		rdb_num = 2;
		size_t pb_size = sizeof (struct PartitionBlock);
                /* Initialize only the part that won't be copied over
                   with a partition block in amiga_read.  */
		memset ((char *)(RDSK(disk->disk_specific)) + pb_size,
			0, PED_SECTOR_SIZE_DEFAULT - pb_size);
	} else {
		memcpy (RDSK(disk->disk_specific), rdb, disk->dev->sector_size);
	}
	free (rdb);
	rdb = RDSK(disk->disk_specific);

	cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) *
		(PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors);
	first_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksLo);
	last_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksHi);

	/* Allocate a free block table and initialize it.
	   There must be room for at least RDB_NUM + 2 entries, since
	   the first RDB_NUM+1 entries get IDNAME_RIGIDDISK, and the
	   following one must have LINK_END to serve as sentinel.  */
	size_t tab_size = 2 + MAX (last_hb - first_hb, rdb_num);
	if (!(table = ped_malloc (tab_size * sizeof *table)))
		return 0;

	for (i = 0; i <= rdb_num; i++)
		table[i] = IDNAME_RIGIDDISK;
	for (     ; i < tab_size; i++)
		table[i] = LINK_END;

	/* Let's allocate a partition block */
	if (!(block = ped_malloc (disk->dev->sector_size))) {
		free (table);
		return 0;
	}

	/* And fill the free block table */
	if (_amiga_find_free_blocks(disk, table, block,
		PED_BE32_TO_CPU (rdb->rdb_BadBlockList), IDNAME_BADBLOCK) == 0)
	{
		ped_exception_throw(PED_EXCEPTION_ERROR,
			PED_EXCEPTION_CANCEL,
			_("%s : Failed to list bad blocks."), __func__);
		goto error_free_table;
	}
	if (_amiga_find_free_blocks(disk, table, block,
		PED_BE32_TO_CPU (rdb->rdb_PartitionList), IDNAME_PARTITION) == 0)
	{
		ped_exception_throw(PED_EXCEPTION_ERROR,
			PED_EXCEPTION_CANCEL,
			_("%s : Failed to list partition blocks."), __func__);
		goto error_free_table;
	}
	if (_amiga_find_free_blocks(disk, table, block,
		PED_BE32_TO_CPU (rdb->rdb_FileSysHeaderList), IDNAME_FILESYSHEADER) == 0)
	{
		ped_exception_throw(PED_EXCEPTION_ERROR,
			PED_EXCEPTION_CANCEL,
			_("%s : Failed to list file system blocks."), __func__);
		goto error_free_table;
	}
	if (_amiga_find_free_blocks(disk, table, block,
		PED_BE32_TO_CPU (rdb->rdb_BootBlockList), IDNAME_BOOT) == 0)
	{
		ped_exception_throw(PED_EXCEPTION_ERROR,
			PED_EXCEPTION_CANCEL,
			_("%s : Failed to list boot blocks."), __func__);
		goto error_free_table;
	}

	block_num = part_num = _amiga_next_free_block(table, rdb_num+1,
                                                      IDNAME_PARTITION);
	part = _amiga_next_real_partition(disk, NULL);
	rdb->rdb_PartitionList = PED_CPU_TO_BE32(part ? part_num : LINK_END);
	for (; part != NULL; part = next_part, block_num = next_num) {
		PED_ASSERT(part->disk_specific != NULL);
		PED_ASSERT(part->geom.start % cylblocks == 0);
		PED_ASSERT((part->geom.end + 1) % cylblocks == 0);

		next_part = _amiga_next_real_partition(disk, part);
		next_num = _amiga_next_free_block(table, block_num+1, IDNAME_PARTITION);

		partition = PART(part->disk_specific);
		if (next_part == NULL)
			partition->pb_Next = PED_CPU_TO_BE32(LINK_END);
		else
			partition->pb_Next = PED_CPU_TO_BE32(next_num);
		partition->de_LowCyl = PED_CPU_TO_BE32(part->geom.start/cylblocks);
		partition->de_HighCyl = PED_CPU_TO_BE32((part->geom.end+1)/cylblocks-1);
		_amiga_calculate_checksum(AMIGA(partition));
		if (!ped_device_write (disk->dev, (void*) partition, block_num, 1)) {
			ped_exception_throw(PED_EXCEPTION_ERROR,
				PED_EXCEPTION_CANCEL,
				_("Failed to write partition block at %d."),
				block_num);
			goto error_free_table;
			/* WARNING : If we fail here, we stop everything,
			 * and the partition table is lost. A better
			 * solution should be found, using the second
			 * half of the hardblocks to not overwrite the
			 * old partition table. It becomes problematic
			 * if we use more than half of the hardblocks. */
		}
	}

	if (block_num > PED_BE32_TO_CPU (rdb->rdb_HighRDSKBlock))
		rdb->rdb_HighRDSKBlock = PED_CPU_TO_BE32(block_num);

	_amiga_calculate_checksum(AMIGA(rdb));
	if (!ped_device_write (disk->dev, (void*) disk->disk_specific, rdb_num, 1))
		goto error_free_table;

	free (table);
	free (block);
	return ped_device_sync (disk->dev);

error_free_table:
	free (table);
	free (block);
	return 0;
}
コード例 #5
0
ファイル: rdb.c プロジェクト: inteos/WBSAirback
/* We have already allocated a rdb, we are now reading it from the disk */
static int
amiga_read (PedDisk* disk)
{
	struct RigidDiskBlock *rdb;
	struct PartitionBlock *partition;
	uint32_t partblock;
	uint32_t partlist[AMIGA_MAX_PARTITIONS];
	PedSector cylblocks;
	int i;

	PED_ASSERT(disk != NULL);
	PED_ASSERT(disk->dev != NULL);
	PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0);
	PED_ASSERT(disk->disk_specific != NULL);
	rdb = RDSK(disk->disk_specific);

	if (_amiga_find_rdb (disk->dev, rdb) == AMIGA_RDB_NOT_FOUND) {
		ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
			_("%s : Didn't find rdb block, should never happen."), __func__);
		return 0;
	}

	/* Let's copy the rdb read geometry to the dev */
	/* FIXME: should this go into disk->dev->bios_geom instead? */
	disk->dev->hw_geom.cylinders = PED_BE32_TO_CPU (rdb->rdb_Cylinders);
	disk->dev->hw_geom.heads = PED_BE32_TO_CPU (rdb->rdb_Heads);
	disk->dev->hw_geom.sectors = PED_BE32_TO_CPU (rdb->rdb_Sectors);
	cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) *
		(PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors);

	/* Remove all partitions in the former in memory table */
	ped_disk_delete_all (disk);

	/* Let's allocate a partition block */
	if (!(partition = ped_malloc (disk->dev->sector_size)))
		return 0;

	/* We initialize the hardblock free list to detect loops */
	for (i = 0; i < AMIGA_MAX_PARTITIONS; i++) partlist[i] = LINK_END;

	for (i = 1, partblock = PED_BE32_TO_CPU(rdb->rdb_PartitionList);
		i < AMIGA_MAX_PARTITIONS && partblock != LINK_END;
		i++, partblock = PED_BE32_TO_CPU(partition->pb_Next))
	{
		PedPartition *part;
		PedSector start, end;

		/* Let's look for loops in the partition table */
		if (_amiga_loop_check(partblock, partlist, i)) {
			break;
		}

		/* Let's allocate and read a partition block to get its geometry*/
		if (!_amiga_read_block (disk->dev, AMIGA(partition),
		                        (PedSector)partblock, NULL)) {
			free(partition);
			return 0;
		}

		start = ((PedSector) PED_BE32_TO_CPU (partition->de_LowCyl))
			* cylblocks;
		end = (((PedSector) PED_BE32_TO_CPU (partition->de_HighCyl))
			+ 1) * cylblocks - 1;

		/* We can now construct a new partition */
		if (!(part = ped_partition_new (disk, PED_PARTITION_NORMAL,
                                                NULL, start, end))) {
			free(partition);
			return 0;
		}
		/* And copy over the partition block */
		memcpy(part->disk_specific, partition, 256);

		part->num = i;
		part->type = 0;
		/* Let's probe what file system is present on the disk */
		part->fs_type = ped_file_system_probe (&part->geom);

		PedConstraint *constraint_exact
			= ped_constraint_exact (&part->geom);
		if (constraint_exact == NULL)
			return 0;
		bool ok = ped_disk_add_partition (disk, part, constraint_exact);
		ped_constraint_destroy (constraint_exact);
		if (!ok) {
			ped_partition_destroy(part);
			free(partition);
			return 0;
		}
	}
	free(partition);
	return 1;
}