#include <u.h>
#include <libc.h>
#include <diskfs.h>

typedef struct DiskPart DiskPart;
struct DiskPart
{
	Disk disk;
	Disk *subdisk;
	u64int offset;
	u64int size;
};

static Block*
diskpartread(Disk *dd, u32int len, u64int offset)
{
	DiskPart *d = (DiskPart*)dd;

	if(offset+len > d->size){
		werrstr("read past end of partition %llud + %lud > %llud", offset, len, d->size);
		return nil;
	}
	return diskread(d->subdisk, len, offset+d->offset);
}

static int
diskpartsync(Disk *dd)
{
	DiskPart *d = (DiskPart*)dd;
	
	if(d->subdisk)
		return disksync(d->subdisk);
	return 0;
}

static void
diskpartclose(Disk *dd)
{
	DiskPart *d = (DiskPart*)dd;
	
	if(d->subdisk)
		diskclose(d->subdisk);
	free(d);
}

Disk*
diskpart(Disk *subdisk, u64int offset, u64int size)
{
	DiskPart *d;
	
	d = mallocz(sizeof(DiskPart), 1);
	if(d == nil)
		return nil;
	
	d->subdisk = subdisk;
	d->offset = offset;
	d->size = size;
	d->disk._read = diskpartread;
	d->disk._sync = diskpartsync;
	d->disk._close = diskpartclose;
	
	return &d->disk;
}

void
diskpartabandon(Disk *d)
{
	if(d->_read != diskpartread)
		abort();
	((DiskPart*)d)->subdisk = nil;
}