static inline int64_t get_sector_offset(BlockDriverState *bs,

    int64_t sector_num, int write)

{

    BDRVVPCState *s = bs->opaque;

    uint64_t offset = sector_num * 512;

    uint64_t bitmap_offset, block_offset;

    uint32_t pagetable_index, pageentry_index;



    pagetable_index = offset / s->block_size;

    pageentry_index = (offset % s->block_size) / 512;



    if (pagetable_index >= s->max_table_entries || s->pagetable[pagetable_index] == 0xffffffff)

        return -1; // not allocated



    bitmap_offset = 512 * (uint64_t) s->pagetable[pagetable_index];

    block_offset = bitmap_offset + s->bitmap_size + (512 * pageentry_index);



    // We must ensure that we don't write to any sectors which are marked as

    // unused in the bitmap. We get away with setting all bits in the block

    // bitmap each time we write to a new block. This might cause Virtual PC to

    // miss sparse read optimization, but it's not a problem in terms of

    // correctness.

    if (write && (s->last_bitmap_offset != bitmap_offset)) {

        uint8_t bitmap[s->bitmap_size];



        s->last_bitmap_offset = bitmap_offset;

        memset(bitmap, 0xff, s->bitmap_size);

        bdrv_pwrite(bs->file, bitmap_offset, bitmap, s->bitmap_size);

    }



//    printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",

//	sector_num, pagetable_index, pageentry_index,

//	bitmap_offset, block_offset);



// disabled by reason

#if 0

#ifdef CACHE

    if (bitmap_offset != s->last_bitmap)

    {

	lseek(s->fd, bitmap_offset, SEEK_SET);



	s->last_bitmap = bitmap_offset;



	// Scary! Bitmap is stored as big endian 32bit entries,

	// while we used to look it up byte by byte

	read(s->fd, s->pageentry_u8, 512);

	for (i = 0; i < 128; i++)

	    be32_to_cpus(&s->pageentry_u32[i]);

    }



    if ((s->pageentry_u8[pageentry_index / 8] >> (pageentry_index % 8)) & 1)

	return -1;

#else

    lseek(s->fd, bitmap_offset + (pageentry_index / 8), SEEK_SET);



    read(s->fd, &bitmap_entry, 1);



    if ((bitmap_entry >> (pageentry_index % 8)) & 1)

	return -1; // not allocated

#endif

#endif



    return block_offset;

}
