add fsseek
diff --git a/include/9pclient.h b/include/9pclient.h
index 8a0d342..e8beed4 100644
--- a/include/9pclient.h
+++ b/include/9pclient.h
@@ -22,6 +22,9 @@
 int fsopenfd(CFsys*, char*, int);
 long fsread(CFid*, void*, long);
 long fsreadn(CFid*, void*, long);
+long fspread(CFid*, void*, long, vlong);
+long fspwrite(CFid*, void*, long, vlong);
+vlong fsseek(CFid*, vlong, int);
 long fswrite(CFid*, void*, long);
 void fsclose(CFid*);
 void fsunmount(CFsys*);
diff --git a/src/lib9pclient/mkfile b/src/lib9pclient/mkfile
index c6bbc7d..097f20a 100644
--- a/src/lib9pclient/mkfile
+++ b/src/lib9pclient/mkfile
@@ -11,6 +11,7 @@
 	open.$O\
 	openfd.$O\
 	read.$O\
+	seek.$O\
 	stat.$O\
 	walk.$O\
 	write.$O\
diff --git a/src/lib9pclient/seek.c b/src/lib9pclient/seek.c
new file mode 100644
index 0000000..0785c4b
--- /dev/null
+++ b/src/lib9pclient/seek.c
@@ -0,0 +1,46 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <9pclient.h>
+#include "fsimpl.h"
+
+vlong
+fsseek(CFid *fid, vlong n, int whence)
+{
+	Dir *d;
+
+	switch(whence){
+	case 0:
+		qlock(&fid->lk);
+		fid->offset = n;
+		qunlock(&fid->lk);
+		break;
+	case 1:
+		qlock(&fid->lk);
+		n += fid->offset;
+		if(n < 0){
+			qunlock(&fid->lk);
+			werrstr("negative offset");
+			return -1;
+		}
+		fid->offset = n;
+		qunlock(&fid->lk);
+		break;
+	case 2:
+		if((d = fsdirfstat(fid)) == nil)
+			return -1;
+		n += d->length;
+		if(n < 0){
+			werrstr("negative offset");
+			return -1;
+		}
+		qlock(&fid->lk);
+		fid->offset = n;
+		qunlock(&fid->lk);
+		break;
+	default:
+		werrstr("bad whence in fsseek");
+		return -1;
+	}
+	return n;
+}