Index: uspace/lib/libc/generic/vfs/vfs.c
===================================================================
--- uspace/lib/libc/generic/vfs/vfs.c	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/lib/libc/generic/vfs/vfs.c	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -39,6 +39,6 @@
 #include <dirent.h>
 #include <fcntl.h>
+#include <stdio.h>
 #include <sys/stat.h>
-#include <stdio.h>
 #include <sys/types.h>
 #include <ipc/ipc.h>
@@ -315,46 +315,4 @@
 }
 
-int fd_phone(int fildes)
-{
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
-	
-	ipcarg_t device;
-	ipcarg_t rc = async_req_1_1(vfs_phone, VFS_IN_DEVICE, fildes, &device);
-	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
-	
-	if (rc != EOK)
-		return -1;
-	
-	return devmap_device_connect((dev_handle_t) device, 0);
-}
-
-int fd_node(int fildes, fdi_node_t *node)
-{
-	futex_down(&vfs_phone_futex);
-	async_serialize_start();
-	vfs_connect();
-	
-	ipcarg_t fs_handle;
-	ipcarg_t dev_handle;
-	ipcarg_t index;
-	ipcarg_t rc = async_req_1_3(vfs_phone, VFS_IN_NODE, fildes, &fs_handle,
-	    &dev_handle, &index);
-	
-	async_serialize_end();
-	futex_up(&vfs_phone_futex);
-	
-	if (rc == EOK) {
-		node->fs_handle = (fs_handle_t) fs_handle;
-		node->dev_handle = (dev_handle_t) dev_handle;
-		node->index = (fs_index_t) index;
-	}
-	
-	return rc;
-}
-
 int fsync(int fildes)
 {
@@ -404,4 +362,29 @@
 	futex_up(&vfs_phone_futex);
 	return (int) rc;
+}
+
+int fstat(int fildes, struct stat *stat)
+{
+	ipcarg_t rc;
+	ipc_call_t answer;
+	aid_t req;
+
+	futex_down(&vfs_phone_futex);
+	async_serialize_start();
+	vfs_connect();
+	
+	req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
+	rc = ipc_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat));
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		async_serialize_end();
+		futex_up(&vfs_phone_futex);
+		return (ssize_t) rc;
+	}
+	async_wait_for(req, &rc);
+	async_serialize_end();
+	futex_up(&vfs_phone_futex);
+
+	return rc;
 }
 
@@ -599,4 +582,33 @@
 }
 
+int fd_phone(int fildes)
+{
+	struct stat stat;
+	int rc;
+
+	rc = fstat(fildes, &stat);
+
+	if (!stat.devfs_stat.device)
+		return -1;
+	
+	return devmap_device_connect(stat.devfs_stat.device, 0);
+}
+
+int fd_node(int fildes, fdi_node_t *node)
+{
+	struct stat stat;
+	int rc;
+
+	rc = fstat(fildes, &stat);
+	
+	if (rc == EOK) {
+		node->fs_handle = stat.fs_handle;
+		node->dev_handle = stat.dev_handle;
+		node->index = stat.index;
+	}
+	
+	return rc;
+}
+
 /** @}
  */
Index: uspace/lib/libc/include/ipc/vfs.h
===================================================================
--- uspace/lib/libc/include/ipc/vfs.h	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/lib/libc/include/ipc/vfs.h	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -64,4 +64,5 @@
 	VFS_IN_SEEK,
 	VFS_IN_TRUNCATE,
+	VFS_IN_FSTAT,
 	VFS_IN_CLOSE,
 	VFS_IN_MOUNT,
@@ -73,4 +74,5 @@
 	VFS_IN_UNLINK,
 	VFS_IN_RENAME,
+	VFS_IN_STAT,
 	VFS_IN_NODE
 } vfs_in_request_t;
@@ -87,4 +89,5 @@
 	VFS_OUT_DEVICE,
 	VFS_OUT_SYNC,
+	VFS_OUT_STAT,
 	VFS_OUT_LOOKUP,
 	VFS_OUT_DESTROY,
Index: uspace/lib/libc/include/sys/stat.h
===================================================================
--- uspace/lib/libc/include/sys/stat.h	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/lib/libc/include/sys/stat.h	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -37,5 +37,23 @@
 
 #include <sys/types.h>
+#include <bool.h>
+#include <ipc/vfs.h>
+#include <ipc/devmap.h>
 
+struct stat {
+	fs_handle_t	fs_handle;
+	dev_handle_t	dev_handle;
+	fs_index_t	index;
+	unsigned	lnkcnt;
+	bool		is_file;
+	off_t		size;
+	union {
+		struct {
+			dev_handle_t	device;
+		} devfs_stat;
+	};
+};
+
+extern int fstat(int, struct stat *);
 extern int mkdir(const char *, mode_t);
 
Index: uspace/srv/fs/devfs/devfs.c
===================================================================
--- uspace/srv/fs/devfs/devfs.c	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/fs/devfs/devfs.c	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -80,6 +80,6 @@
 			devfs_open_node(callid, &call);
 			break;
-		case VFS_OUT_DEVICE:
-			devfs_device(callid, &call);
+		case VFS_OUT_STAT:
+			devfs_stat(callid, &call);
 			break;
 		case VFS_OUT_READ:
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -44,4 +44,5 @@
 #include <fibril_sync.h>
 #include <adt/hash_table.h>
+#include <sys/stat.h>
 #include "devfs.h"
 #include "devfs_ops.h"
@@ -278,7 +279,32 @@
 }
 
-void devfs_device(ipc_callid_t rid, ipc_call_t *request)
-{
+void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
+{
+	dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
 	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!ipc_data_read_receive(&callid, &size) ||
+	    size < sizeof(struct stat)) {
+		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(rid, EINVAL);
+		return;
+	}
+
+	struct stat *stat = malloc(sizeof(struct stat));
+	if (!stat) {
+		ipc_answer_0(callid, ENOMEM);
+		ipc_answer_0(rid, ENOMEM);
+		return;
+	}
+	memset(stat, 0, sizeof(struct stat));
+
+	stat->fs_handle = devfs_reg.fs_handle;
+	stat->dev_handle = dev_handle;
+	stat->index = index;
+	stat->lnkcnt = 1;
+	stat->is_file = (index != 0);
+	stat->size = 0;
 	
 	if (index != 0) {
@@ -289,14 +315,13 @@
 		fibril_mutex_lock(&devices_mutex);
 		link_t *lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			fibril_mutex_unlock(&devices_mutex);
-			ipc_answer_0(rid, ENOENT);
-			return;
-		}
+		if (lnk != NULL) 
+			stat->devfs_stat.device = (dev_handle_t)index;
 		fibril_mutex_unlock(&devices_mutex);
-		
-		ipc_answer_1(rid, EOK, (ipcarg_t) index);
-	} else
-		ipc_answer_0(rid, ENOTSUP);
+	}
+
+	ipc_data_read_finalize(callid, stat, sizeof(struct stat));
+	ipc_answer_0(rid, EOK);
+
+	free(stat);
 }
 
Index: uspace/srv/fs/devfs/devfs_ops.h
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.h	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/fs/devfs/devfs_ops.h	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -43,5 +43,5 @@
 extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
 extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void devfs_device(ipc_callid_t, ipc_call_t *);
+extern void devfs_stat(ipc_callid_t, ipc_call_t *);
 extern void devfs_sync(ipc_callid_t, ipc_call_t *);
 extern void devfs_read(ipc_callid_t, ipc_call_t *);
Index: uspace/srv/fs/fat/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/fs/fat/fat.c	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -110,4 +110,7 @@
 			fat_truncate(callid, &call);
 			break;
+		case VFS_OUT_STAT:
+			fat_stat(callid, &call);
+			break;
 		case VFS_OUT_CLOSE:
 			fat_close(callid, &call);
@@ -118,7 +121,4 @@
 		case VFS_OUT_OPEN_NODE:
 			fat_open_node(callid, &call);
-			break;
-		case VFS_OUT_DEVICE:
-			fat_device(callid, &call);
 			break;
 		case VFS_OUT_SYNC:
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/fs/fat/fat.h	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -208,8 +208,9 @@
 extern void fat_write(ipc_callid_t, ipc_call_t *);
 extern void fat_truncate(ipc_callid_t, ipc_call_t *);
+extern void fat_stat(ipc_callid_t, ipc_call_t *);
 extern void fat_close(ipc_callid_t, ipc_call_t *);
 extern void fat_destroy(ipc_callid_t, ipc_call_t *);
 extern void fat_open_node(ipc_callid_t, ipc_call_t *);
-extern void fat_device(ipc_callid_t, ipc_call_t *);
+extern void fat_stat(ipc_callid_t, ipc_call_t *);
 extern void fat_sync(ipc_callid_t, ipc_call_t *);
 
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -1203,5 +1203,5 @@
 }
 
-void fat_device(ipc_callid_t rid, ipc_call_t *request)
+void fat_stat(ipc_callid_t rid, ipc_call_t *request)
 {
 	ipc_answer_0(rid, ENOTSUP);
Index: uspace/srv/fs/tmpfs/tmpfs.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.c	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -126,6 +126,6 @@
 			tmpfs_open_node(callid, &call);
 			break;
-		case VFS_OUT_DEVICE:
-			tmpfs_device(callid, &call);
+		case VFS_OUT_STAT:
+			tmpfs_stat(callid, &call);
 			break;
 		case VFS_OUT_SYNC:
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -87,8 +87,8 @@
 extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
 extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *);
+extern void tmpfs_stat(ipc_callid_t, ipc_call_t *);
 extern void tmpfs_close(ipc_callid_t, ipc_call_t *);
 extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *);
 extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_device(ipc_callid_t, ipc_call_t *);
 extern void tmpfs_sync(ipc_callid_t, ipc_call_t *);
 
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -629,5 +629,5 @@
 }
 
-void tmpfs_device(ipc_callid_t rid, ipc_call_t *request)
+void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request)
 {
 	ipc_answer_0(rid, ENOTSUP);
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/vfs/vfs.c	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -108,4 +108,10 @@
 			vfs_truncate(callid, &call);
 			break;
+		case VFS_IN_FSTAT:
+			vfs_fstat(callid, &call);
+			break;
+		case VFS_IN_STAT:
+			vfs_stat(callid, &call);
+			break;
 		case VFS_IN_MKDIR:
 			vfs_mkdir(callid, &call);
@@ -117,12 +123,6 @@
 			vfs_rename(callid, &call);
 			break;
-		case VFS_IN_DEVICE:
-			vfs_device(callid, &call);
-			break;
 		case VFS_IN_SYNC:
 			vfs_sync(callid, &call);
-			break;
-		case VFS_IN_NODE:
-			vfs_node(callid, &call);
 			break;
 		default:
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/vfs/vfs.h	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -199,7 +199,5 @@
 extern void vfs_open(ipc_callid_t, ipc_call_t *);
 extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void vfs_device(ipc_callid_t, ipc_call_t *);
 extern void vfs_sync(ipc_callid_t, ipc_call_t *);
-extern void vfs_node(ipc_callid_t, ipc_call_t *);
 extern void vfs_close(ipc_callid_t, ipc_call_t *);
 extern void vfs_read(ipc_callid_t, ipc_call_t *);
@@ -207,4 +205,7 @@
 extern void vfs_seek(ipc_callid_t, ipc_call_t *);
 extern void vfs_truncate(ipc_callid_t, ipc_call_t *);
+extern void vfs_fstat(ipc_callid_t, ipc_call_t *);
+extern void vfs_fstat(ipc_callid_t, ipc_call_t *);
+extern void vfs_stat(ipc_callid_t, ipc_call_t *);
 extern void vfs_mkdir(ipc_callid_t, ipc_call_t *);
 extern void vfs_unlink(ipc_callid_t, ipc_call_t *);
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 4198f9c3ae7988eea2c8a649c01af1be31ded05d)
+++ uspace/srv/vfs/vfs_ops.c	(revision 852b80130e0f28124d72af653ed0aef959db3053)
@@ -642,53 +642,4 @@
 }
 
-void vfs_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	int fd = IPC_GET_ARG1(*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;
-	}
-	
-	ipc_answer_3(rid, EOK, file->node->fs_handle, file->node->dev_handle,
-	    file->node->index);
-}
-
-void vfs_device(ipc_callid_t rid, ipc_call_t *request)
-{
-	int fd = IPC_GET_ARG1(*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;
-	}
-	
-	/*
-	 * Lock the open file structure so that no other thread can manipulate
-	 * the same open file at a time.
-	 */
-	fibril_mutex_lock(&file->lock);
-	int fs_phone = vfs_grab_phone(file->node->fs_handle);
-	
-	/* Make a VFS_OUT_DEVICE request at the destination FS server. */
-	aid_t msg;
-	ipc_call_t answer;
-	msg = async_send_2(fs_phone, VFS_OUT_DEVICE, file->node->dev_handle,
-	    file->node->index, &answer);
-
-	/* Wait for reply from the FS server. */
-	ipcarg_t rc;
-	async_wait_for(msg, &rc);
-
-	vfs_release_phone(fs_phone);
-	fibril_mutex_unlock(&file->lock);
-	
-	ipc_answer_1(rid, EOK, IPC_GET_ARG1(answer));
-}
-
 void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
 {
@@ -975,4 +926,42 @@
 	fibril_mutex_unlock(&file->lock);
 	ipc_answer_0(rid, (ipcarg_t)rc);
+}
+
+void vfs_fstat(ipc_callid_t rid, ipc_call_t *request)
+{
+	int fd = IPC_GET_ARG1(*request);
+	size_t size = IPC_GET_ARG2(*request);
+	ipcarg_t rc;
+
+	vfs_file_t *file = vfs_file_get(fd);
+	if (!file) {
+		ipc_answer_0(rid, ENOENT);
+		return;
+	}
+
+	ipc_callid_t callid;
+	if (!ipc_data_read_receive(&callid, NULL)) {
+		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(rid, EINVAL);
+		return;
+	}
+
+	fibril_mutex_lock(&file->lock);
+
+	int fs_phone = vfs_grab_phone(file->node->fs_handle);
+	
+	aid_t msg;
+	msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->dev_handle,
+	    file->node->index, true, NULL);
+	ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	async_wait_for(msg, &rc);
+	vfs_release_phone(fs_phone);
+
+	fibril_mutex_unlock(&file->lock);
+	ipc_answer_0(rid, rc);
+}
+
+void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
+{
 }
 
