File system access library.
diff --git a/src/libdiskfs/file.c b/src/libdiskfs/file.c
new file mode 100644
index 0000000..b72f053
--- /dev/null
+++ b/src/libdiskfs/file.c
@@ -0,0 +1,99 @@
+#include <u.h>
+#include <libc.h>
+#include <diskfs.h>
+
+typedef struct DiskFile DiskFile;
+struct DiskFile
+{
+	Disk disk;
+	int fd;
+};
+
+int nfilereads;
+
+static long
+preadn(int fd, void *vdata, u32int ulen, u64int offset)
+{
+	long n;
+	uchar *data;
+	long len;
+
+	nfilereads++;
+	len = ulen;
+	data = vdata;
+//	fprint(2, "readn 0x%llux 0x%ux\n", offset, ulen);
+	while(len > 0){
+		n = pread(fd, data, len, offset);
+		if(n <= 0)
+			break;
+		data += n;
+		offset += n;
+		len -= n;
+	}
+	return data-(uchar*)vdata;
+}
+
+static void
+diskfileblockput(Block *b)
+{
+	free(b);
+}
+
+uvlong nreadx;
+static Block*
+diskfileread(Disk *dd, u32int len, u64int offset)
+{
+	int n;
+	Block *b;
+	DiskFile *d = (DiskFile*)dd;
+
+	b = mallocz(sizeof(Block)+len, 1);
+	if(b == nil)
+		return nil;
+	b->data = (uchar*)&b[1];
+nreadx += len;
+	n = preadn(d->fd, b->data, len, offset);
+	if(n <= 0){
+		free(b);
+		return nil;
+	}
+	b->_close = diskfileblockput;
+	b->len = n;
+	return b;
+}
+
+static int
+diskfilesync(Disk *dd)
+{
+	USED(dd);
+	return 0;
+}
+
+static void
+diskfileclose(Disk *dd)
+{
+	DiskFile *d = (DiskFile*)dd;
+
+	close(d->fd);
+	free(d);
+}
+
+Disk*
+diskopenfile(char *file)
+{
+	int fd;
+	DiskFile *d;
+
+	if((fd = open(file, OREAD)) < 0)
+		return nil;
+	d = mallocz(sizeof(DiskFile), 1);
+	if(d == nil){
+		close(fd);
+		return nil;
+	}
+	d->disk._read = diskfileread;
+	d->disk._sync = diskfilesync;
+	d->disk._close = diskfileclose;
+	d->fd = fd;
+	return &d->disk;
+}