Index: trunk/kernel/syscalls/sys_readdir.c
===================================================================
--- trunk/kernel/syscalls/sys_readdir.c	(revision 473)
+++ trunk/kernel/syscalls/sys_readdir.c	(revision 611)
@@ -1,6 +1,6 @@
 /*
- * sys_readdir.c - Read one entry from an open directory.
+ * sys_readdir.c - Copy one entry from an open VFS directory to an user buffer.
  *
- * Author    Alain Greiner (2016,2017)
+ * Author    Alain Greiner (2016,2017,2018)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -30,4 +30,5 @@
 #include <vfs.h>
 #include <process.h>
+#include <remote_dir.h>
 #include <syscalls.h>
 #include <shared_syscalls.h>
@@ -35,7 +36,103 @@
 ///////////////////////////////////////
 int sys_readdir( DIR            * dirp,
-                 struct dirent ** dentp )
+                 struct dirent ** buffer )
 {
-    printk("\n[ERROR] in %s : not implemented yet\n", __FUNCTION__, dirp, dentp );
-    return -1;
+    error_t         error;
+    vseg_t        * vseg;               // for user space checking of buffer
+    xptr_t          dir_xp;             // extended pointer on remote_dir_t structure
+    remote_dir_t  * dir_ptr;            // local pointer on remote_dir_t structure
+    cxy_t           dir_cxy;            // remote_dir_t stucture cluster identifier
+    struct dirent * direntp;            // dirent pointer in user space  
+    uint32_t        entries;            // total number of dirent entries
+    uint32_t        current;            // current dirent index
+
+	thread_t  * this    = CURRENT_THREAD;  // client thread
+	process_t * process = this->process;   // client process
+
+#if (DEBUG_SYS_READDIR || CONFIG_INSTRUMENTATION_SYSCALLS)
+uint64_t     tm_start = hal_get_cycles();
+#endif
+
+#if DEBUG_SYS_READDIR
+if( DEBUG_SYS_READDIR < tm_start )
+printk("\n[%s] thread[%x,%x] enter / dirp %x / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, dirp, (uint32_t)tm_start );
+#endif
+ 
+    // check buffer in user space
+    error = vmm_get_vseg( process , (intptr_t)buffer, &vseg );
+
+	if( error )
+	{
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s / thread[%x,%x] : user buffer %x unmapped\n",
+__FUNCTION__ , process->pid , this->trdid, buffer );
+vmm_display( process , false );
+#endif
+		this->errno = EINVAL;
+		return -1;
+	}	
+
+    // get pointers on remote_dir_t structure from dirp
+    dir_xp  = remote_dir_from_ident( (intptr_t)dirp );
+    dir_ptr = GET_PTR( dir_xp );
+    dir_cxy = GET_CXY( dir_xp );
+
+    if( dir_xp == XPTR_NULL )
+	{
+
+#if DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s / thread[%x,%x] : dirp %x not registered\n",
+__FUNCTION__ , process->pid , this->trdid, dirp );
+#endif
+		this->errno = EBADF;
+		return -1;
+	}	
+
+    // get "current" and "entries_nr" values from remote_dir_t structure
+    current = hal_remote_l32( XPTR( dir_cxy , &dir_ptr->current ) );
+    entries = hal_remote_l32( XPTR( dir_cxy , &dir_ptr->entries ) );
+
+    // check "current" index
+    if( current >= entries )
+    {
+        this->errno = 0;
+        return -1;
+    }
+
+    // compute dirent pointer in user space
+    direntp = (struct dirent *)dirp + current;
+
+#if (DEBUG_SYS_READDIR & 1)
+if( DEBUG_SYS_READDIR < tm_start )
+printk("\n[%s] entries = %d / current = %d / direntp = %x\n",
+__FUNCTION__, entries, current, direntp );
+#endif
+
+    // copy dirent pointer to user buffer 
+    hal_copy_to_uspace( buffer, &direntp , sizeof(void *) );
+
+    // update current index in "remote_dir_t" structure
+    hal_remote_atomic_add( XPTR( dir_cxy , &dir_ptr->current ) , 1 );
+
+    hal_fence();
+
+#if (DEBUG_SYS_READDIR || CONFIG_INSTRUMENTATION_SYSCALLS)
+uint64_t     tm_end = hal_get_cycles();
+#endif
+
+#if DEBUG_SYS_READDIR
+if( DEBUG_SYS_READDIR < tm_end )
+printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
+#endif
+ 
+#if CONFIG_INSTRUMENTATION_SYSCALLS
+hal_atomic_add( &syscalls_cumul_cost[SYS_READDIR] , tm_end - tm_start );
+hal_atomic_add( &syscalls_occurences[SYS_READDIR] , 1 );
+#endif
+
+	return 0;
+
 }  // end sys_readdir()
