Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 10d6b8581001bd7ee48d03024e92ffbc0a7f49e3)
+++ uspace/srv/vfs/vfs.c	(revision 41a0d27303c8ba364f016cb27a8fb82af5194dac)
@@ -100,8 +100,10 @@
 			vfs_write(callid, &call);
 			break;
+		case VFS_SEEK:
+			vfs_seek(callid, &call);
+			break;
 		case VFS_UNMOUNT:
 		case VFS_CREATE:
 		case VFS_CLOSE:
-		case VFS_SEEK:
 		case VFS_UNLINK:
 		case VFS_RENAME:
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 10d6b8581001bd7ee48d03024e92ffbc0a7f49e3)
+++ uspace/srv/vfs/vfs.h	(revision 41a0d27303c8ba364f016cb27a8fb82af5194dac)
@@ -136,4 +136,5 @@
 	unsigned refcnt;	/**< Usage counter. */
 	link_t nh_link;		/**< Node hash-table link. */
+	size_t size;		/**< Cached size of the file. */
 
 	/**
@@ -211,4 +212,5 @@
 extern void vfs_read(ipc_callid_t, ipc_call_t *);
 extern void vfs_write(ipc_callid_t, ipc_call_t *);
+extern void vfs_seek(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/vfs/vfs_rdwr.c
===================================================================
--- uspace/srv/vfs/vfs_rdwr.c	(revision 10d6b8581001bd7ee48d03024e92ffbc0a7f49e3)
+++ uspace/srv/vfs/vfs_rdwr.c	(revision 41a0d27303c8ba364f016cb27a8fb82af5194dac)
@@ -41,4 +41,5 @@
 #include <errno.h>
 #include <rwlock.h>
+#include <unistd.h>
 
 static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
@@ -156,4 +157,58 @@
 }
 
+void vfs_seek(ipc_callid_t rid, ipc_call_t *request)
+{
+	int fd = (int) IPC_GET_ARG1(*request);
+	off_t off = (off_t) IPC_GET_ARG2(*request);
+	int whence = (int) IPC_GET_ARG3(*request);
+
+
+	/*
+	 * Lookup the file structure corresponding to the file descriptor.
+	 */
+	vfs_file_t *file = vfs_file_get(fd);
+	if (!file) {
+		ipc_answer_0(rid, ENOENT);
+		return;
+	}
+
+	off_t newpos;
+	futex_down(&file->lock);
+	if (whence == SEEK_SET) {
+		file->pos = off;
+		futex_up(&file->lock);
+		ipc_answer_1(rid, EOK, off);
+		return;
+	}
+	if (whence == SEEK_CUR) {
+		if (file->pos + off < file->pos) {
+			futex_up(&file->lock);
+			ipc_answer_0(rid, EOVERFLOW);
+			return;
+		}
+		file->pos += off;
+		newpos = file->pos;
+		futex_up(&file->lock);
+		ipc_answer_1(rid, EOK, newpos);
+		return;
+	}
+	if (whence == SEEK_END) {
+		rwlock_reader_lock(&file->node->contents_rwlock);
+		size_t size = file->node->size;
+		rwlock_reader_unlock(&file->node->contents_rwlock);
+		if (size + off < size) {
+			futex_up(&file->lock);
+			ipc_answer_0(rid, EOVERFLOW);
+			return;
+		}
+		newpos = size + off;
+		futex_up(&file->lock);
+		ipc_answer_1(rid, EOK, newpos);
+		return;
+	}
+	futex_up(&file->lock);
+	ipc_answer_0(rid, EINVAL);
+}
+
 /**
  * @}
