/*************************************************************************** * 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" #include #include #include #include "filesystem/stringpart.h" using namespace std; namespace miosix { #ifdef WITH_FILESYSTEM /** * Directory class for MountpointFs */ class MountpointFsDirectory : public DirectoryBase { public: /** * \param parent parent filesystem * \param mutex mutex to lock when accessing the file map * \param dirs file map * \param root true if we're listing the root directory * \param currentInode inode of the directory we're listing * \param parentInode inode of the parent directory */ MountpointFsDirectory(intrusive_ref_ptr parent, FastMutex& mutex, map& dirs, bool root, int currentInode, int parentInode) : DirectoryBase(parent), mutex(mutex), dirs(dirs), currentInode(currentInode), parentInode(parentInode), first(true), last(false) { Lock l(mutex); if(root && dirs.empty()==false) currentItem=dirs.begin()->first.c_str(); } /** * Also directories can be opened as files. In this case, this system call * allows to retrieve directory entries. * \param dp pointer to a memory buffer where one or more struct dirent * will be placed. dp must be four words aligned. * \param len memory buffer size. * \return the number of bytes read on success, or a negative number on * failure. */ virtual int getdents(void *dp, int len); private: FastMutex& mutex; ///< Mutex of parent class std::map& dirs; ///< Directory entries of parent class string currentItem; ///< First unhandled item in directory int currentInode,parentInode; ///< Inodes of . and .. bool first; ///< True if first time getdents is called bool last; ///< True if directory has ended }; // // class MountpointFsDirctory // int MountpointFsDirectory::getdents(void *dp, int len) { if(len l(mutex); char *begin=reinterpret_cast(dp); char *buffer=begin; char *end=buffer+len; if(first) { first=false; addDefaultEntries(&buffer,currentInode,parentInode); } if(currentItem.empty()==false) { map::iterator it=dirs.find(StringPart(currentItem)); //Someone deleted the exact directory entry we had saved (unlikely) if(it==dirs.end()) return -EBADF; for(;it!=dirs.end();++it) { if(addEntry(&buffer,end,it->second,DT_DIR,it->first)>0) continue; //Buffer finished currentItem=it->first.c_str(); return buffer-begin; } } addTerminatingEntry(&buffer,end); last=true; return buffer-begin; } // // class MountpointFs // int MountpointFs::open(intrusive_ref_ptr& file, StringPart& name, int flags, int mode) { if(flags & (O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC)) return -EACCES; Lock l(mutex); int currentInode=rootDirInode; int parentInode=parentFsMountpointInode; if(name.empty()==false) { map::iterator it=dirs.find(name); if(it==dirs.end()) return -EACCES; parentInode=currentInode; currentInode=it->second; } file=intrusive_ref_ptr( new MountpointFsDirectory( shared_from_this(),mutex,dirs,name.empty(),currentInode,parentInode)); return 0; } int MountpointFs::lstat(StringPart& name, struct stat *pstat) { Lock l(mutex); map::iterator it; if(name.empty()==false) { it=dirs.find(name); if(it==dirs.end()) return -ENOENT; } memset(pstat,0,sizeof(struct stat)); pstat->st_dev=filesystemId; pstat->st_ino=name.empty() ? rootDirInode : it->second; pstat->st_mode=S_IFDIR | 0755; //drwxr-xr-x pstat->st_nlink=1; pstat->st_blksize=512; return 0; } int MountpointFs::unlink(StringPart& name) { return -ENOENT; } int MountpointFs::rename(StringPart& oldName, StringPart& newName) { Lock l(mutex); map::iterator it=dirs.find(oldName); if(it==dirs.end()) return -ENOENT; for(unsigned int i=0;isecond; dirs.erase(it); return 0; } int MountpointFs::mkdir(StringPart& name, int mode) { for(unsigned int i=0;i l(mutex); if(dirs.insert(make_pair(name,inodeCount)).second==false) return -EEXIST; inodeCount++; return 0; } int MountpointFs::rmdir(StringPart& name) { Lock l(mutex); if(dirs.erase(name)==1) return 0; return -ENOENT; } #endif //WITH_FILESYSTEM } //namespace miosix