From 3bb19feba42174a08842e035d21edd424ce9ced1 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 20 Feb 2011 04:59:31 +0000 Subject: Cleaned up a little, and added a bunch more stuff to myriadfs. As far as I can tell, we're missing rename, chown, and chmod. --- src/myriadfs.cpp | 223 ++++++++++++++++++++++++++++++++++++++++--------- src/myriadfs.h | 13 ++- src/tools/myriadfs.cpp | 62 ++++++++++++-- 3 files changed, 253 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/myriadfs.cpp b/src/myriadfs.cpp index b4ba733..41ba652 100644 --- a/src/myriadfs.cpp +++ b/src/myriadfs.cpp @@ -112,7 +112,8 @@ void Bu::MyriadFs::stat( const Bu::String &sPath, Bu::MyriadFs::Stat &rBuf ) stat( iNode, rBuf, is ); } -Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int iMode ) +Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int iMode, + uint16_t uPerms ) { int32_t iParent = -1; int32_t iNode; @@ -134,16 +135,10 @@ Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int iMode ) // The file wasn't found, but the path leading up to it was. // first, figure out the final path element... - Bu::String::const_iterator iStart = sPath.begin(); - if( *iStart == '/' ) - iStart++; - sio << "Scanning for filename:" << sio.nl; - for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd; - iStart = iEnd+1, iEnd = iStart.find('/') ) { } - Bu::String sName( iStart, sPath.end() ); + Bu::String sName = filePart( sPath ); sio << "End filename: " << sName << sio.nl; sio << "Parent inode: " << iParent << sio.nl; - iNode = create( iParent, sName, 0664|typeRegFile, 0 ); + iNode = create( iParent, sName, (uPerms&permMask)|typeRegFile, 0 ); sio << "New iNode: " << iNode << sio.nl; return openByInode( iNode ); } @@ -183,13 +178,7 @@ void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, // The file wasn't found, but the path leading up to it was. // first, figure out the final path element... - Bu::String::const_iterator iStart = sPath.begin(); - if( *iStart == '/' ) - iStart++; - sio << "Scanning for filename:" << sio.nl; - for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd; - iStart = iEnd+1, iEnd = iStart.find('/') ) { } - Bu::String sName( iStart, sPath.end() ); + Bu::String sName = filePart( sPath ); sio << "End filename: " << sName << sio.nl; sio << "Parent inode: " << iParent << sio.nl; iNode = create( iParent, sName, iPerms, uSpecial ); @@ -202,6 +191,49 @@ void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms ) create( sPath, (iPerms&permMask)|typeDir, 0 ); } +void Bu::MyriadFs::mkSymLink( const Bu::String &sPath, + const Bu::String &sTarget ) +{ + int32_t iParent = -1; + int32_t iNode; + try + { + iNode = lookupInode( sPath, iParent ); + throw Bu::MyriadFsException("Path already exists."); + } + catch( Bu::MyriadFsException &e ) + { + if( iParent < 0 ) + throw; + + // This means that an intermediate path component couldn't be found + if( e.getErrorCode() == 1 ) + throw; + + // The file wasn't found, but the path leading up to it was. + // first, figure out the final path element... + Bu::String sName = filePart( sPath ); + sio << "End filename: " << sName << sio.nl; + sio << "Parent inode: " << iParent << sio.nl; + iNode = create( iParent, sName, 0777|typeSymLink, 0 ); + sio << "New iNode: " << iNode << sio.nl; + MyriadStream ms = openByInode( iNode ); + ms.write( sTarget ); + } +} + +Bu::String Bu::MyriadFs::readSymLink( const Bu::String &sPath ) +{ + int32_t iParent = -1; + int32_t iNode; + iNode = lookupInode( sPath, iParent ); + MyriadStream ms = openByInode( iNode ); + Bu::String sRet; + sRet.setSize( ms.getSize() ); + ms.read( sRet.getStr(), ms.getSize() ); + return sRet; +} + Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath ) { int32_t iParent = -1; @@ -220,6 +252,59 @@ void Bu::MyriadFs::setTimes( const Bu::String &sPath, int64_t iATime, setTimes( iNode, iATime, iMTime ); } +void Bu::MyriadFs::unlink( const Bu::String &sPath ) +{ + int32_t iParent = -1; + int32_t iNode; + + iNode = lookupInode( sPath, iParent ); + + Dir lDir = readDir( iParent ); + + Bu::String sName = filePart( sPath ); + + for( Dir::iterator i = lDir.begin(); i; i++ ) + { + if( sName == (*i).sName ) + { + RawStat rs; + readInode( (*i).iNode, rs ); + if( (rs.uPerms&typeMask) == typeDir ) + { + MyriadStream msDir = mStore.openStream( rs.uStreamIndex ); + int32_t iCount; + msDir.read( &iCount, 4 ); + if( iCount > 0 ) + { + throw Bu::MyriadFsException("Directory not empty."); + } + } + if( --rs.iLinks == 0 ) + { + destroyNode( (*i).iNode ); + } + else + { + writeInode( rs ); + } + lDir.erase( i ); + break; + } + } + + Bu::MyriadStream ms = openByInode( iParent ); + int32_t iNumChildren = lDir.getSize(); + ms.write( &iNumChildren, 4 ); + for( Dir::iterator i = lDir.begin(); i; i++ ) + { + ms.write( &(*i).iNode, 4 ); + uint8_t iSize = (*i).sName.getSize(); + ms.write( &iSize, 1 ); + ms.write( (*i).sName.getStr(), iSize ); + } + ms.setSize( ms.tell() ); +} + dev_t Bu::MyriadFs::devToSys( uint32_t uDev ) { return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF)); @@ -295,6 +380,36 @@ int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart, throw Bu::MyriadFsException( 2, "Path not found"); } +void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs ) +{ + rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) ); + if( rIs.read( &rs, sizeof(RawStat) ) < sizeof(RawStat) ) + throw Bu::MyriadFsException("Filesystem corruption detected."); + if( rs.iNode != iNode ) + throw Bu::MyriadFsException("Filesystem corruption detected."); +} + +void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs ) +{ + MyriadStream ms = mStore.openStream( 2 ); + readInode( iNode, rs, ms ); +} + +void Bu::MyriadFs::writeInode( const RawStat &rs, + MyriadStream &rOs ) +{ + rOs.setSize( hNodeIndex.getSize()*sizeof(RawStat) ); + rOs.setPos( hNodeIndex.get( rs.iNode )*sizeof(RawStat) ); + if( rOs.write( &rs, sizeof(RawStat) ) < sizeof(RawStat) ) + throw Bu::MyriadFsException("Error writing inode to header stream."); +} + +void Bu::MyriadFs::writeInode( const RawStat &rs ) +{ + MyriadStream ms = mStore.openStream( 2 ); + writeInode( rs, ms ); +} + Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode ) { Bu::MyriadStream ms = openByInode( iNode ); @@ -324,11 +439,8 @@ Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode ) Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode ) { - int32_t iIndex = hNodeIndex.get( iNode ); - Bu::MyriadStream ms = mStore.openStream( 2 ); - ms.setPos( iIndex*sizeof(RawStat) ); RawStat rs; - ms.read( &rs, sizeof(RawStat) ); + readInode( iNode, rs ); switch( (rs.uPerms&typeMask) ) { case typeDir: @@ -371,10 +483,6 @@ int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial ) { if( !hNodeIndex.has( iNode ) ) { - Bu::MyriadStream is = mStore.openStream( 2 ); - is.setSize( (hNodeIndex.getSize()+1)*sizeof(RawStat) ); - is.setPos( hNodeIndex.getSize()*sizeof(RawStat) ); - hNodeIndex.insert( iNode, hNodeIndex.getSize() ); RawStat rs; rs.iNode = iNode; @@ -414,7 +522,7 @@ int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial ) rs.iATime = time(NULL); rs.iMTime = time(NULL); rs.iCTime = time(NULL); - is.write( &rs, sizeof(RawStat) ); + writeInode( rs ); return iNode; } @@ -426,11 +534,8 @@ int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial ) void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ) { - rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) ); RawStat rs; - rIs.read( &rs, sizeof(RawStat) ); - if( rs.iNode != iNode ) - throw Bu::MyriadFsException("Filesystem corruption detected."); + readInode( iNode, rs, rIs ); rBuf.iNode = iNode; rBuf.iUser = rs.iUser; rBuf.iGroup = rs.iGroup; @@ -459,11 +564,6 @@ void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ) } } -void Bu::MyriadFs::unlink( int32_t iNode ) -{ - -} - void Bu::MyriadFs::writeHeader() { Bu::MyriadStream ms = mStore.openStream( 1 ); @@ -489,11 +589,58 @@ void Bu::MyriadFs::setTimes( int32_t iNode, int64_t iATime, int64_t iMTime ) RawStat rs; Bu::MyriadStream is = mStore.openStream( 2 ); - is.setPos( hNodeIndex.get(iNode)*sizeof(RawStat) ); - is.read( &rs, sizeof(RawStat) ); + readInode( iNode, rs, is ); rs.iATime = iATime; rs.iMTime = iMTime; - is.setPos( hNodeIndex.get(iNode)*sizeof(RawStat) ); - is.write( &rs, sizeof(RawStat) ); + writeInode( rs, is ); +} + +void Bu::MyriadFs::destroyNode( int32_t iNode ) +{ + if( iNode == 0 ) + throw Bu::MyriadFsException("You cannot destroy the root."); + + Bu::MyriadStream is = mStore.openStream( 2 ); + + // This will be overwritten with the last node + int32_t iPosition = hNodeIndex.get( iNode ); + RawStat rsOld; + readInode( iNode, rsOld, is ); + switch( (rsOld.uPerms&typeMask) ) + { + case typeRegFile: + case typeDir: + case typeSymLink: + mStore.deleteStream( rsOld.uStreamIndex ); + break; + } + + hNodeIndex.erase( iNode ); + + // Read the last node, can't use the helpers, because we don't know the + // iNode yet. + if( iPosition != hNodeIndex.getSize() ) + { + // If this is the last node, then we don't need to do anything, but + // this case handles what to do if we aren't on the last node + RawStat rs; + is.setPos( (hNodeIndex.getSize())*sizeof(RawStat) ); + is.read( &rs, sizeof(RawStat) ); + + hNodeIndex.get( rs.iNode ) = iPosition; + writeInode( rs, is ); + } + + is.setSize( hNodeIndex.getSize() * sizeof(RawStat) ); +} + +Bu::String Bu::MyriadFs::filePart( const Bu::String &sPath ) +{ + Bu::String::const_iterator iStart = sPath.begin(); + if( *iStart == '/' ) + iStart++; + for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd; + iStart = iEnd+1, iEnd = iStart.find('/') ) { } + return Bu::String( iStart, sPath.end() ); } diff --git a/src/myriadfs.h b/src/myriadfs.h index 0b9c97f..b54d170 100644 --- a/src/myriadfs.h +++ b/src/myriadfs.h @@ -133,13 +133,16 @@ namespace Bu typedef Bu::List Dir; void stat( const Bu::String &sPath, Stat &rBuf ); - MyriadStream open( const Bu::String &sPath, int iMode ); + MyriadStream open( const Bu::String &sPath, int iMode, + uint16_t uPerms=0664 ); void create( const Bu::String &sPath, uint16_t iPerms ); void create( const Bu::String &sPath, uint16_t iPerms, uint16_t iDevHi, uint16_t iDevLo ); void create( const Bu::String &sPath, uint16_t iPerms, uint32_t uSpecial ); void mkDir( const Bu::String &sPath, uint16_t iPerms ); + void mkSymLink( const Bu::String &sPath, const Bu::String &sTarget ); + Bu::String readSymLink( const Bu::String &sPath ); Dir readDir( const Bu::String &sPath ); void setTimes( const Bu::String &sPath, int64_t iATime, int64_t iMTime ); @@ -168,15 +171,21 @@ namespace Bu int32_t lookupInode( const Bu::String &sPath, int32_t &iParent ); int32_t lookupInode( Bu::String::const_iterator iStart, int32_t iNode, int32_t &iParent ); + void readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs ); + void readInode( int32_t iNode, RawStat &rs ); + void writeInode( const RawStat &rs ); + void writeInode( const RawStat &rs, MyriadStream &rOs ); Dir readDir( int32_t iNode ); MyriadStream openByInode( int32_t iNode ); int32_t create( int32_t iParent, const Bu::String &sName, uint16_t uPerms, uint32_t uSpecial ); int32_t allocInode( uint16_t uPerms, uint32_t uSpecial ); void stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ); - void unlink( int32_t iNode ); void writeHeader(); void setTimes( int32_t iNode, int64_t iATime, int64_t iMTime ); + void destroyNode( int32_t iNode ); + + Bu::String filePart( const Bu::String &sPath ); private: Bu::Stream &rStore; diff --git a/src/tools/myriadfs.cpp b/src/tools/myriadfs.cpp index c4004b7..8db59d7 100644 --- a/src/tools/myriadfs.cpp +++ b/src/tools/myriadfs.cpp @@ -29,7 +29,6 @@ extern "C" { { try { - printf("myriadfs_getattr: Statting file: %s\n", sPath ); Bu::MyriadFs::Stat st; pFs->stat( sPath, st ); stbuf->st_ino = st.iNode; @@ -78,7 +77,8 @@ extern "C" { Bu::MyriadStream ms = pFs->open( sPath, 0 ); fi->fh = iNextFileId; hOpenFiles.insert( iNextFileId++, ms ); - printf("File opened, %d files open now.\n", hOpenFiles.getSize() ); + printf("File '%s' opened, %d files open now.\n", + sPath, hOpenFiles.getSize() ); return 0; } catch(...) @@ -108,10 +108,11 @@ extern "C" { { try { - Bu::MyriadStream ms = pFs->open( sPath, 0 ); + Bu::MyriadStream ms = pFs->open( sPath, 0, uPerms ); fi->fh = iNextFileId; hOpenFiles.insert( iNextFileId++, ms ); - printf("File created, %d files open now.\n", hOpenFiles.getSize() ); + printf("File '%s' created, %d files open now.\n", + sPath, hOpenFiles.getSize() ); return 0; } catch(...) @@ -136,7 +137,8 @@ extern "C" { static int myriadfs_release( const char *sPath, struct fuse_file_info *fi ) { hOpenFiles.erase( fi->fh ); - printf("File released, %d files open now.\n", hOpenFiles.getSize() ); + printf("File '%s' released, %d files open now.\n", + sPath, hOpenFiles.getSize() ); return 0; } @@ -155,6 +157,52 @@ extern "C" { return 0; } + static int myriadfs_unlink( const char *sPath ) + { + try + { + pFs->unlink( sPath ); + } + catch( Bu::MyriadFsException &e ) + { + printf("MyriadFsException: %s\n", e.what() ); + return -EACCES; + } + return 0; + } + + static int myriadfs_symlink( const char *sTarget, const char *sPath ) + { + try + { + printf("Path = '%s', Target = '%s'\n", sPath, sTarget ); + pFs->mkSymLink( sPath, sTarget ); + } + catch( Bu::MyriadFsException &e ) + { + printf("MyriadFsException: %s\n", e.what() ); + return -EACCES; + } + return 0; + } + + static int myriadfs_readlink( const char *sPath, char *sOut, size_t s ) + { + try + { + Bu::String sTrg = pFs->readSymLink( sPath ); + size_t iLen = (s-1>sTrg.getSize())?(sTrg.getSize()):(s-1); + memcpy( sOut, sTrg.getStr(), iLen ); + sOut[iLen] = '\0'; + } + catch( Bu::MyriadFsException &e ) + { + printf("MyriadFsException: %s\n", e.what() ); + return -EACCES; + } + return 0; + } + static struct fuse_operations myriadfs_oper; int main( int argc, char *argv[] ) @@ -172,6 +220,10 @@ extern "C" { myriadfs_oper.mknod = myriadfs_mknod; myriadfs_oper.release = myriadfs_release; myriadfs_oper.utimens = myriadfs_utimens; + myriadfs_oper.unlink = myriadfs_unlink; + myriadfs_oper.rmdir = myriadfs_unlink; + myriadfs_oper.symlink = myriadfs_symlink; + myriadfs_oper.readlink = myriadfs_readlink; printf("Starting fuse_main.\n"); int iRet = fuse_main( argc, argv, &myriadfs_oper, NULL ); printf("Done with fuse_main.\n"); -- cgit v1.2.3