From 8a91fe69f852d9c98ea9989d276e9191bf5a8901 Mon Sep 17 00:00:00 2001
From: Terraneo Federico <fede.tft@hotmail.it>
Date: Sun, 6 Oct 2013 22:02:11 +0000
Subject: [PATCH] Implemented mkdir(), unlink() and rename()

---
 miosix/Makefile                               |  1 -
 miosix/_doc/textdoc/Changelog.txt             |  7 ++
 miosix/_tools/compiler/patches/newlib.patch   |  2 +-
 miosix/_tools/testsuite/testsuite.cpp         | 81 +++++++++++++++++++
 miosix/filesystem/devfs/devfs.cpp             | 21 +++++
 miosix/filesystem/devfs/devfs.h               | 15 ++++
 miosix/filesystem/file.h                      | 15 ++++
 miosix/filesystem/file_access.cpp             | 66 +++++++++++++++
 miosix/filesystem/file_access.h               | 42 ++++++++++
 .../filesystem/mountpointfs/mountpointfs.cpp  | 20 +++++
 miosix/filesystem/mountpointfs/mountpointfs.h | 15 ++++
 miosix/kernel/unistd.cpp                      | 63 ---------------
 .../stdlib_integration/libc_integration.cpp   | 72 ++++++++++++++---
 miosix_np_2/nbproject/configurations.xml      | 27 -------
 .../nbproject/private/configurations.xml      |  1 -
 15 files changed, 346 insertions(+), 102 deletions(-)
 delete mode 100644 miosix/kernel/unistd.cpp

diff --git a/miosix/Makefile b/miosix/Makefile
index b5e4ef4f..54e1ecdb 100644
--- a/miosix/Makefile
+++ b/miosix/Makefile
@@ -14,7 +14,6 @@ kernel/kernel.cpp                                                          \
 kernel/sync.cpp                                                            \
 kernel/error.cpp                                                           \
 kernel/pthread.cpp                                                         \
-kernel/unistd.cpp                                                          \
 kernel/stage_2_boot.cpp                                                    \
 kernel/scheduler/priority/priority_scheduler.cpp                           \
 kernel/scheduler/control/control_scheduler.cpp                             \
diff --git a/miosix/_doc/textdoc/Changelog.txt b/miosix/_doc/textdoc/Changelog.txt
index 57ae1f92..516d6f63 100644
--- a/miosix/_doc/textdoc/Changelog.txt
+++ b/miosix/_doc/textdoc/Changelog.txt
@@ -1,5 +1,12 @@
 Changelog for Miosix np embedded OS
 
+- Implemented the nanosleep() syscall to support sleep() and usleep().
+- Removed kernel/unistd.cpp as we're now relying in the implementation of
+  sleep() and usleep() in newlib.
+- Fixed newlib patch to add HAVE_NANOSLEEP, as it was omitted by mistake.
+  This change requires recompiling GCC!
+- File abstraction layer: added support for mkdir(), unlink() and rename()
+  syscalls.
 - File abstraction layer: added testsuite test for directory listing.
   Also removed two tests from the testsuite related to the old Filesystem
   and Directory classes.
diff --git a/miosix/_tools/compiler/patches/newlib.patch b/miosix/_tools/compiler/patches/newlib.patch
index 3e91dd82..eba1160c 100644
--- a/miosix/_tools/compiler/patches/newlib.patch
+++ b/miosix/_tools/compiler/patches/newlib.patch
@@ -28,7 +28,7 @@ diff -ruN newlib-2.0.0-old/newlib/configure.host newlib-2.0.0/newlib/configure.h
 +# _NO_WORDEXP: no wordexp() support in Miosix (missing fork())
 +# _SMALL_HEXDIG: save 256 byte of RAM in stdlib/gdtoa-gethex.c
 +# SIGNAL_PROVIDED: disable the implementation of signals in newlib
-+	newlib_cflags="${newlib_cflags} -DREENTRANT_SYSCALLS_PROVIDED -DHAVE_BLKSIZE -DHAVE_FCNTL -D_NO_POPEN -D_NO_WORDEXP -D_SMALL_HEXDIG -DSIGNAL_PROVIDED"
++	newlib_cflags="${newlib_cflags} -DREENTRANT_SYSCALLS_PROVIDED -DHAVE_BLKSIZE -DHAVE_FCNTL -DHAVE_NANOSLEEP -D_NO_POPEN -D_NO_WORDEXP -D_SMALL_HEXDIG -DSIGNAL_PROVIDED"
 +	newlib_cflags="${newlib_cflags} -Wall"
 +	;;
  # RTEMS supplies its own versions of some routines:
diff --git a/miosix/_tools/testsuite/testsuite.cpp b/miosix/_tools/testsuite/testsuite.cpp
index 7ddeb996..cb62ddca 100644
--- a/miosix/_tools/testsuite/testsuite.cpp
+++ b/miosix/_tools/testsuite/testsuite.cpp
@@ -99,6 +99,7 @@ static void test_24();
 //Filesystem test functions
 #ifdef WITH_FILESYSTEM
 static void fs_test_1();
+static void fs_test_2();
 static void fs_test_3();
 static void fs_test_4();
 #endif //WITH_FILESYSTEM
@@ -169,6 +170,7 @@ int main()
                 ledOn();
                 #ifdef WITH_FILESYSTEM
                 fs_test_1();
+                fs_test_2();
                 fs_test_3();
                 fs_test_4();
                 #else //WITH_FILESYSTEM
@@ -3649,6 +3651,85 @@ static void fs_test_1()
     pass();
 }
 
+//
+// Filesystem test 2
+//
+/*
+tests:
+mkdir/unlink/rename
+*/
+
+/**
+ * \param d scan the content of this directory
+ * \param a if not null, this file must be in the directory
+ * \param b if not null, this file most not be in the directory
+ * \return true on success, false on failure
+ */
+static bool checkDirContent(const std::string& d, const char *a, const char *b)
+{
+    DIR *dir=opendir(d.c_str());
+    bool found=false;
+    for(;;)
+    {
+        struct dirent *de=readdir(dir);
+        if(de==NULL) break;
+        if(a && !strcmp(de->d_name,a)) found=true;
+        if(b && !strcmp(de->d_name,b))
+        {
+            closedir(dir);
+            return false;
+        }
+    }
+    closedir(dir);
+    if(a) return found; else return true;
+}
+
+static void checkInDir(const std::string& d, bool createFile)
+{
+    using namespace std;
+    const char dirname1[]="test1";
+    if(mkdir((d+dirname1).c_str(),0755)!=0) fail("mkdir");
+    if(checkDirContent(d,dirname1,0)==false) fail("mkdir 2");
+    const char dirname2[]="test2";
+    if(rename((d+dirname1).c_str(),(d+dirname2).c_str())) fail("rename");
+    if(checkDirContent(d,dirname2,dirname1)==false) fail("rename 2");
+    if(remove((d+dirname2).c_str())) fail("remove");
+    if(checkDirContent(d,0,dirname2)==false) fail("remove 2");
+    
+    if(createFile==false) return;
+    const char filename1[]="test.txt";
+    FILE *f;
+    if((f=fopen((d+filename1).c_str(),"w"))==NULL) fail("fopen");
+    const char teststr[]="Testing\n";
+    fputs(teststr,f);
+    fclose(f);
+    if(checkDirContent(d,filename1,0)==false) fail("fopen 2");
+    const char filename2[]="test2.txt";
+    if(rename((d+filename1).c_str(),(d+filename2).c_str())) fail("rename 3");
+    if(checkDirContent(d,filename2,filename1)==false) fail("rename 4");
+    if((f=fopen((d+filename2).c_str(),"r"))==NULL) fail("fopen");
+    char s[32];
+    fgets(s,sizeof(s),f);
+    if(strcmp(s,teststr)) fail("file content after rename");
+    fclose(f);
+    if(remove((d+filename2).c_str())) fail("remove 3");
+    if(checkDirContent(d,0,filename2)==false) fail("remove 4");
+}
+
+static void fs_test_2()
+{
+    test_name("mkdir/rename/unlink");
+    checkInDir("/",false);
+    DIR *d=opendir("/sd");
+    if(d!=NULL)
+    {
+        // the /sd mountpoint exists, check mkdir/rename/unlink also here
+        closedir(d);
+        checkInDir("/sd/",true);
+    }
+    pass();
+}
+
 //
 // Filesystem test 3
 //
diff --git a/miosix/filesystem/devfs/devfs.cpp b/miosix/filesystem/devfs/devfs.cpp
index 6fef3966..76fdd864 100644
--- a/miosix/filesystem/devfs/devfs.cpp
+++ b/miosix/filesystem/devfs/devfs.cpp
@@ -153,6 +153,27 @@ int DevFs::lstat(StringPart& name, struct stat *pstat)
     return it->second.lstat(pstat);
 }
 
+int DevFs::unlink(StringPart& name)
+{
+    Lock<FastMutex> l(mutex);
+    if(files.erase(name)==1) return 0;
+    return -ENOENT;
+}
+
+int DevFs::rename(StringPart& oldName, StringPart& newName)
+{
+    Lock<FastMutex> l(mutex);
+    map<StringPart,DeviceFileWrapper>::iterator it=files.find(oldName);
+    if(it==files.end()) return -ENOENT;
+    for(unsigned int i=0;i<newName.length();i++)
+        if(newName[i]=='/')
+            return -EACCES; //DevFs does not support subdirectories
+    files.erase(newName); //If it exists
+    files.insert(make_pair(newName,it->second));
+    files.erase(it);
+    return 0;
+}
+
 int DevFs::mkdir(StringPart& name, int mode)
 {
     return -EACCES; // No directories support in DevFs yet
diff --git a/miosix/filesystem/devfs/devfs.h b/miosix/filesystem/devfs/devfs.h
index 80577601..ea52e27a 100644
--- a/miosix/filesystem/devfs/devfs.h
+++ b/miosix/filesystem/devfs/devfs.h
@@ -264,6 +264,21 @@ public:
      * \return 0 on success, or a negative number on failure
      */
     virtual int lstat(StringPart& name, struct stat *pstat);
+    
+    /**
+     * Remove a file or directory
+     * \param name path name of file or directory to remove
+     * \return 0 on success, or a negative number on failure
+     */
+    virtual int unlink(StringPart& name);
+    
+    /**
+     * Rename a file or directory
+     * \param oldName old file name
+     * \param newName new file name
+     * \return 0 on success, or a negative number on failure
+     */
+    virtual int rename(StringPart& oldName, StringPart& newName);
      
     /**
      * Create a directory
diff --git a/miosix/filesystem/file.h b/miosix/filesystem/file.h
index 53236947..8cc82fad 100644
--- a/miosix/filesystem/file.h
+++ b/miosix/filesystem/file.h
@@ -267,6 +267,21 @@ public:
      */
     virtual int lstat(StringPart& name, struct stat *pstat)=0;
     
+    /**
+     * Remove a file or directory
+     * \param name path name of file or directory to remove
+     * \return 0 on success, or a negative number on failure
+     */
+    virtual int unlink(StringPart& name)=0;
+    
+    /**
+     * Rename a file or directory
+     * \param oldName old file name
+     * \param newName new file name
+     * \return 0 on success, or a negative number on failure
+     */
+    virtual int rename(StringPart& oldName, StringPart& newName)=0;
+    
     /**
      * Create a directory
      * \param name directory name
diff --git a/miosix/filesystem/file_access.cpp b/miosix/filesystem/file_access.cpp
index 87b5561c..7cb2be35 100644
--- a/miosix/filesystem/file_access.cpp
+++ b/miosix/filesystem/file_access.cpp
@@ -167,6 +167,35 @@ int FileDescriptorTable::chdir(const char* name)
     return 0;
 }
 
+int FileDescriptorTable::mkdir(const char *name, int mode)
+{
+    if(name==0 || name[0]=='\0') return -EFAULT;
+    string path=absolutePath(name);
+    if(path.empty()) return -ENAMETOOLONG;
+    ResolvedPath openData=FilesystemManager::instance().resolvePath(path,true);
+    if(openData.result<0) return openData.result;
+    StringPart sp(path,string::npos,openData.off);
+    return openData.fs->mkdir(sp,mode);
+}
+
+int FileDescriptorTable::unlink(const char *name)
+{
+    if(name==0 || name[0]=='\0') return -EFAULT;
+    string path=absolutePath(name);
+    if(path.empty()) return -ENAMETOOLONG;
+    return FilesystemManager::instance().unlinkHelper(path);
+}
+
+int FileDescriptorTable::rename(const char *oldName, const char *newName)
+{
+    if(oldName==0 || oldName[0]=='\0') return -EFAULT;
+    if(newName==0 || newName[0]=='\0') return -EFAULT;
+    string oldPath=absolutePath(oldName);
+    string newPath=absolutePath(newName);
+    if(oldPath.empty() || newPath.empty()) return -ENAMETOOLONG;
+    return FilesystemManager::instance().renameHelper(oldPath,newPath);
+}
+
 int FileDescriptorTable::statImpl(const char* name, struct stat* pstat, bool f)
 {
     if(name==0 || name[0]=='\0') return -EFAULT;
@@ -596,6 +625,43 @@ ResolvedPath FilesystemManager::resolvePath(string& path, bool followLastSymlink
     return pr.resolvePath(path,followLastSymlink);
 }
 
+int FilesystemManager::unlinkHelper(string& path)
+{
+    //Do everything while keeping the mutex locked to prevent someone to
+    //concurrently mount a filesystem on the directory we're unlinking
+    Lock<FastMutex> l(mutex);
+    ResolvedPath openData=resolvePath(path,true);
+    if(openData.result<0) return openData.result;
+    //After resolvePath() so path is in canonical form and symlinks are followed
+    if(filesystems.find(StringPart(path))!=filesystems.end()) return -EBUSY;
+    StringPart sp(path,string::npos,openData.off);
+    return openData.fs->unlink(sp);
+}
+
+int FilesystemManager::renameHelper(string& oldPath, string& newPath)
+{
+    //Do everything while keeping the mutex locked to prevent someone to
+    //concurrently mount a filesystem on the directory we're renaming
+    Lock<FastMutex> l(mutex);
+    ResolvedPath oldOpenData=resolvePath(oldPath,true);
+    if(oldOpenData.result<0) return oldOpenData.result;
+    ResolvedPath newOpenData=resolvePath(newPath,true);
+    if(newOpenData.result<0) return newOpenData.result;
+    
+    if(oldOpenData.fs!=newOpenData.fs) return -EXDEV; //Can't rename across fs
+    
+    //After resolvePath() so path is in canonical form and symlinks are followed
+    if(filesystems.find(StringPart(oldPath))!=filesystems.end()) return -EBUSY;
+    if(filesystems.find(StringPart(newPath))!=filesystems.end()) return -EBUSY;
+    
+    StringPart oldSp(oldPath,string::npos,oldOpenData.off);
+    StringPart newSp(newPath,string::npos,newOpenData.off);
+    
+    //Can't rename a directory into a subdirectory of itself
+    if(newSp.startsWith(oldSp)) return -EINVAL;
+    return oldOpenData.fs->rename(oldSp,newSp);
+}
+
 short int FilesystemManager::getFilesystemId()
 {
     return atomicAddExchange(&devCount,1);
diff --git a/miosix/filesystem/file_access.h b/miosix/filesystem/file_access.h
index ebaa23d7..ef99d8d7 100644
--- a/miosix/filesystem/file_access.h
+++ b/miosix/filesystem/file_access.h
@@ -232,6 +232,29 @@ public:
      */
     int chdir(const char *name);
     
+    /**
+     * Create a directory
+     * \param name directory to create
+     * \param mode directory permissions
+     * \return 0 on success, or a negative number on failure
+     */
+    int mkdir(const char *name, int mode);
+    
+    /**
+     * Remove a file or directory
+     * \param name file or directory to remove
+     * \return 0 on success, or a negative number on failure
+     */
+    int unlink(const char *name);
+    
+    /**
+     * Rename a file or directory
+     * \param oldName old file name
+     * \param newName new file name
+     * \return 0 on success, or a negative number on failure
+     */
+    int rename(const char *oldName, const char *newName);
+    
     /**
      * Retrieves an entry in the file descriptor table
      * \param fd file descriptor, index into the table
@@ -330,6 +353,25 @@ public:
      */
     ResolvedPath resolvePath(std::string& path, bool followLastSymlink=true);
     
+    /**
+     * \internal
+     * Helper function to unlink a file or directory. Only meant to be used by
+     * FileDescriptorTable::unlink()
+     * \param path path of file or directory to unlink
+     * \return 0 on success, or a neagtive number on failure
+     */
+    int unlinkHelper(std::string& path);
+    
+    /**
+     * \internal
+     * Helper function to unlink a file or directory. Only meant to be used by
+     * FileDescriptorTable::unlink()
+     * \param oldPath path of file or directory to unlink
+     * \param newPath path of file or directory to unlink
+     * \return 0 on success, or a neagtive number on failure
+     */
+    int renameHelper(std::string& oldPath, std::string& newPath);
+    
     /**
      * \internal
      * Called by FileDescriptorTable's constructor. Never call this function
diff --git a/miosix/filesystem/mountpointfs/mountpointfs.cpp b/miosix/filesystem/mountpointfs/mountpointfs.cpp
index 759ed71f..f2042ea0 100644
--- a/miosix/filesystem/mountpointfs/mountpointfs.cpp
+++ b/miosix/filesystem/mountpointfs/mountpointfs.cpp
@@ -161,6 +161,26 @@ int MountpointFs::lstat(StringPart& name, struct stat *pstat)
     return 0;
 }
 
+int MountpointFs::unlink(StringPart& name)
+{
+    Lock<FastMutex> l(mutex);
+    if(dirs.erase(name)==1) return 0;
+    return -ENOENT;
+}
+
+int MountpointFs::rename(StringPart& oldName, StringPart& newName)
+{
+    Lock<FastMutex> l(mutex);
+    map<StringPart,int>::iterator it=dirs.find(oldName);
+    if(it==dirs.end()) return -ENOENT;
+    for(unsigned int i=0;i<newName.length();i++)
+        if(newName[i]=='/')
+            return -EACCES; //MountpointFs does not support subdirectories
+    dirs[newName]=it->second;
+    dirs.erase(it);
+    return 0;
+}
+
 int MountpointFs::mkdir(StringPart& name, int mode)
 {
     for(unsigned int i=0;i<name.length();i++)
diff --git a/miosix/filesystem/mountpointfs/mountpointfs.h b/miosix/filesystem/mountpointfs/mountpointfs.h
index fdd8709e..9acbe6be 100644
--- a/miosix/filesystem/mountpointfs/mountpointfs.h
+++ b/miosix/filesystem/mountpointfs/mountpointfs.h
@@ -66,6 +66,21 @@ public:
      * \return 0 on success, or a negative number on failure
      */
     virtual int lstat(StringPart& name, struct stat *pstat);
+    
+    /**
+     * Remove a file or directory
+     * \param name path name of file or directory to remove
+     * \return 0 on success, or a negative number on failure
+     */
+    virtual int unlink(StringPart& name);
+    
+    /**
+     * Rename a file or directory
+     * \param oldName old file name
+     * \param newName new file name
+     * \return 0 on success, or a negative number on failure
+     */
+    virtual int rename(StringPart& oldName, StringPart& newName);
          
     /**
      * Create a directory
diff --git a/miosix/kernel/unistd.cpp b/miosix/kernel/unistd.cpp
deleted file mode 100644
index 8829aa7b..00000000
--- a/miosix/kernel/unistd.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2010 by Terraneo Federico                               *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   As a special exception, if other files instantiate templates or use   *
- *   macros or inline functions from this file, or you compile this file   *
- *   and link it with other works to produce a work based on this file,    *
- *   this file does not by itself cause the resulting work to be covered   *
- *   by the GNU General Public License. However the source code for this   *
- *   file must still be made available in accordance with the GNU General  *
- *   Public License. This exception does not invalidate any other reasons  *
- *   why a work based on this file might be covered by the GNU General     *
- *   Public License.                                                       *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
- ***************************************************************************/
-
-/*
- * unistd.cpp Part of the Miosix Embedded OS. Provides a preliminary
- * implementation of some of the functions in <unistd.h>
- */
-
-#include "miosix.h"
-#include <unistd.h>
-
-using namespace miosix;
-
-//These functions needs to be callable from C
-extern "C" {
-
-/**
- * Sleep at least the specified number of seconds.
- * Always return 0 (success)
- */
-unsigned int sleep(unsigned int __seconds)
-{
-    Thread::sleep(__seconds*1000);
-    return 0;
-}
-
-/**
- * Sleep at least the specified number of microseconds.
- * Always return 0 (success)
- */
-int usleep(useconds_t __useconds)
-{
-    if(__useconds>=1000) Thread::sleep(__useconds / 1000);
-    delayUs(__useconds % 1000);
-    return 0;
-}
-
-
-}// extern C
diff --git a/miosix/stdlib_integration/libc_integration.cpp b/miosix/stdlib_integration/libc_integration.cpp
index f95254e1..63831e0e 100644
--- a/miosix/stdlib_integration/libc_integration.cpp
+++ b/miosix/stdlib_integration/libc_integration.cpp
@@ -45,6 +45,7 @@
 //// kernel interface
 #include "kernel/kernel.h"
 #include "interfaces/bsp.h"
+#include "interfaces/delays.h"
 #include "board_settings.h"
 
 using namespace std;
@@ -577,8 +578,23 @@ int fcntl(int fd, int cmd, ...)
 int _mkdir_r(struct _reent *ptr, const char *path, int mode)
 {
     #ifdef WITH_FILESYSTEM
-    //FIXME: implement this //return miosix::Filesystem::instance().mkdir(path,mode);
+
+    #ifndef __NO_EXCEPTIONS
+    try {
+    #endif //__NO_EXCEPTIONS
+        int result=miosix::getFileDescriptorTable().mkdir(path,mode);
+        if(result>=0) return result;
+        ptr->_errno=-result;
+        return -1;
+    #ifndef __NO_EXCEPTIONS
+    } catch(exception& e) {
+        ptr->_errno=ENOMEM;
+        return -1;
+    }
+    #endif //__NO_EXCEPTIONS
+    
     #else //WITH_FILESYSTEM
+    ptr->_errno=ENOENT;
     return -1;
     #endif //WITH_FILESYSTEM
 }
@@ -590,11 +606,11 @@ int mkdir(const char *path, mode_t mode)
 
 /**
  * \internal
- * _link_r
- * FIXME: implement me
+ * _link_r: create hardlinks
  */
 int _link_r(struct _reent *ptr, const char *f_old, const char *f_new)
 {
+    ptr->_errno=ENOENT; //Unimplemented at the moment
     return -1;
 }
 
@@ -610,8 +626,23 @@ int link(const char *f_old, const char *f_new)
 int _unlink_r(struct _reent *ptr, const char *file)
 {
     #ifdef WITH_FILESYSTEM
-    //FIXME: implement this //return miosix::Filesystem::instance().unlink(file);
+
+    #ifndef __NO_EXCEPTIONS
+    try {
+    #endif //__NO_EXCEPTIONS
+        int result=miosix::getFileDescriptorTable().unlink(file);
+        if(result>=0) return result;
+        ptr->_errno=-result;
+        return -1;
+    #ifndef __NO_EXCEPTIONS
+    } catch(exception& e) {
+        ptr->_errno=ENOMEM;
+        return -1;
+    }
+    #endif //__NO_EXCEPTIONS
+    
     #else //WITH_FILESYSTEM
+    ptr->_errno=ENOENT;
     return -1;
     #endif //WITH_FILESYSTEM
 }
@@ -623,12 +654,30 @@ int unlink(const char *file)
 
 /**
  * \internal
- * _rename_r
- * FIXME: implement me
+ * _rename_r, rename a file or directory
  */
 int _rename_r(struct _reent *ptr, const char *f_old, const char *f_new)
 {
+    #ifdef WITH_FILESYSTEM
+
+    #ifndef __NO_EXCEPTIONS
+    try {
+    #endif //__NO_EXCEPTIONS
+        int result=miosix::getFileDescriptorTable().rename(f_old,f_new);
+        if(result>=0) return result;
+        ptr->_errno=-result;
+        return -1;
+    #ifndef __NO_EXCEPTIONS
+    } catch(exception& e) {
+        ptr->_errno=ENOMEM;
+        return -1;
+    }
+    #endif //__NO_EXCEPTIONS
+    
+    #else //WITH_FILESYSTEM
+    ptr->_errno=ENOENT;
     return -1;
+    #endif //WITH_FILESYSTEM
 }
 
 int rename(const char *f_old, const char *f_new)
@@ -695,7 +744,7 @@ clock_t times(struct tms *tim)
 
 /**
  * \internal
- * _gettimeofday_r, FIXME: implement me
+ * _gettimeofday_r, unimplemented
  */
 int _gettimeofday_r(struct _reent *ptr, struct timeval *tv, void *tz)
 {
@@ -709,11 +758,16 @@ int gettimeofday(struct timeval *tv, void *tz)
 
 /**
  * \internal
- * nanosleep, FIXME: implement me
+ * nanosleep, high resolution sleep
  */
 int nanosleep(const struct timespec *req, struct timespec *rem)
 {
-    return -1;
+    if(req->tv_sec) miosix::Thread::sleep(req->tv_sec*1000);
+    unsigned int microseconds=req->tv_nsec/1000; //No sub-microsecond support yet
+    if(microseconds>=1000) miosix::Thread::sleep(microseconds/1000);
+    microseconds %= 1000;
+    if(microseconds) miosix::delayUs(microseconds);
+    return 0;
 }
 
 
diff --git a/miosix_np_2/nbproject/configurations.xml b/miosix_np_2/nbproject/configurations.xml
index fbe87c79..3e35bf86 100644
--- a/miosix_np_2/nbproject/configurations.xml
+++ b/miosix_np_2/nbproject/configurations.xml
@@ -380,7 +380,6 @@
           <in>stage_2_boot.h</in>
           <in>sync.cpp</in>
           <in>sync.h</in>
-          <in>unistd.cpp</in>
         </df>
         <df name="stdlib_integration">
           <in>libc_integration.cpp</in>
@@ -1493,8 +1492,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -2610,8 +2607,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -3729,8 +3724,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -4848,8 +4841,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -5967,8 +5958,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -7086,8 +7075,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -8205,8 +8192,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -9322,8 +9307,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -10439,8 +10422,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -11556,8 +11537,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -12673,8 +12652,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -13790,8 +13767,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
@@ -14907,8 +14882,6 @@
       </item>
       <item path="../miosix/kernel/sync.h" ex="false" tool="3" flavor2="0">
       </item>
-      <item path="../miosix/kernel/unistd.cpp" ex="false" tool="1" flavor2="0">
-      </item>
       <item path="../miosix/miosix.h" ex="false" tool="3" flavor2="0">
       </item>
       <item path="../miosix/stdlib_integration/libc_integration.cpp"
diff --git a/miosix_np_2/nbproject/private/configurations.xml b/miosix_np_2/nbproject/private/configurations.xml
index 76d068c7..78e00392 100644
--- a/miosix_np_2/nbproject/private/configurations.xml
+++ b/miosix_np_2/nbproject/private/configurations.xml
@@ -384,7 +384,6 @@
           <in>stage_2_boot.h</in>
           <in>sync.cpp</in>
           <in>sync.h</in>
-          <in>unistd.cpp</in>
         </df>
         <df name="stdlib_integration">
           <in>libc_integration.cpp</in>
-- 
GitLab