From b6c30ddcdf921bb1c94633caf64eb993d82003eb Mon Sep 17 00:00:00 2001
From: Terraneo Federico <fede.tft@hotmail.it>
Date: Sun, 7 Jul 2013 15:35:45 +0200
Subject: [PATCH] Continuing filesystem work

---
 main.cpp                          |  6 ++++++
 miosix/filesystem/devfs/devfs.cpp | 34 +++++++++++++++++++++++--------
 miosix/filesystem/devfs/devfs.h   | 34 ++++++++++++++++++++++++++++++-
 miosix/filesystem/file.h          | 15 +++++++++++++-
 miosix/filesystem/file_access.cpp | 15 ++++++++++++++
 miosix/filesystem/file_access.h   | 34 ++++++++++++++++++++++++++-----
 6 files changed, 123 insertions(+), 15 deletions(-)

diff --git a/main.cpp b/main.cpp
index 8764b9fa..c72a394f 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,6 +1,7 @@
 
 #include <cstdio>
 #include "miosix.h"
+#include "filesystem/devfs/devfs.h"
 
 using namespace std;
 using namespace miosix;
@@ -8,4 +9,9 @@ using namespace miosix;
 int main()
 {
     //iprintf("Hello world, write your application here\n");
+    DevFs *dfs=new DevFs;
+    FilesystemManager& fsm=FilesystemManager::instance();
+    fsm.kmount("/dev",dfs);
+    FileDescriptorTable fdt;
+    
 }
diff --git a/miosix/filesystem/devfs/devfs.cpp b/miosix/filesystem/devfs/devfs.cpp
index 7a5fc8b8..0170eae0 100644
--- a/miosix/filesystem/devfs/devfs.cpp
+++ b/miosix/filesystem/devfs/devfs.cpp
@@ -35,22 +35,40 @@ namespace miosix {
 // class DevFs
 //
 
-int DevFs::open(intrusive_ref_ptr<FileBase>& file, std::string name, int flags,
+DevFs::DevFs()
+{
+    files["null"]=intrusive_ref_ptr<FileBase>(new NullFile(this));
+    files["zero"]=intrusive_ref_ptr<FileBase>(new ZeroFile(this));
+}
+
+int DevFs::open(intrusive_ref_ptr<FileBase>& file, StringPart& name, int flags,
         int mode)
 {
-    
+    return -1; //FIXME
+}
+
+int DevFs::lstat(StringPart& name, struct stat *pstat)
+{
+    return -1; //FIXME
 }
 
-/**
- * \return true if all files belonging to this filesystem are closed 
- */
+int DevFs::readlink(StringPart& name, std::string& target)
+{
+    return -1; //FIXME
+}
+
+bool DevFs::supportsSymlinks() const { return false; }
+
 bool DevFs::areAllFilesClosed()
 {
+    //Lock the mutex just in case we'll want to support dynamically removing
+    //device files at runtime
+    Lock<Mutex> l(mutex);
     //Can't use openFileCount in devFS, as one instance of each file is stored
     //in the map. Rather, check the reference count value. No need to use
-    //atomic ops to make a copy of the file before calling use_count() as
-    //the existence of at least one reference in the map guarantees the file
-    //won't be deleted
+    //atomic ops to make a copy of the file before calling use_count() as the
+    //existence of at least one reference in the map guarantees the file won't
+    //be deleted.
     map<string,intrusive_ref_ptr<FileBase> >::iterator it;
     for(it=files.begin();it!=files.end();++it)
         if(it->second.use_count()>1) return false;
diff --git a/miosix/filesystem/devfs/devfs.h b/miosix/filesystem/devfs/devfs.h
index d7f9181f..50d7b58f 100644
--- a/miosix/filesystem/devfs/devfs.h
+++ b/miosix/filesystem/devfs/devfs.h
@@ -38,6 +38,11 @@ namespace miosix {
 class DevFs : public FilesystemBase
 {
 public:
+    /**
+     * Constructor
+     */
+    DevFs();
+    
     /**
      * Open a file
      * \param file the file object will be stored here, if the call succeeds
@@ -45,11 +50,38 @@ public:
      * filesystem
      * \param flags file flags (open for reading, writing, ...)
      * \param mode file permissions
+     * \return 0 on success, or a negative number on failure
      */
-    virtual int open(intrusive_ref_ptr<FileBase>& file, std::string name,
+    virtual int open(intrusive_ref_ptr<FileBase>& file, StringPart& name,
             int flags, int mode);
     
+        /**
+     * Obtain information on a file, identified by a path name. Does not follow
+     * symlinks
+     * \param name path name, relative to the local filesystem
+     * \param pstat file information is stored here
+     * \return 0 on success, or a negative number on failure
+     */
+    virtual int lstat(StringPart& name, struct stat *pstat);
+    
+    /**
+     * Follows a symbolic link
+     * \param path path identifying a symlink, relative to the local filesystem
+     * \param target the link target is returned here if the call succeeds.
+     * Note that the returned path is not relative to this filesystem, and can
+     * be either relative or absolute.
+     * \return 0 on success, a negative number on failure
+     */
+    virtual int readlink(StringPart& name, std::string& target);
+    
+    /**
+     * \return true if the filesystem supports symbolic links.
+     * In this case, the filesystem should override readlink
+     */
+    virtual bool supportsSymlinks() const;
+    
     /**
+     * \internal
      * \return true if all files belonging to this filesystem are closed 
      */
     virtual bool areAllFilesClosed();
diff --git a/miosix/filesystem/file.h b/miosix/filesystem/file.h
index 1a919cfe..94536720 100644
--- a/miosix/filesystem/file.h
+++ b/miosix/filesystem/file.h
@@ -48,7 +48,8 @@ class FileBase : public IntrusiveRefCounted
 {
 public:
     /**
-     * Construcotr
+     * Constructor
+     * \param parent the filesystem to which this file belongs
      */
     FileBase(FilesystemBase *parent) : parent(parent) {}
     
@@ -123,6 +124,12 @@ private:
 class NullFile : public FileBase
 {
 public:
+    /**
+     * Constructor
+     * \param parent the filesystem to which this file belongs
+     */
+    NullFile(FilesystemBase *parent) : FileBase(parent) {}
+    
     /**
      * Write data to the file, if the file supports writing.
      * \param data the data to write
@@ -178,6 +185,12 @@ public:
 class ZeroFile : public FileBase
 {
 public:
+    /**
+     * Constructor
+     * \param parent the filesystem to which this file belongs
+     */
+    ZeroFile(FilesystemBase *parent) : FileBase(parent) {}
+    
     /**
      * Write data to the file, if the file supports writing.
      * \param data the data to write
diff --git a/miosix/filesystem/file_access.cpp b/miosix/filesystem/file_access.cpp
index 6c4aca81..7b6820b7 100644
--- a/miosix/filesystem/file_access.cpp
+++ b/miosix/filesystem/file_access.cpp
@@ -88,11 +88,18 @@ FilesystemBase::~FilesystemBase() {}
 // class FileDescriptorTable
 //
 
+FileDescriptorTable::FileDescriptorTable() : mutex(Mutex::RECURSIVE), cwd("/")
+{
+    FilesystemManager::instance().addFileDescriptorTable(this);
+}
+
 FileDescriptorTable::FileDescriptorTable(const FileDescriptorTable& rhs)
+    : mutex(Mutex::RECURSIVE), cwd(rhs.cwd)
 {
     //No need to lock the mutex since we are in a constructor and there can't
     //be pointers to this in other threads yet
     for(int i=0;i<MAX_OPEN_FILES;i++) this->files[i]=atomic_load(&rhs.files[i]);
+    FilesystemManager::instance().addFileDescriptorTable(this);
 }
 
 FileDescriptorTable& FileDescriptorTable::operator=(
@@ -174,6 +181,14 @@ int FileDescriptorTable::statImpl(const char* name, struct stat* pstat, bool f)
     return openData.fs->lstat(sp,pstat);
 }
 
+FileDescriptorTable::~FileDescriptorTable()
+{
+    FilesystemManager::instance().removeFileDescriptorTable(this);
+    //There's no need to lock the mutex and explicitly close files eventually
+    //left open, because if there are other threads accessing this while we are
+    //being deleted we have bigger problems anyway
+}
+
 string FileDescriptorTable::absolutePath(const char* path)
 {
     int len=strlen(path);
diff --git a/miosix/filesystem/file_access.h b/miosix/filesystem/file_access.h
index bf46adb9..c3b51a97 100644
--- a/miosix/filesystem/file_access.h
+++ b/miosix/filesystem/file_access.h
@@ -138,7 +138,7 @@ public:
     /**
      * Constructor
      */
-    FileDescriptorTable() : mutex(Mutex::RECURSIVE), cwd("/") {}
+    FileDescriptorTable();
     
     /**
      * Copy constructor
@@ -292,9 +292,10 @@ public:
         return atomic_load(files+fd);
     }
     
-    //Using default destructor as there's no need to lock the mutex while
-    //closing files eventually left open, because if there are other threads
-    //accessing this while we are being deleted we have bigger problems anyway
+    /**
+     * Destructor
+     */
+    ~FileDescriptorTable();
     
 private:
     /**
@@ -498,7 +499,8 @@ public:
      * and board support packages. It is the only mount operation that can
      * mount the root filesystem.
      * \param path path where to mount the filesystem
-     * \param fs filesystem to mount
+     * \param fs filesystem to mount. Ownership of the pointer is transferred
+     * to the FilesystemManager class
      * \return 0 on success, a negative number on failure
      */
     int kmount(const char *path, FilesystemBase *fs);
@@ -528,6 +530,28 @@ public:
      */
     ResolvedPath resolvePath(std::string& path, bool followLastSymlink=true);
     
+    /**
+     * \internal
+     * Called by FileDescriptorTable's constructor. Never call this function
+     * from user code.
+     */
+    void addFileDescriptorTable(FileDescriptorTable *fdt)
+    {
+        Lock<Mutex> l(mutex);
+        fileTables.push_back(fdt);
+    }
+    
+    /**
+     * \internal
+     * Called by FileDescriptorTable's constructor. Never call this function
+     * from user code.
+     */
+    void removeFileDescriptorTable(FileDescriptorTable *fdt)
+    {
+        Lock<Mutex> l(mutex);
+        fileTables.remove(fdt);
+    }
+    
 private:
     /**
      * Constructor, private as it is a singleton
-- 
GitLab