diff --git a/main.cpp b/main.cpp index 4d281ba..8764b9f 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,6 @@ #include #include "miosix.h" -#include "filesystem/devfs/devfs.h" using namespace std; using namespace miosix; @@ -9,9 +8,4 @@ using namespace miosix; int main() { //iprintf("Hello world, write your application here\n"); - intrusive_ref_ptr dfs(new DevFs); - FilesystemManager& fsm=FilesystemManager::instance(); - fsm.kmount("/dev",dfs); - FileDescriptorTable fdt; - } diff --git a/miosix/Makefile b/miosix/Makefile index 53dd39d..8f570f1 100644 --- a/miosix/Makefile +++ b/miosix/Makefile @@ -23,6 +23,7 @@ kernel/scheduler/edf/edf_scheduler.cpp \ filesystem/filesystem.cpp \ filesystem/file_access.cpp \ filesystem/file.cpp \ +filesystem/mountpointfs/mountpointfs.cpp \ filesystem/devfs/devfs.cpp \ filesystem/fat32/ff.c \ filesystem/fat32/diskio.cpp \ diff --git a/miosix/_doc/textdoc/Changelog.txt b/miosix/_doc/textdoc/Changelog.txt index 2e6eecb..cdb8f94 100644 --- a/miosix/_doc/textdoc/Changelog.txt +++ b/miosix/_doc/textdoc/Changelog.txt @@ -1,5 +1,27 @@ Changelog for Miosix np embedded OS +- File abstraction layer now handles stdin/stdout/stderr and passes the + testsuite, still does not handle fat32 and echo on console is not working. +- File abstraction layer: added MountpointFs as the default root filesystem + to allow mounting other filesystems. +- Added operator[] to StringPart. +- File abstraction layer: added pure virtual mkdir() to FilesystemBase. +- Renamed DIR struct in FatFs code into _DIR_ to avoid conflicts with + struct DIR in dirent.h +- File abstraction layer: added ConsoleDevice class to store the default + console device passed by the board support package. +- File abstraction layer: added ConsoleAdapter class to map the old + Console class into the new file abstraction. Will be removed when all + bsp will upgrade to the new model. +- File abstraction layer: correctly handling the one FiledescriptorTable + model when WITH_PROCESSES is undefined (processes branch not merged yet). +- File abstraction layer: now FileDescriptorTable's constructor opens + /dev/console as file descriptors 0, 1 and 2 (stdin, stdout and stderr). +- Now all non reentrant syscalls use CReentrancyAccessor::getReent() to set + the errno variable of the thread they're called in. +- Added option in libc_integration to route the filesystem-related syscalls + to the old one filesystem model, or the new file abstraction layer allowing + multiple mountpoint model. The new model will gradually replace the old one. - Added -DCOMPILING_MIOSIX to CFLAGS and CXXFLAGS, to allow the introduction of private headers. - getMaxHeap() in libc_integration.h is now in the miosix namespace diff --git a/miosix/config/miosix_settings.h b/miosix/config/miosix_settings.h index 5ddfa17..9bea405 100644 --- a/miosix/config/miosix_settings.h +++ b/miosix/config/miosix_settings.h @@ -80,6 +80,7 @@ namespace miosix { #define SYNC_AFTER_WRITE /// Maximum number of open files. Trying to open more will fail. +/// Cannot be lower than 3, as the first three are stdin, stdout, stderr const unsigned char MAX_OPEN_FILES=8; // diff --git a/miosix/filesystem/devfs/devfs.cpp b/miosix/filesystem/devfs/devfs.cpp index bf634d6..a347877 100644 --- a/miosix/filesystem/devfs/devfs.cpp +++ b/miosix/filesystem/devfs/devfs.cpp @@ -37,8 +37,16 @@ namespace miosix { DevFs::DevFs() { - files[StringPart("null")]=intrusive_ref_ptr(new NullFile); - files[StringPart("zero")]=intrusive_ref_ptr(new ZeroFile); + string null="/null"; + string zero="/zero"; + string console="/console"; + + files[StringPart(null)]=intrusive_ref_ptr(new NullFile); + files[StringPart(zero)]=intrusive_ref_ptr(new ZeroFile); + + intrusive_ref_ptr consoleDev=ConsoleDevice::instance().get(); + if(consoleDev) files[StringPart(console)]=consoleDev; + else files[StringPart(console)]=files[StringPart(null)]; } int DevFs::open(intrusive_ref_ptr& file, StringPart& name, int flags, @@ -61,6 +69,11 @@ int DevFs::lstat(StringPart& name, struct stat *pstat) return 0; } +int DevFs::mkdir(StringPart& name, int mode) +{ + return -EACCES; // No directories support in DevFs yet +} + bool DevFs::areAllFilesClosed() { Lock l(mutex); diff --git a/miosix/filesystem/devfs/devfs.h b/miosix/filesystem/devfs/devfs.h index bc5a225..cc0258a 100644 --- a/miosix/filesystem/devfs/devfs.h +++ b/miosix/filesystem/devfs/devfs.h @@ -29,7 +29,6 @@ #define DEVFS_H #include -#include #include "filesystem/file.h" #include "filesystem/file_access.h" @@ -80,7 +79,7 @@ class DevFs : public FilesystemBase virtual int open(intrusive_ref_ptr& 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 @@ -88,6 +87,14 @@ class DevFs : public FilesystemBase * \return 0 on success, or a negative number on failure */ virtual int lstat(StringPart& name, struct stat *pstat); + + /** + * Create a directory + * \param name directory name + * \param mode directory permissions + * \return 0 on success, or a negative number on failure + */ + virtual int mkdir(StringPart& name, int mode); /** * \internal diff --git a/miosix/filesystem/fat32/ff.c b/miosix/filesystem/fat32/ff.c index 9a3a2ce..c305765 100644 --- a/miosix/filesystem/fat32/ff.c +++ b/miosix/filesystem/fat32/ff.c @@ -354,7 +354,7 @@ DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */ static BOOL next_dir_entry ( /* TRUE: successful, FALSE: could not move next */ - DIR *dj /* Pointer to directory object */ + _DIR_ *dj /* Pointer to directory object */ ) { DWORD clust; @@ -498,7 +498,7 @@ char make_dirfile ( /* 1: error - detected an invalid format, '\0'or'/': next c static FRESULT trace_path ( /* FR_OK(0): successful, !=0: error code */ - DIR *dj, /* Pointer to directory object to return last directory */ + _DIR_ *dj, /* Pointer to directory object to return last directory */ char *fn, /* Pointer to last segment name to return {file(8),ext(3),attr(1)} */ const char *path, /* Full-path string to trace a file or directory */ BYTE **dir /* Pointer to pointer to found entry to retutn */ @@ -558,7 +558,7 @@ FRESULT trace_path ( /* FR_OK(0): successful, !=0: error code */ #if !_FS_READONLY static FRESULT reserve_direntry ( /* FR_OK: successful, FR_DENIED: no free entry, FR_RW_ERROR: a disk error occured */ - DIR *dj, /* Target directory to create new entry */ + _DIR_ *dj, /* Target directory to create new entry */ BYTE **dir /* Pointer to pointer to created entry to retutn */ ) { @@ -820,7 +820,7 @@ FRESULT f_open ( ) { FRESULT res; - DIR dj; + _DIR_ dj; BYTE *dir; char fn[8+3+1]; @@ -1230,7 +1230,7 @@ FRESULT f_lseek ( /*-----------------------------------------------------------------------*/ FRESULT f_opendir ( - DIR *dj, /* Pointer to directory object to create */ + _DIR_ *dj, /* Pointer to directory object to create */ const char *path /* Pointer to the directory path */ ) { @@ -1267,7 +1267,7 @@ FRESULT f_opendir ( /*-----------------------------------------------------------------------*/ FRESULT f_readdir ( - DIR *dj, /* Pointer to the directory object */ + _DIR_ *dj, /* Pointer to the directory object */ FILINFO *finfo /* Pointer to file information to return */ ) { @@ -1307,7 +1307,7 @@ FRESULT f_stat ( ) { FRESULT res; - DIR dj; + _DIR_ dj; BYTE *dir; char fn[8+3+1]; @@ -1444,7 +1444,7 @@ FRESULT f_unlink ( ) { FRESULT res; - DIR dj; + _DIR_ dj; BYTE *dir, *sdir; DWORD dclust, dsect; char fn[8+3+1]; @@ -1492,7 +1492,7 @@ FRESULT f_mkdir ( ) { FRESULT res; - DIR dj; + _DIR_ dj; BYTE *dir, *fw, n; char fn[8+3+1]; DWORD sect, dsect, dclust, pclust, tim; @@ -1559,7 +1559,7 @@ FRESULT f_chmod ( ) { FRESULT res; - DIR dj; + _DIR_ dj; BYTE *dir; char fn[8+3+1]; @@ -1593,7 +1593,7 @@ FRESULT f_utime ( ) { FRESULT res; - DIR dj; + _DIR_ dj; BYTE *dir; char fn[8+3+1]; @@ -1627,7 +1627,7 @@ FRESULT f_rename ( ) { FRESULT res; - DIR dj; + _DIR_ dj; DWORD sect_old; BYTE *dir_old, *dir_new, direntry[32-11]; char fn[8+3+1]; diff --git a/miosix/filesystem/fat32/ff.h b/miosix/filesystem/fat32/ff.h index c44ccfc..4fb7d3b 100644 --- a/miosix/filesystem/fat32/ff.h +++ b/miosix/filesystem/fat32/ff.h @@ -121,7 +121,7 @@ typedef struct _DIR { DWORD sclust; /* Start cluster */ DWORD clust; /* Current cluster */ DWORD sect; /* Current sector */ -} DIR; +} _DIR_; /* File object structure */ @@ -205,8 +205,8 @@ FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */ FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */ FRESULT f_close (FIL*); /* Close an open file object */ -FRESULT f_opendir (DIR*, const char*); /* Open an existing directory */ -FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ +FRESULT f_opendir (_DIR_*, const char*); /* Open an existing directory */ +FRESULT f_readdir (_DIR_*, FILINFO*); /* Read a directory item */ FRESULT f_stat (const char*, FILINFO*); /* Get file status */ FRESULT f_getfree (const char*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ FRESULT f_truncate (FIL*); /* Truncate file */ diff --git a/miosix/filesystem/file.cpp b/miosix/filesystem/file.cpp index 67473a2..5775676 100644 --- a/miosix/filesystem/file.cpp +++ b/miosix/filesystem/file.cpp @@ -27,6 +27,7 @@ #include "file.h" #include +#include //FIXME: remove #include "file_access.h" namespace miosix { @@ -222,4 +223,28 @@ int TerminalDevice::isatty() const { return device->isatty(); } int TerminalDevice::sync() { return device->sync(); } +// FIXME temporary -- begin +ssize_t ConsoleAdapter::write(const void *data, size_t len) +{ + Console::write(reinterpret_cast(data),len); + return len; +} +ssize_t ConsoleAdapter::read(void *data, size_t len) +{ + char *d=reinterpret_cast(data); + for(size_t i=0;ist_mode=S_IFCHR;//Character device + pstat->st_blksize=0; //Defualt file buffer equals to BUFSIZ + return 0; +} +int ConsoleAdapter::isatty() const { return true; } +int ConsoleAdapter::sync() { return 0; } +// FIXME temporary -- end + } //namespace miosix diff --git a/miosix/filesystem/file.h b/miosix/filesystem/file.h index ec195c8..5bb3186 100644 --- a/miosix/filesystem/file.h +++ b/miosix/filesystem/file.h @@ -341,6 +341,21 @@ class TerminalDevice : public FileBase bool skipNewline; }; +/** + * FIXME remove this when removing Console interface! + */ +class ConsoleAdapter : public FileBase +{ +public: + ConsoleAdapter() : FileBase(intrusive_ref_ptr()) {} + virtual ssize_t write(const void *data, size_t len); + virtual ssize_t read(void *data, size_t len); + virtual off_t lseek(off_t pos, int whence); + virtual int fstat(struct stat *pstat) const; + virtual int isatty() const; + virtual int sync(); +}; + } //namespace miosix #endif //FILE_H diff --git a/miosix/filesystem/file_access.cpp b/miosix/filesystem/file_access.cpp index 79f9bca..cb81d6c 100644 --- a/miosix/filesystem/file_access.cpp +++ b/miosix/filesystem/file_access.cpp @@ -2,6 +2,8 @@ #include #include #include "file_access.h" +#include "devfs/devfs.h" +#include "mountpointfs/mountpointfs.h" using namespace std; @@ -93,6 +95,10 @@ FilesystemBase::~FilesystemBase() {} FileDescriptorTable::FileDescriptorTable() : mutex(Mutex::RECURSIVE), cwd("/") { FilesystemManager::instance().addFileDescriptorTable(this); + //We need to open stdin, stdout, stderr. + //We're relying on open to choose the lowest numbered files slot + open("/dev/console",0,0); //FIXME: flags is wrong + files[1]=files[2]=files[0]; } FileDescriptorTable::FileDescriptorTable(const FileDescriptorTable& rhs) @@ -626,6 +632,7 @@ int FilesystemManager::umount(const char* path, bool force) //descriptor table (4 bytes), and because umount happens infrequently. //Note that since we are locking the same mutex used by resolvePath(), //other threads can't open new files concurrently while we check + #ifdef WITH_PROCESSES list::iterator it3; for(it3=fileTables.begin();it3!=fileTables.end();++it3) { @@ -642,6 +649,20 @@ int FilesystemManager::umount(const char* path, bool force) } } } + #else //WITH_PROCESSES + for(int i=0;i file=getFileDescriptorTable().getFile(i); + if(!file) continue; + vector::iterator it4; + for(it4=fsToUmount.begin();it4!=fsToUmount.end();++it4) + { + if(file->getParent()!=(*it4)->second) continue; + if(force==false) return -EBUSY; + getFileDescriptorTable().close(i);//If forced umount, close the file + } + } + #endif //WITH_PROCESSES //Now there should be no more files belonging to the filesystems to umount, //but check if it is really so, as there is a possible race condition @@ -686,4 +707,36 @@ ResolvedPath FilesystemManager::resolvePath(string& path, bool followLastSymlink return pr.resolvePath(path,followLastSymlink); } +FilesystemManager::FilesystemManager() +{ + //TODO: move to BSPs + intrusive_ref_ptr rootFs(new MountpointFs); + string dev="/dev"; + StringPart sp(dev); + rootFs->mkdir(sp,0755); + kmount("/",rootFs); + kmount("/dev",intrusive_ref_ptr(new DevFs)); +} + +// +// class ConsoleDevice +// + +ConsoleDevice& ConsoleDevice::instance() +{ + static ConsoleDevice singleton; + return singleton; +} + +FileDescriptorTable& getFileDescriptorTable() +{ + #ifdef WITH_PROCESSES + //Something like + return Thread::getCurrentThread()->getProcess()->getFileTable(); + #else //WITH_PROCESSES + static FileDescriptorTable fileTable; ///< The only file table + return fileTable; + #endif //WITH_PROCESSES +} + } //namespace miosix diff --git a/miosix/filesystem/file_access.h b/miosix/filesystem/file_access.h index 2a4f787..53f798d 100644 --- a/miosix/filesystem/file_access.h +++ b/miosix/filesystem/file_access.h @@ -82,6 +82,14 @@ class FilesystemBase : public IntrusiveRefCounted */ virtual int lstat(StringPart& name, struct stat *pstat)=0; + /** + * Create a directory + * \param name directory name + * \param mode directory permissions + * \return 0 on success, or a negative number on failure + */ + virtual int mkdir(StringPart& name, int mode)=0; + /** * Follows a symbolic link * \param path path identifying a symlink, relative to the local filesystem @@ -451,6 +459,11 @@ class StringPart return type==CSTR ? cstr+offset : str->c_str()+offset; } + char operator[] (unsigned int index) const + { + return type==CSTR ? cstr[offset+index] : (*str)[offset+index]; + } + /** * \return true if the string is empty */ @@ -540,8 +553,10 @@ class FilesystemManager */ void addFileDescriptorTable(FileDescriptorTable *fdt) { + #ifdef WITH_PROCESSES Lock l(mutex); fileTables.push_back(fdt); + #endif //WITH_PROCESSES } /** @@ -551,15 +566,17 @@ class FilesystemManager */ void removeFileDescriptorTable(FileDescriptorTable *fdt) { + #ifdef WITH_PROCESSES Lock l(mutex); fileTables.remove(fdt); + #endif //WITH_PROCESSES } private: /** * Constructor, private as it is a singleton */ - FilesystemManager() {} + FilesystemManager(); FilesystemManager(const FilesystemManager&); FilesystemManager& operator=(const FilesystemManager&); @@ -569,13 +586,56 @@ class FilesystemManager /// Mounted filesystem std::map > filesystems; -// #ifdef WITH_PROCESSES + #ifdef WITH_PROCESSES std::list fileTables; ///< Process file tables -// #else //WITH_PROCESSES -// FileDescriptorTable fileTable; ///< The only file table -// #endif //WITH_PROCESSES + #endif //WITH_PROCESSES }; +/** + * This class holds the file object related to the console, that is set by + * the board support package, and used to populate /dev/console in DevFs + */ +class ConsoleDevice +{ +public: + /** + * \return an instance of this class (singleton) + */ + static ConsoleDevice& instance(); + + /** + * Called by the board support package, in particular IRQbspInit(), to pass + * to the kernel the console device. This device file is used as the default + * one for stdin/stdout/stderr. + * \param console device file handling console I/O. Can only be called with + * interrupts disabled. + */ + void IRQset(intrusive_ref_ptr console) { this->console=console; } + + /** + * \return the currently installed console device + */ + intrusive_ref_ptr get() const { return console; } + +private: + /** + * Constructor, private as it is a singleton + */ + ConsoleDevice() {} + + ConsoleDevice(const ConsoleDevice&); + ConsoleDevice& operator= (const ConsoleDevice&); + + intrusive_ref_ptr console; ///< The console device +}; + +/** + * \return a pointer to the file descriptor table associated with the + * current process. Note: make sure you don't call this function before + * IRQsetConsole(), otherwise stdin/stdout/stderr won't be set up properly + */ +FileDescriptorTable& getFileDescriptorTable(); + } //namespace miosix #endif //FILE_ACCESS_H diff --git a/miosix/filesystem/filesystem.cpp b/miosix/filesystem/filesystem.cpp index 9973376..d054ab8 100644 --- a/miosix/filesystem/filesystem.cpp +++ b/miosix/filesystem/filesystem.cpp @@ -68,7 +68,7 @@ char Filesystem::mount() if(f_mount(0,&filesystem)!=FR_OK) result=1; //Fatfs will delay actual filesystem mount until the first request is //made. So let's force it to mount the filesystem. - DIR d; + _DIR_ d; if(f_opendir(&d,"/")!=FR_OK) result=1; } if(result==0) mounted=true; diff --git a/miosix/filesystem/filesystem.h b/miosix/filesystem/filesystem.h index 229350a..a57a285 100644 --- a/miosix/filesystem/filesystem.h +++ b/miosix/filesystem/filesystem.h @@ -382,7 +382,7 @@ class Directory Directory(const Directory& d);///< No copy constructor Directory& operator= (const Directory& d);///< No operator = //Data - DIR d;///< FatFs directory variable + _DIR_ d;///< FatFs directory variable }; /** diff --git a/miosix/filesystem/mountpointfs/mountpointfs.cpp b/miosix/filesystem/mountpointfs/mountpointfs.cpp new file mode 100644 index 0000000..2fab5b0 --- /dev/null +++ b/miosix/filesystem/mountpointfs/mountpointfs.cpp @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2013 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 * + ***************************************************************************/ + +#include "mountpointfs.h" + +using namespace std; + +namespace miosix { + +// +// class DevFs +// + +int MountpointFs::open(intrusive_ref_ptr& file, StringPart& name, + int flags, int mode) +{ + return -EACCES; //MountpointFs does not support files, only directories +} + +int MountpointFs::lstat(StringPart& name, struct stat *pstat) +{ + Lock l(mutex); + map::iterator it=dirs.find(name); + if(it==dirs.end()) return -ENOENT; + memset(pstat,0,sizeof(struct stat)); + pstat->st_ino=it->second; + pstat->st_mode=S_IFDIR | 0755; //drwxr-xr-x + pstat->st_nlink=1; + pstat->st_blksize=512; + return 0; +} + +int MountpointFs::mkdir(StringPart& name, int mode) +{ + //TODO: start from 0 when name will not contain / + for(unsigned int i=1;i l(mutex); + if(dirs.insert(make_pair(name,inodeCount)).second==false) return -EEXIST; + inodeCount++; + return 0; +} + +} //namespace miosix diff --git a/miosix/filesystem/mountpointfs/mountpointfs.h b/miosix/filesystem/mountpointfs/mountpointfs.h new file mode 100644 index 0000000..67d2cbc --- /dev/null +++ b/miosix/filesystem/mountpointfs/mountpointfs.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (C) 2013 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 * + ***************************************************************************/ + +#ifndef MOUNTPOINTFS_H +#define MOUNTPOINTFS_H + +#include +#include "filesystem/file.h" +#include "filesystem/file_access.h" + +namespace miosix { + +/** + * MountpointFs is a special filesystem whose purpose is to create directories + * to be used as mountpoints for other filesystems. + */ +class MountpointFs : public FilesystemBase +{ +public: + /** + * Constructor + */ + MountpointFs() : inodeCount(1) {} + + /** + * Open a file + * \param file the file object will be stored here, if the call succeeds + * \param name the name of the file to open, relative to the local + * 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& 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); + + /** + * Create a directory + * \param name directory name + * \param mode directory permissions + * \return 0 on success, or a negative number on failure + */ + virtual int mkdir(StringPart& name, int mode); + +private: + Mutex mutex; + std::map dirs; + int inodeCount; +}; + +} //namespace miosix + +#endif //MOUNTPOINTFS_H diff --git a/miosix/kernel/interrupt_output_device.h b/miosix/kernel/interrupt_output_device.h index 91e7b58..9ed7ee2 100644 --- a/miosix/kernel/interrupt_output_device.h +++ b/miosix/kernel/interrupt_output_device.h @@ -102,7 +102,7 @@ class NullInterruptOutputDevice * an interrupt. * \param str the string to write. The string must be NUL terminated. */ - virtual void IRQwrite(const char *str)=0; + virtual void IRQwrite(const char *str); /** * Can ONLY be called when the kernel is not yet started, paused or within @@ -112,7 +112,7 @@ class NullInterruptOutputDevice * example to wait until all data has been sent before performing a reboot. * \return true if all write buffers are empty. */ - virtual bool IRQtxComplete()=0; + virtual bool IRQtxComplete(); }; } //namespace miosix diff --git a/miosix/kernel/stage_2_boot.cpp b/miosix/kernel/stage_2_boot.cpp index b238cec..211abce 100644 --- a/miosix/kernel/stage_2_boot.cpp +++ b/miosix/kernel/stage_2_boot.cpp @@ -38,6 +38,7 @@ start the kernel and filesystem. #include "interfaces/bsp.h" // Miosix kernel #include "kernel.h" +#include "filesystem/file_access.h" #include "filesystem/filesystem.h" #include "error.h" #include "logging.h" @@ -137,6 +138,7 @@ void *mainLoader(void *argv) //If main returns, shutdown shutdown(); + return 0; } /** @@ -148,6 +150,8 @@ void *mainLoader(void *argv) extern "C" void _init() { if(areInterruptsEnabled()) errorHandler(INTERRUPTS_ENABLED_AT_BOOT); + ConsoleDevice::instance().IRQset(intrusive_ref_ptr(new TerminalDevice( + intrusive_ref_ptr(new ConsoleAdapter)))); //FIXME: remove! IRQbspInit(); //After IRQbspInit() serial port is initialized, so we can use BOOTLOG IRQbootlog(getMiosixVersion()); diff --git a/miosix/stdlib_integration/libc_integration.cpp b/miosix/stdlib_integration/libc_integration.cpp index e0a4df2..33b54fb 100644 --- a/miosix/stdlib_integration/libc_integration.cpp +++ b/miosix/stdlib_integration/libc_integration.cpp @@ -28,15 +28,17 @@ #include "libc_integration.h" #include #include +#include +#include #include #include #include #include -#include //// Settings #include "config/miosix_settings.h" //// Filesystem #include "filesystem/filesystem.h" +#include "filesystem/file_access.h" //// Console #include "kernel/logging.h" #include "interfaces/console.h" @@ -138,6 +140,10 @@ void _exit(int n) for(;;) ; //Required to avoid a warning about noreturn functions } +/** + * \internal + * _sbrk_r, allocates memory dynamically + */ void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr) { //This is the absolute start of the heap @@ -176,7 +182,7 @@ void *_sbrk_r(struct _reent *ptr, ptrdiff_t incr) void *sbrk(ptrdiff_t incr) { - return _sbrk_r(_impure_ptr,incr); + return _sbrk_r(miosix::CReentrancyAccessor::getReent(),incr); } /** @@ -205,11 +211,21 @@ void __malloc_unlock() miosix::restartKernel(); } +/** + * \internal + * __getreent(), return the reentrancy structure of the current thread. + * Used by newlib to make the C standard library thread safe + */ struct _reent *__getreent() { return miosix::CReentrancyAccessor::getReent(); } + + + +#define TEST_NEW_FS +#ifndef TEST_NEW_FS /** * \internal * _open_r, open a file @@ -227,7 +243,8 @@ int _open_r(struct _reent *ptr, const char *name, int flags, int mode) int open(const char *name, int flags, ...) { - return _open_r(_impure_ptr,name,flags,0); //TODO: retrieve file mode + //TODO: retrieve file mode + return _open_r(miosix::CReentrancyAccessor::getReent(),name,flags,0); } /** @@ -247,7 +264,7 @@ int _close_r(struct _reent *ptr, int fd) int close(int fd) { - return _close_r(_impure_ptr,fd); + return _close_r(miosix::CReentrancyAccessor::getReent(),fd); } /** @@ -297,7 +314,7 @@ int _write_r(struct _reent *ptr, int fd, const void *buf, size_t cnt) int write(int fd, const void *buf, size_t cnt) { - return _write_r(_impure_ptr,fd,buf,cnt); + return _write_r(miosix::CReentrancyAccessor::getReent(),fd,buf,cnt); } /** @@ -366,7 +383,7 @@ int _read_r(struct _reent *ptr, int fd, void *buf, size_t cnt) int read(int fd, void *buf, size_t cnt) { - return _read_r(_impure_ptr,fd,buf,cnt); + return _read_r(miosix::CReentrancyAccessor::getReent(),fd,buf,cnt); } /** @@ -385,7 +402,7 @@ off_t _lseek_r(struct _reent *ptr, int fd, off_t pos, int whence) off_t lseek(int fd, off_t pos, int whence) { - return _lseek_r(_impure_ptr,fd,pos,whence); + return _lseek_r(miosix::CReentrancyAccessor::getReent(),fd,pos,whence); } /** @@ -412,7 +429,7 @@ int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat) int fstat(int fd, struct stat *pstat) { - return _fstat_r(_impure_ptr,fd,pstat); + return _fstat_r(miosix::CReentrancyAccessor::getReent(),fd,pstat); } /** @@ -430,7 +447,7 @@ int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat) int stat(const char *file, struct stat *pstat) { - return _stat_r(_impure_ptr,file,pstat); + return _stat_r(miosix::CReentrancyAccessor::getReent(),file,pstat); } /** @@ -452,14 +469,329 @@ int _isatty_r(struct _reent *ptr, int fd) int isatty(int fd) { - return _isatty_r(_impure_ptr,fd); + return _isatty_r(miosix::CReentrancyAccessor::getReent(),fd); +} + +/** + * \internal + * _fntl_r, TODO: implement it + */ +int _fcntl_r(struct _reent *, int fd, int cmd, int opt) +{ + return -1; +} + +int fcntl(int fd, int cmd, ...) +{ + return -1; } /** * \internal - * mkdir, create a directory + * _mkdir_r, create a directory */ +int _mkdir_r(struct _reent *ptr, const char *path, int mode) +{ + #ifdef WITH_FILESYSTEM + return miosix::Filesystem::instance().mkdir(path,mode); + #else //WITH_FILESYSTEM + return -1; + #endif //WITH_FILESYSTEM +} + int mkdir(const char *path, mode_t mode) +{ + return _mkdir_r(miosix::CReentrancyAccessor::getReent(),path,mode); +} + +/** + * \internal + * _link_r + * FIXME: implement me + */ +int _link_r(struct _reent *ptr, const char *f_old, const char *f_new) +{ + return -1; +} + +int link(const char *f_old, const char *f_new) +{ + return _link_r(miosix::CReentrancyAccessor::getReent(),f_old,f_new); +} + +/** + * \internal + * _unlink_r, remove a file + */ +int _unlink_r(struct _reent *ptr, const char *file) +{ + #ifdef WITH_FILESYSTEM + return miosix::Filesystem::instance().unlink(file); + #else //WITH_FILESYSTEM + return -1; + #endif //WITH_FILESYSTEM +} + +int unlink(const char *file) +{ + return _unlink_r(miosix::CReentrancyAccessor::getReent(),file); +} + +/** + * \internal + * _rename_r + * FIXME: implement me + */ +int _rename_r(struct _reent *ptr, const char *f_old, const char *f_new) +{ + return -1; +} + +int rename(const char *f_old, const char *f_new) +{ + return _rename_r(miosix::CReentrancyAccessor::getReent(),f_old,f_new); +} + +/** + * \internal + * getdents, FIXME: implement me + */ +int getdents(unsigned int fd, struct dirent *dirp, unsigned int count) +{ + return -1; +} + +#else //TEST_NEW_FS +/** + * \internal + * _open_r, open a file + */ +int _open_r(struct _reent *ptr, const char *name, int flags, int mode) +{ + #ifdef WITH_FILESYSTEM + int result=miosix::getFileDescriptorTable().open(name,flags,mode); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + #else //WITH_FILESYSTEM + ptr->_errno=ENFILE; + return -1; + #endif //WITH_FILESYSTEM +} + +int open(const char *name, int flags, ...) +{ + //TODO: retrieve file mode + return _open_r(miosix::CReentrancyAccessor::getReent(),name,flags,0); +} + +/** + * \internal + * _close_r, close a file + */ +int _close_r(struct _reent *ptr, int fd) +{ + #ifdef WITH_FILESYSTEM + int result=miosix::getFileDescriptorTable().close(fd); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + #else //WITH_FILESYSTEM + ptr->_errno=EBADF; + return -1; + #endif //WITH_FILESYSTEM +} + +int close(int fd) +{ + return _close_r(miosix::CReentrancyAccessor::getReent(),fd); +} + +/** + * \internal + * _write_r, write to a file + */ +int _write_r(struct _reent *ptr, int fd, const void *buf, size_t cnt) +{ + #ifdef WITH_FILESYSTEM + int result=miosix::getFileDescriptorTable().write(fd,buf,cnt); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + #else //WITH_FILESYSTEM + if(fd==STDOUT_FILENO || fd==STDERR_FILENO) + { + int result=miosix::ConsoleDevice::instance().get()->write(buf,cnt); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + } else { + ptr->_errno=EBADF; + return -1; + } + #endif //WITH_FILESYSTEM +} + +int write(int fd, const void *buf, size_t cnt) +{ + return _write_r(miosix::CReentrancyAccessor::getReent(),fd,buf,cnt); +} + +/** + * \internal + * _read_r, read from a file + */ +int _read_r(struct _reent *ptr, int fd, void *buf, size_t cnt) +{ + #ifdef WITH_FILESYSTEM + int result=miosix::getFileDescriptorTable().read(fd,buf,cnt); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + #else //WITH_FILESYSTEM + if(fd==STDIN_FILENO) + { + int result=miosix::ConsoleDevice::instance().get()->read(buf,cnt); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + } else { + ptr->_errno=EBADF; + return -1; + } + #endif //WITH_FILESYSTEM +} + +int read(int fd, void *buf, size_t cnt) +{ + return _read_r(miosix::CReentrancyAccessor::getReent(),fd,buf,cnt); +} + +/** + * \internal + * _lseek_r, move file pointer + */ +off_t _lseek_r(struct _reent *ptr, int fd, off_t pos, int whence) +{ + #ifdef WITH_FILESYSTEM + off_t result=miosix::getFileDescriptorTable().lseek(fd,pos,whence); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + #else //WITH_FILESYSTEM + ptr->_errno=EBADF; + return -1; + #endif //WITH_FILESYSTEM +} + +off_t lseek(int fd, off_t pos, int whence) +{ + return _lseek_r(miosix::CReentrancyAccessor::getReent(),fd,pos,whence); +} + +/** + * \internal + * _fstat_r, return file info + */ +int _fstat_r(struct _reent *ptr, int fd, struct stat *pstat) +{ + #ifdef WITH_FILESYSTEM + int result=miosix::getFileDescriptorTable().fstat(fd,pstat); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + #else //WITH_FILESYSTEM + switch(fd) + { + case STDIN_FILENO: + case STDOUT_FILENO: + case STDERR_FILENO: + memset(pstat,0,sizeof(struct stat)); + pstat->st_mode=S_IFCHR;//Character device + pstat->st_blksize=0; //Defualt file buffer equals to BUFSIZ + return 0; + default: + ptr->_errno=EBADF; + return -1; + } + #endif //WITH_FILESYSTEM +} + +int fstat(int fd, struct stat *pstat) +{ + return _fstat_r(miosix::CReentrancyAccessor::getReent(),fd,pstat); +} + +/** + * \internal + * _stat_r, collect data about a file + */ +int _stat_r(struct _reent *ptr, const char *file, struct stat *pstat) +{ + #ifdef WITH_FILESYSTEM + int result=miosix::getFileDescriptorTable().stat(file,pstat); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + #else //WITH_FILESYSTEM + ptr->_errno=ENOENT; + return -1; + #endif //WITH_FILESYSTEM +} + +int stat(const char *file, struct stat *pstat) +{ + return _stat_r(miosix::CReentrancyAccessor::getReent(),file,pstat); +} + +/** + * \internal + * isatty, returns 1 if fd is associated with a terminal + */ +int _isatty_r(struct _reent *ptr, int fd) +{ + #ifdef WITH_FILESYSTEM + int result=miosix::getFileDescriptorTable().isatty(fd); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + #else //WITH_FILESYSTEM + switch(fd) + { + case STDIN_FILENO: + case STDOUT_FILENO: + case STDERR_FILENO: + return 1; + default: + return 0; + } + #endif //WITH_FILESYSTEM +} + +int isatty(int fd) +{ + return _isatty_r(miosix::CReentrancyAccessor::getReent(),fd); +} + +/** + * \internal + * _fntl_r, TODO: implement it + */ +int _fcntl_r(struct _reent *, int fd, int cmd, int opt) +{ + return -1; +} + +int fcntl(int fd, int cmd, ...) +{ + return -1; +} + +/** + * \internal + * _mkdir_r, create a directory + */ +int _mkdir_r(struct _reent *ptr, const char *path, int mode) { #ifdef WITH_FILESYSTEM return miosix::Filesystem::instance().mkdir(path,mode); @@ -468,6 +800,26 @@ int mkdir(const char *path, mode_t mode) #endif //WITH_FILESYSTEM } +int mkdir(const char *path, mode_t mode) +{ + return _mkdir_r(miosix::CReentrancyAccessor::getReent(),path,mode); +} + +/** + * \internal + * _link_r + * FIXME: implement me + */ +int _link_r(struct _reent *ptr, const char *f_old, const char *f_new) +{ + return -1; +} + +int link(const char *f_old, const char *f_new) +{ + return _link_r(miosix::CReentrancyAccessor::getReent(),f_old,f_new); +} + /** * \internal * _unlink_r, remove a file @@ -481,6 +833,38 @@ int _unlink_r(struct _reent *ptr, const char *file) #endif //WITH_FILESYSTEM } +int unlink(const char *file) +{ + return _unlink_r(miosix::CReentrancyAccessor::getReent(),file); +} + +/** + * \internal + * _rename_r + * FIXME: implement me + */ +int _rename_r(struct _reent *ptr, const char *f_old, const char *f_new) +{ + return -1; +} + +int rename(const char *f_old, const char *f_new) +{ + return _rename_r(miosix::CReentrancyAccessor::getReent(),f_old,f_new); +} + +/** + * \internal + * getdents, FIXME: implement me + */ +int getdents(unsigned int fd, struct dirent *dirp, unsigned int count) +{ + return -1; +} +#endif //TEST_NEW_FS + + + /** * \internal * _times_r, return elapsed time @@ -503,28 +887,37 @@ clock_t _times_r(struct _reent *ptr, struct tms *tim) return 0; } +clock_t times(struct tms *tim) +{ + return _times_r(miosix::CReentrancyAccessor::getReent(),tim); +} + /** * \internal - * _link_r, used by the C standard library function rename(). - * rename(old,new) calls link(old,new) and if link returns 0 it calls - * unlink(old) - * FIXME: implement me + * _gettimeofday_r, FIXME: implement me */ -int _link_r(struct _reent *ptr, const char *f_old, const char *f_new) +int _gettimeofday_r(struct _reent *ptr, struct timeval *tv, void *tz) { return -1; } +int gettimeofday(struct timeval *tv, void *tz) +{ + return _gettimeofday_r(miosix::CReentrancyAccessor::getReent(),tv,tz); +} + /** - * _kill, it looks like abort() calls _kill instead of exit, this implementation - * calls _exit() so that calling abort() really terminates the program + * \internal + * nanosleep, FIXME: implement me */ -int _kill(int pid, int sig) +int nanosleep(const struct timespec *req, struct timespec *rem) { - if(pid==1) _exit(1); //pid=1 means the only running process - else return -1; + return -1; } + + + /** * \internal * it looks like abort() calls _kill instead of exit, this implementation @@ -532,16 +925,13 @@ int _kill(int pid, int sig) */ int _kill_r(struct _reent* ptr, int pid, int sig) { - return _kill(pid,sig); + if(pid==0) _exit(1); //pid=1 means the only running process + else return -1; } -/** - * \internal - * _getpid, there is only one process in Miosix (but multiple threads) - */ -int _getpid() +int kill(int pid, int sig) { - return 1; + return _kill_r(miosix::CReentrancyAccessor::getReent(),pid,sig); } /** @@ -550,16 +940,16 @@ int _getpid() */ int _getpid_r(struct _reent* ptr) { - return _getpid(); + return 0; } /** * \internal - * _fork_r, unimplemented because processes are not supported in Miosix + * getpid, there is only one process in Miosix (but multiple threads) */ -int _fork_r(struct _reent *ptr) +int getpid() { - return -1; + return _getpid_r(miosix::CReentrancyAccessor::getReent()); } /** @@ -571,12 +961,48 @@ int _wait_r(struct _reent *ptr, int *status) return -1; } +int wait(int *status) +{ + return _wait_r(miosix::CReentrancyAccessor::getReent(),status); +} + +/** + * \internal + * _execve_r, unimpemented because processes are not supported in Miosix + */ +int _execve_r(struct _reent *ptr, const char *path, char *const argv[], + char *const env[]) +{ + return -1; +} + +int execve(const char *path, char *const argv[], char *const env[]) +{ + return _execve_r(miosix::CReentrancyAccessor::getReent(),path,argv,env); +} + +/** + * \internal + * _forkexecve_r, reserved for future use + */ +pid_t _forkexecve_r(struct _reent *ptr, const char *path, char *const argv[], + char *const env[]) +{ + return -1; +} + +pid_t forkexecve(const char *path, char *const argv[], char *const env[]) +{ + return _forkexecve_r(miosix::CReentrancyAccessor::getReent(),path,argv,env); +} + #ifdef __cplusplus } #endif + // // Check that newlib has been configured correctly // =============================================== diff --git a/miosix_np_2/nbproject/configurations.xml b/miosix_np_2/nbproject/configurations.xml index 17e6927..6a4e3a6 100644 --- a/miosix_np_2/nbproject/configurations.xml +++ b/miosix_np_2/nbproject/configurations.xml @@ -319,6 +319,10 @@ ff.h integer.h + + mountpointfs.cpp + mountpointfs.h + file.cpp file.h file_access.cpp