Ejemplo n.º 1
0
void test_move_onto() {
	/* Set up */
	world_t* world = world_create(5);

	/* Test case 1 - A is top of stack */
	move_onto(world, 1, 2);
	assert(world->position_blocks_top[1] == NULL && 
			world->position_blocks_bottom[1] == NULL);
	assert(world->position_blocks_top[2]->value == 1 &&
			world->position_blocks_bottom[2]->value == 2);

	/* Test case 2 - A and B in middle of their stacks */
	move_onto(world, 3, 4);
	move_onto(world, 2, 4);
	assert(block_get_stack(block_get(world, 1)) == 1 &&
			block_get_stack(block_get(world, 3)) == 3);
	assert(block_get_stack(block_get(world, 2)) == 4 &&
			block_get_stack(block_get(world, 4)) == 4);

	assert(world->position_blocks_top[4]->value == 2 &&
			world->position_blocks_bottom[4]->value == 4);

	/* Test case 3 - A and B on same stack */
	move_onto(world, 3, 2);
	move_onto(world, 3, 4);
	assert(block_get_stack(block_get(world, 2)) == 4);

	/* Tear down */
	world_delete(&world);
}
Ejemplo n.º 2
0
/** Read block from file located on a exFAT file system.
 *
 * @param block		Pointer to a block pointer for storing result.
 * @param bs		Buffer holding the boot sector of the file system.
 * @param service_id	Service ID of the file system.
 * @param fcl		First cluster used by the file. Can be zero if the file
 *			is empty.
 * @param clp		If not NULL, address where the cluster containing bn
 *			will be stored.
 *			stored
 * @param bn		Block number.
 * @param flags		Flags passed to libblock.
 *
 * @return		EOK on success or a negative error code.
 */
int
exfat_block_get_by_clst(block_t **block, exfat_bs_t *bs, 
    service_id_t service_id, bool fragmented, exfat_cluster_t fcl,
    exfat_cluster_t *clp, aoff64_t bn, int flags)
{
	uint32_t clusters;
	uint32_t max_clusters;
	exfat_cluster_t c;
	int rc;

	if (fcl < EXFAT_CLST_FIRST || fcl > DATA_CNT(bs) + 2)
		return ELIMIT;

	if (!fragmented) {
		rc = block_get(block, service_id, DATA_FS(bs) + 
		    (fcl - EXFAT_CLST_FIRST)*SPC(bs) + bn, flags);
	} else {
		max_clusters = bn / SPC(bs);
		rc = exfat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);
		if (rc != EOK)
			return rc;
		assert(clusters == max_clusters);

		rc = block_get(block, service_id, DATA_FS(bs) + 
		    (c - EXFAT_CLST_FIRST) * SPC(bs) + (bn % SPC(bs)), flags);

		if (clp)
			*clp = c;
	}

	return rc;
}
Ejemplo n.º 3
0
/** Get cluster from the first FAT.
 *
 * @param bs		Buffer holding the boot sector for the file system.
 * @param service_id	Service ID for the file system.
 * @param clst		Cluster which to get.
 * @param value		Output argument holding the value of the cluster.
 *
 * @return		EOK or a negative error code.
 */
static int
fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    fat_cluster_t clst, fat_cluster_t *value)
{
	block_t *b, *b1;
	uint16_t byte1, byte2;
	aoff64_t offset;
	int rc;

	offset = (clst + clst / 2);
	if (offset / BPS(bs) >= SF(bs))
		return ERANGE;

	rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
	    offset / BPS(bs), BLOCK_FLAGS_NONE);
	if (rc != EOK)
		return rc;

	byte1 = ((uint8_t *) b->data)[offset % BPS(bs)];
	/* This cluster access spans a sector boundary. Check only for FAT12 */
	if ((offset % BPS(bs)) + 1 == BPS(bs)) {
		/* Is this the last sector of FAT? */
		if (offset / BPS(bs) < SF(bs)) {
			/* No, read the next sector */
			rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
			    SF(bs) * fatno + offset / BPS(bs),
			    BLOCK_FLAGS_NONE);
			if (rc != EOK) {
				block_put(b);
				return rc;
			}
			/*
			* Combining value with last byte of current sector and
			* first byte of next sector
			*/
			byte2 = ((uint8_t*) b1->data)[0];

			rc = block_put(b1);
			if (rc != EOK) {
				block_put(b);
				return rc;
			}
		} else {
			/* Yes. This is the last sector of FAT */
			block_put(b);
			return ERANGE;
		}
	} else
		byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1];

	*value = uint16_t_le2host(byte1 | (byte2 << 8));
	if (IS_ODD(clst))
		*value = (*value) >> 4;
	else
Ejemplo n.º 4
0
static ssize_t block_read(struct cdev *cdev, void *buf, size_t count,
		unsigned long offset, unsigned long flags)
{
	struct block_device *blk = cdev->priv;
	unsigned long mask = BLOCKSIZE(blk) - 1;
	unsigned long block = offset >> blk->blockbits;
	size_t icount = count;
	int blocks;

	if (offset & mask) {
		size_t now = BLOCKSIZE(blk) - (offset & mask);
		void *iobuf = block_get(blk, block);

		now = min(count, now);

		if (IS_ERR(iobuf))
			return PTR_ERR(iobuf);

		memcpy(buf, iobuf + (offset & mask), now);
		buf += now;
		count -= now;
		block++;
	}

	blocks = count >> blk->blockbits;

	while (blocks) {
		void *iobuf = block_get(blk, block);

		if (IS_ERR(iobuf))
			return PTR_ERR(iobuf);

		memcpy(buf, iobuf, BLOCKSIZE(blk));
		buf += BLOCKSIZE(blk);
		blocks--;
		block++;
		count -= BLOCKSIZE(blk);
	}

	if (count) {
		void *iobuf = block_get(blk, block);

		if (IS_ERR(iobuf))
			return PTR_ERR(iobuf);

		memcpy(buf, iobuf, count);
	}

	return icount;
}
Ejemplo n.º 5
0
void test_pile_over(){
	/* Set up*/
	world_t* world = world_create(7);
	pile_over(world, 1, 2);
	pile_over(world, 3, 4);
	pile_over(world, 5, 6);

	/* Test case 1 - move all left stack to right stack*/
	pile_over(world, 2, 4);
	int i = 0;
	for(i = 1; i <= 4; i++) {
		assert(block_get_stack(block_get(world, i)) == 4);
	}
	assert(world->position_blocks_bottom[2] == NULL &&
			world->position_blocks_top[2] == NULL);


	/* Test case 2 - move part of left stack to right stack. Choose middle elem in right stack*/
	/* Elements should be on top of 6*/
	pile_over(world, 3, 5);
	int stack[] = {1, 2, 3, 5, 6};
	for(i = 0; i < 5; i++) {
		assert(block_get_stack(block_get(world, stack[i])) == 6);
	}
	assert(world->position_blocks_bottom[4]->value == 4 &&
			world->position_blocks_top[4]->value == 4);
	assert(world->position_blocks_bottom[6]->value == 6 &&
			world->position_blocks_top[6]->value == 1);

	/* Test case 3 - move block that is already on top of another*/
	pile_over(world, 3, 5);
	for(i = 0; i < 5; i++) {
		assert(block_get_stack(block_get(world, stack[i])) == 6);
	}
	assert(world->position_blocks_bottom[4]->value == 4 &&
			world->position_blocks_top[4]->value == 4);
	assert(world->position_blocks_bottom[6]->value == 6 &&
			world->position_blocks_top[6]->value == 1);

	/* Test case 4 - move stack to middle of stack*/
	pile_over(world, 0, 4);
	pile_over(world, 4, 2);
	for (i = 0; i < 7; i++) {
		assert(block_get_stack(block_get(world, i)) == 6);
	}

	/* Tear down */
	world_delete(&world);

}
Ejemplo n.º 6
0
void print_inode_data(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t data)
{
	int rc;
	uint32_t data_block_index;
	block_t *block;
	
	rc = ext2_filesystem_get_inode_data_block_index(fs, inode, data,
	    &data_block_index);
	
	if (rc != EOK) {
		printf("Failed getting data block #%u\n", data);
		return;
	}
	
	printf("Data for inode contents block #%u is located in filesystem "
	    "block %u\n", data, data_block_index);
	
	printf("Data preview (only printable characters):\n");
	
	rc = block_get(&block, fs->device, data_block_index, 0);
	if (rc != EOK) {
		printf("Failed reading filesystem block %u\n", data_block_index);
		return;
	}
	
	print_data(block->data, block->size);
	printf("\n");	
	
	rc = block_put(block);
	if (rc != EOK) {
		printf("Failed putting filesystem block\n");
	}
	
}
Ejemplo n.º 7
0
/*
 ****************************************************************
 *	Encerra o uso das entradas da tabela "disktb"		*
 ****************************************************************
 */
int
disktb_close_entry (dev_t dev)
{
	DISKTB		*up;
	int		i;
	BHEAD		*bp;

	/*
	 *	Obtém a partição inicial do dispositivo
	 */
	if ((up = disktb_get_first_entry (dev)) == NODISKTB)
		return (-1);

	/*
	 *	Força a releitura da tabela de partições
	 */
	bp = block_get (up->p_dev, 0, 0);

#ifdef	DEBUG
	printf ("%v: O bloco 0 == %d\n", up->p_dev, EVENTTEST (&bp->b_done));
#endif	DEBUG

	EVENTCLEAR (&bp->b_done); block_put (bp);

	/*
	 *	Encerra as entradas
	 */
	for (i = 0; i < 2; i++, up++)
	{
	   /***	up->p_name = ...; ***/

		up->p_offset = 0;
		up->p_size   = BL4SZ / BLSZ;	/* Provisório, para ler a "parttb" */

	   /***	up->p_dev    = ...; ***/
	   /***	up->p_unit   = ...; ***/
	   /***	up->p_target = ...; ***/

		up->p_type  = 0;
		up->p_flags = 0;

		up->p_head  = 0;
		up->p_sect  = 0;
		up->p_cyl   = 0;

		if (up->p_nopen != 0)
		{
			printf
			(	"%s: p_nopen residual: %d\n",
				up->p_name, up->p_nopen
			);
		}

		up->p_nopen  = 0;
		up->p_lock  = 0;
	}

	return (0);

}	/* end disktb_close_entry */
Ejemplo n.º 8
0
int
block_next_lin(struct map_rect_priv *mr)
{
	struct coord_rect r;
	for (;;) {
		block_lin_count++;
		block_mem+=sizeof(struct block *);
		mr->b.block_num++;
		if (! mr->b.block_num) 
			mr->b.p=mr->file->begin+0x2000;
		else
			mr->b.p=mr->b.block_start+block_get_blocks(mr->b.b)*512;
		if (mr->b.p >= mr->file->end) {
			dbg(lvl_debug,"end of blocks %p vs %p\n", mr->b.p, mr->file->end);
			return 0;
		}
		mr->b.block_start=mr->b.p;
		mr->b.b=block_get(&mr->b.p);
		mr->b.p_start=mr->b.p;
		mr->b.end=mr->b.block_start+block_get_size(mr->b.b);
		if (block_get_count(mr->b.b) == -1) {
			dbg(lvl_warning,"empty blocks\n");
			return 0;
		}
		block_get_r(mr->b.b, &r);
		if (!mr->cur_sel || coord_rect_overlap(&mr->cur_sel->u.c_rect, &r)) {
			block_active_count++;
			block_active_mem+=block_get_blocks(mr->b.b)*512-sizeof(struct block *);
			dbg(lvl_debug,"block ok\n");
			return 1;
		}
		dbg(lvl_info,"block not in cur_sel\n");
	}
}
Ejemplo n.º 9
0
int
block_next_lin(struct map_rect_priv *mr)
{
	for (;;) {
		block_lin_count++;
		block_mem+=sizeof(struct block *);
		mr->b.block_num++;
		if (! mr->b.block_num) 
			mr->b.p=mr->file->begin+0x2000;
		else
			mr->b.p=mr->b.block_start+mr->b.b->blocks*512;
		if (mr->b.p >= mr->file->end)
			return 0;
		mr->b.block_start=mr->b.p;
		mr->b.b=block_get(&mr->b.p);
		mr->b.p_start=mr->b.p;
		mr->b.end=mr->b.block_start+mr->b.b->size;
		if (mr->b.b->count == -1)
			return 0;
		if (!mr->cur_sel || coord_rect_overlap(&mr->cur_sel->rect, &mr->b.b->r)) {
			block_active_count++;
			block_active_mem+=mr->b.b->blocks*512-sizeof(struct block *);
			return 1;
		}
	}
}
Ejemplo n.º 10
0
void test_pile_onto() {
	/* Set up */
	world_t* world = world_create(7);
	pile_onto(world, 1, 2);
	pile_onto(world, 3, 4);
	pile_onto(world, 2, 4);

	/* Test case 1 - Middle of stack A to middle of stack B */
	assert(block_get_stack(block_get(world, 3)) == 3);
	assert(block_get_stack(block_get(world, 1)) == 4 &&
		block_get_stack(block_get(world, 2)) == 4);
	assert(world->position_blocks_top[4]->value == 1 &&
			world->position_blocks_bottom[4]->value == 4);

	/* Test case 2 - stack A already on top of block B*/
	pile_onto(world, 1, 4);
	assert(block_get_stack(block_get(world, 2)) == 4);

	/* Tear down */
	world_delete(&world);
}
Ejemplo n.º 11
0
/** Read block from file located on a FAT file system.
 *
 * @param block		Pointer to a block pointer for storing result.
 * @param bs		Buffer holding the boot sector of the file system.
 * @param nodep		FAT node.
 * @param bn		Block number.
 * @param flags		Flags passed to libblock.
 *
 * @return		EOK on success or a negative error code.
 */
int
fat_block_get(block_t **block, struct fat_bs *bs, fat_node_t *nodep,
    aoff64_t bn, int flags)
{
	fat_cluster_t firstc = nodep->firstc;
	fat_cluster_t currc;
	aoff64_t relbn = bn;
	int rc;

	if (!nodep->size)
		return ELIMIT;

	if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
		goto fall_through;

	if (((((nodep->size - 1) / BPS(bs)) / SPC(bs)) == bn / SPC(bs)) &&
	    nodep->lastc_cached_valid) {
	    	/*
		 * This is a request to read a block within the last cluster
		 * when fortunately we have the last cluster number cached.
		 */
		return block_get(block, nodep->idx->service_id,
		    CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
	}

	if (nodep->currc_cached_valid && bn >= nodep->currc_cached_bn) {
		/*
		 * We can start with the cluster cached by the previous call to
		 * fat_block_get().
		 */
		firstc = nodep->currc_cached_value;
		relbn -= (nodep->currc_cached_bn / SPC(bs)) * SPC(bs);
	}

fall_through:
	rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc,
	    &currc, relbn, flags);
	if (rc != EOK)
		return rc;

	/*
	 * Update the "current" cluster cache.
	 */
	nodep->currc_cached_valid = true;
	nodep->currc_cached_bn = bn;
	nodep->currc_cached_value = currc;

	return rc;
}
Ejemplo n.º 12
0
/** Read block from file located on a FAT file system.
 *
 * @param block		Pointer to a block pointer for storing result.
 * @param bs		Buffer holding the boot sector of the file system.
 * @param service_id	Service ID handle of the file system.
 * @param fcl		First cluster used by the file. Can be zero if the file
 *			is empty.
 * @param clp		If not NULL, address where the cluster containing bn
 *			will be stored.
 *			stored
 * @param bn		Block number.
 * @param flags		Flags passed to libblock.
 *
 * @return		EOK on success or a negative error code.
 */
int
_fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id,
    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
{
	uint32_t clusters;
	uint32_t max_clusters;
	fat_cluster_t c;
	int rc;

	/*
	 * This function can only operate on non-zero length files.
	 */
	if (fcl == FAT_CLST_RES0)
		return ELIMIT;

	if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
		/* root directory special case */
		assert(bn < RDS(bs));
		rc = block_get(block, service_id,
		    RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags);
		return rc;
	}

	max_clusters = bn / SPC(bs);
	rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);
	if (rc != EOK)
		return rc;
	assert(clusters == max_clusters);

	rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags);

	if (clp)
		*clp = c;

	return rc;
}
Ejemplo n.º 13
0
/** Read block from file located on a exFAT file system.
 *
 * @param block		Pointer to a block pointer for storing result.
 * @param bs		Buffer holding the boot sector of the file system.
 * @param nodep		FAT node.
 * @param bn		Block number.
 * @param flags		Flags passed to libblock.
 *
 * @return		EOK on success or a negative error code.
 */
int
exfat_block_get(block_t **block, exfat_bs_t *bs, exfat_node_t *nodep,
    aoff64_t bn, int flags)
{
	exfat_cluster_t firstc = nodep->firstc;
	exfat_cluster_t currc = 0;
	aoff64_t relbn = bn;
	int rc;

	if (!nodep->size)
		return ELIMIT;

	if (nodep->fragmented) {
		if (((((nodep->size - 1) / BPS(bs)) / SPC(bs)) == bn / SPC(bs)) &&
		    nodep->lastc_cached_valid) {
			/*
			 * This is a request to read a block within the last cluster
			 * when fortunately we have the last cluster number cached.
			 */
			return block_get(block, nodep->idx->service_id, DATA_FS(bs) + 
		        (nodep->lastc_cached_value-EXFAT_CLST_FIRST)*SPC(bs) + 
			    (bn % SPC(bs)), flags);
		}

		if (nodep->currc_cached_valid && bn >= nodep->currc_cached_bn) {
			/*
			* We can start with the cluster cached by the previous call to
			* fat_block_get().
			*/
			firstc = nodep->currc_cached_value;
			relbn -= (nodep->currc_cached_bn / SPC(bs)) * SPC(bs);
		}
	}

	rc = exfat_block_get_by_clst(block, bs, nodep->idx->service_id,
	    nodep->fragmented, firstc, &currc, relbn, flags);
	if (rc != EOK)
		return rc;

	/*
	 * Update the "current" cluster cache.
	 */
	nodep->currc_cached_valid = true;
	nodep->currc_cached_bn = bn;
	nodep->currc_cached_value = currc;

	return rc;
}
Ejemplo n.º 14
0
static struct block *
block_get_byid(struct file *file, int id, unsigned char **p_ret)
{
	struct block_index *blk_idx;
	int blk_num,max;


	blk_idx=(struct block_index *)(file->begin+0x1000);
	max=(blk_idx->size-sizeof(struct block_index))/sizeof(struct block_index_item);
	block_mem+=24;
	while (id >= max) {
		blk_idx=(struct block_index *)(file->begin+blk_idx->next*512);
		id-=max;
	}
	blk_num=blk_idx->list[id].blocknum;

	*p_ret=file->begin+blk_num*512;
	return block_get(p_ret);
}
Ejemplo n.º 15
0
/** Get cluster from the FAT.
 *
 * @param bs		Buffer holding the boot sector for the file system.
 * @param service_id	Service ID for the file system.
 * @param clst		Cluster which to get.
 * @param value		Output argument holding the value of the cluster.
 *
 * @return		EOK or a negative error code.
 */
int
exfat_get_cluster(exfat_bs_t *bs, service_id_t service_id,
    exfat_cluster_t clst, exfat_cluster_t *value)
{
	block_t *b;
	aoff64_t offset;
	int rc;

	offset = clst * sizeof(exfat_cluster_t);

	rc = block_get(&b, service_id, FAT_FS(bs) + offset / BPS(bs), BLOCK_FLAGS_NONE);
	if (rc != EOK)
		return rc;

	*value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));

	rc = block_put(b);

	return rc;
}
Ejemplo n.º 16
0
/** Set cluster in FAT.
 *
 * @param bs		Buffer holding the boot sector for the file system.
 * @param service_id	Service ID for the file system.
 * @param clst		Cluster which is to be set.
 * @param value		Value to set the cluster with.
 *
 * @return		EOK on success or a negative error code.
 */
int
exfat_set_cluster(exfat_bs_t *bs, service_id_t service_id,
    exfat_cluster_t clst, exfat_cluster_t value)
{
	block_t *b;
	aoff64_t offset;
	int rc;

	offset = clst * sizeof(exfat_cluster_t);

	rc = block_get(&b, service_id, FAT_FS(bs) + offset / BPS(bs), BLOCK_FLAGS_NONE);
	if (rc != EOK)
		return rc;

	*(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(value);

	b->dirty = true;	/* need to sync block */
	rc = block_put(b);
	return rc;
}
Ejemplo n.º 17
0
void test_move_top_block(){
	world_t* world = world_create(3);
	move_top_block(world, 1, 2);
	/* Test case 1 - move block on top of another */
	assert(world->position_blocks_top[1] == NULL &&
			world->position_blocks_bottom[1] == NULL);
	assert(world->position_blocks_top[2]->value == 1 && 
			world->position_blocks_bottom[2]->value == 2);
	assert(equals(block_get(world, 2)->next, block_get(world, 1)));
	assert(equals(block_get(world, 1)->previous, block_get(world, 2)));
	assert(block_get_stack(block_get(world, 1)) == 2);

	/* Test case 2 - try to move slot without block*/
	move_top_block(world, 1, 2);

	/* Test case 3 - block to empty space */
	move_top_block(world, 2, 1);
	assert(equals(world->position_blocks_top[1], block_get(world, 1)));
	assert(equals(world->position_blocks_bottom[1], block_get(world, 1)));
	assert(equals(world->position_blocks_top[2], block_get(world, 2)));
	assert(equals(world->position_blocks_bottom[2], block_get(world, 2)));
	assert(block_get_stack(block_get(world, 1)) == 1);
	assert(block_get(world, 2)->next == NULL);
	assert(block_get(world, 2)->previous == NULL);
	assert(block_get(world, 1)->next == NULL);
	assert(block_get(world, 1)->previous == NULL);

	/* Tear down */
	world_delete(&world);
}
Ejemplo n.º 18
0
int process()
{
    BlockMediumInfo bmi;
    const char* dev_name;
    BlockOperations* bops;
    void* iterator = NULL;
    void* cd_devid;
    int res;
    #if TEST_BLOCK_DUMP
    unsigned long n;
    int fhandle;
    char filename[12];
    #endif
    #if TEST_GET_LAST_SESSION
    uint32_t last_session_address;
    #endif


    fd32_message("Searching for CD-ROM drives...\n");
    /* Search for all devices with name hd<letter> an test if they respond to FD32_ATAPI_INFO */
    while ((dev_name = block_enumerate(&iterator)) != NULL)
    {
        if (strncasecmp(dev_name, "cdrom", 5))
        {
            continue;
        }
        if (block_get(dev_name, BLOCK_OPERATIONS_TYPE, &bops, &cd_devid) < 0)
        {
            fd32_message("Error: Failed to get device data for device %s!\n", dev_name);
            return 1;
        }
        res = bops->open(cd_devid);
        if(res<0)
        {
            fd32_message("Device %s could not be mounted. No medium?\nReturned %i\n", dev_name, res);
            continue;
        }
        res = bops->get_medium_info(cd_devid, &bmi);
        if(res < 0)
        {
            fd32_message("Error: Block medium info failed for device %s\nReturned %i\n", dev_name, res);
            return 1;
        }
        if(bmi.block_bytes != 2048)
        {
            fd32_message("Error: Strange sector size %u\n", bmi.block_bytes);
            return 1;
        }
        fd32_message("Disk contains %llu sectors\n", bmi.blocks_count);
        #if TEST_GET_LAST_SESSION
        res = req_cd_get_last_session(bops->request, cd_devid, &last_session_address);
        if(res < 0)
        {
            fd32_message("Error: Get last session failed for device %s\nReturned %i\n", dev_name, res);
            return 1;
        }
        fd32_message("Last session start address: %08xh\n", last_session_address);
        #endif
        #if TEST_BLOCK_DUMP
        if(sectors_to_read >= bmi.blocks_count)
        {
            ksprintf(filename, "%s.iso", dev_name);
            sectors_to_read = bmi.blocks_count;
        }
        else
        {
            ksprintf(filename, "%s.dat", dev_name);
        }
        fd32_message("Going to write %lu bytes to file %s...\n", sectors_to_read * 2048, filename);
        fhandle = fd32_open(filename, O_CREAT | O_TRUNC | O_WRONLY, FD32_ANONE, 0, NULL);
        if(fhandle < 0)
        {
            fd32_message("Error: Unable to open file %s\n", filename);
            return 1;
        }
        for(n=0; n < sectors_to_read; n++)
        {
            fd32_log_printf("[CDTEST] Write sector %lu/%lu\n", n, sectors_to_read);
            res = bops->read(cd_devid, buffer, n, 1, 0);
            if(res < 0)
            {
                fd32_message("Error: Block read failed for device %s\nReturned %i\n", dev_name, res);
                //fd32_close(fhandle);
                return 1;
            }
            res = fd32_write(fhandle, buffer, 2048);
            if(res<0)
            {
                fd32_message("Error: unable to write to file\n");
                fd32_close(fhandle);
                return 1;
            }

        }
        fd32_close(fhandle);
        fd32_message("%lu sectors written to file %s\n", sectors_to_read, filename);
        #endif
    }
    return 0;
}