From 26bb069c535e3fd5b0e0fb28fb54a2a540b60a84 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Fri, 18 Feb 2011 17:41:24 +0000 Subject: Some Uuid tweaks, not much, just figuring out the format. MyriadFs is coming along quite nicely. It looks like it works great for normal programs, but there need to be some tweaks made to a few things before it's working 100% via fuse. Also, the fuse module won't let you specify a file, a little odd. --- src/myriadfs.cpp | 144 +++++++++++++++++++++++++++++++++++++++++++------ src/myriadfs.h | 32 +++++++---- src/tests/myriadfs.cpp | 24 ++++++++- src/tests/uuid.cpp | 1 + src/tools/myriadfs.cpp | 124 +++++++++++++++++++++++++++++++++++++++++- src/uuid.cpp | 10 ++++ src/uuid.h | 3 ++ 7 files changed, 309 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/myriadfs.cpp b/src/myriadfs.cpp index 4e2a0f6..8312bce 100644 --- a/src/myriadfs.cpp +++ b/src/myriadfs.cpp @@ -45,7 +45,17 @@ Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : int8_t iVer; ms.read( &iVer, 1 ); - throw MyriadFsException("You totally have a MyriadFs stream, version %d, but they can't be loaded yet.", iVer ); + + int32_t iNumNodes; + ms.read( &iNumNodes, 4 ); + for( int32_t j = 0; j < iNumNodes; j++ ) + { + int32_t iNode; + int32_t iPos; + ms.read( &iNode, 4 ); + ms.read( &iPos, 4 ); + hNodeIndex.insert( iNode, iPos ); + } } else { @@ -125,26 +135,103 @@ Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int iMode ) 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::const_iterator iStart = sPath.begin(); if( *iStart == '/' ) iStart++; sio << "Scanning for filename:" << sio.nl; - for( Bu::String::const_iterator iEnd = iStart.find('/')+1; iEnd; iStart = iEnd ) { } + for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd; + iStart = iEnd+1, iEnd = iStart.find('/') ) { } Bu::String sName( iStart, sPath.end() ); sio << "End filename: " << sName << sio.nl; sio << "Parent inode: " << iParent << sio.nl; - iNode = create( iParent, sName, 0664|typeRegFile ); + iNode = create( iParent, sName, 0664|typeRegFile, 0 ); sio << "New iNode: " << iNode << sio.nl; return openByInode( iNode ); } +} + +void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms ) +{ + create( sPath, iPerms, 0 ); +} - return mStore.openStream( 2 ); +void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, + uint16_t iDevHi, uint16_t iDevLo ) +{ + create( sPath, iPerms, ((uint32_t)iDevHi<<16)|(uint32_t)iDevLo ); +} + +void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, + uint32_t uSpecial ) +{ + int32_t iParent = -1; + int32_t iNode; + try + { + iNode = lookupInode( sPath, iParent ); + sio << "File found." << sio.nl; + // The file was found + 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::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() ); + sio << "End filename: " << sName << sio.nl; + sio << "Parent inode: " << iParent << sio.nl; + iNode = create( iParent, sName, iPerms, uSpecial ); + sio << "New iNode: " << iNode << sio.nl; + } +} + +void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms ) +{ + create( sPath, (iPerms&permMask)|typeDir, 0 ); +} + +Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath ) +{ + int32_t iParent = -1; + int32_t iNode = lookupInode( sPath, iParent ); + return readDir( iNode ); +} + +dev_t Bu::MyriadFs::devToSys( uint32_t uDev ) +{ + return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF)); +} + +uint32_t Bu::MyriadFs::sysToDev( dev_t uDev ) +{ + return (((uint32_t)uDev&0xFF00)<<8) | ((uint32_t)uDev&0xFF); } int32_t Bu::MyriadFs::lookupInode( const Bu::String &sPath, int32_t &iParent ) { + if( sPath == "/" ) + { + return 0; + } if( sPath[0] == '/' ) { // Absolute lookup @@ -185,7 +272,7 @@ int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart, // Not the last one in our path, double check it's a dir if( ((*i).uPerms&typeMask) == typeDir ) { - return lookupInode( iEnd+1, (*i).iNode ); + return lookupInode( iEnd+1, (*i).iNode, iParent ); } else { @@ -198,13 +285,16 @@ int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart, } } - throw Bu::MyriadFsException( 1, "Path not found"); + if( iEnd ) + throw Bu::MyriadFsException( 1, "Path not found"); + else + throw Bu::MyriadFsException( 2, "Path not found"); } Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode ) { Bu::MyriadStream ms = openByInode( iNode ); - int32_t iNumChildren; + int32_t iNumChildren = 0; ms.read( &iNumChildren, 4 ); Bu::MyriadStream is = mStore.openStream( 2 ); @@ -236,7 +326,7 @@ Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode ) case typeDir: case typeSymLink: case typeRegFile: - return mStore.openStream( rs.iStreamIndex ); + return mStore.openStream( rs.uStreamIndex ); default: throw Bu::MyriadFsException( @@ -245,22 +335,22 @@ Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode ) } int32_t Bu::MyriadFs::create( int32_t iParent, const Bu::String &sName, - uint16_t uPerms ) + uint16_t uPerms, uint32_t uSpecial ) { Bu::MyriadStream ms = openByInode( iParent ); - int32_t iNumChildren; + int32_t iNumChildren = 0; ms.read( &iNumChildren, 4 ); iNumChildren++; ms.setPos( 0 ); ms.write( &iNumChildren, 4 ); ms.setPos( iNumChildren*4 ); // Actually 4+(iNumChildren-1)*4 :-P - int32_t iNode = allocInode( sName, iParent, uPerms ); + int32_t iNode = allocInode( sName, iParent, uPerms, uSpecial ); ms.write( &iNode, 4 ); return iNode; } int32_t Bu::MyriadFs::allocInode( const Bu::String &sName, int32_t iParent, - uint16_t uPerms ) + uint16_t uPerms, uint32_t uSpecial ) { int32_t iNode = 0; for(; iNode < 0xfffffff; iNode++ ) @@ -279,14 +369,29 @@ int32_t Bu::MyriadFs::allocInode( const Bu::String &sName, int32_t iParent, rs.iLinks = 1; switch( (uPerms&typeMask) ) { - case typeDir: case typeRegFile: case typeSymLink: - rs.iStreamIndex = mStore.createStream(); + rs.uStreamIndex = mStore.createStream(); + break; + + case typeDir: + rs.uStreamIndex = mStore.createStream(); + { + Bu::MyriadStream msDir = mStore.openStream( + rs.uStreamIndex + ); + uint32_t uSize = 0; + msDir.write( &uSize, 4 ); + } + break; + + case typeChrDev: + case typeBlkDev: + rs.uStreamIndex = uSpecial; break; default: - rs.iStreamIndex = 0; + rs.uStreamIndex = 0; break; } rs.iParentNode = iParent; @@ -320,11 +425,18 @@ void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ) rBuf.iATime = rs.iATime; rBuf.iMTime = rs.iMTime; rBuf.iCTime = rs.iCTime; + rBuf.uDev = 0; + rBuf.iSize = 0; switch( (rBuf.uPerms&typeMask) ) { case typeRegFile: case typeSymLink: - rBuf.iSize = mStore.getStreamSize( rs.iStreamIndex ); + rBuf.iSize = mStore.getStreamSize( rs.uStreamIndex ); + break; + + case typeChrDev: + case typeBlkDev: + rBuf.uDev = rs.uStreamIndex; break; default: diff --git a/src/myriadfs.h b/src/myriadfs.h index 808444b..3eecca5 100644 --- a/src/myriadfs.h +++ b/src/myriadfs.h @@ -8,6 +8,8 @@ #ifndef MYRIAD_FS_H #define MYRIAD_FS_H +#include + #include "bu/myriad.h" namespace Bu @@ -38,9 +40,9 @@ namespace Bu * Basic node header format: * int32_t iUser * int32_t iGroup - * int16_t iPerms + * uint16_t uPerms * int16_t iLinks - * int32_t iStreamIndex + * uint32_t uStreamIndex * int32_t iParentNode * int64_t iATime * int64_t iMTime @@ -51,14 +53,14 @@ namespace Bu * Some types get special formats for their assosiated data stream, or * other special considerations, here's a list: * - * - typeFifo: No stream, iStreamIndex unused (probably) - * - typeChrDev: No stream, iStreamIndex is device hi/lo + * - typeFifo: No stream, uStreamIndex unused (probably) + * - typeChrDev: No stream, uStreamIndex is device hi/lo * - typeDir: The stream contains a directory contents listing, described * below - * - typeBlkDev: No stream, iStreamIndex is device hi/lo + * - typeBlkDev: No stream, uStreamIndex is device hi/lo * - typeRegFile: The stream is the file data * - typeSymLink: The stream is the destination of the symlink - * - typeSocket: No steram, iStreamIndex unused (probably) + * - typeSocket: No steram, uStreamIndex unused (probably) * * Directory streams have this simple listing format. They contain a list * of all child elements, with no particular order at the moment. The . and @@ -89,6 +91,7 @@ namespace Bu permSticky = 0001000, permSetGid = 0002000, permSetUid = 0004000, + permMask = 0007777, typeFifo = 0010000, typeChrDev = 0020000, typeDir = 0040000, @@ -127,14 +130,23 @@ namespace Bu int64_t iMTime; int64_t iCTime; int32_t iSize; + uint32_t uDev; Bu::String sName; }; typedef Bu::List Dir; void stat( const Bu::String &sPath, Stat &rBuf ); MyriadStream open( const Bu::String &sPath, int iMode ); -// void create( const Bu::String &sPath, uint16_t iPerms ); + 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 ); + Dir readDir( const Bu::String &sPath ); + static dev_t devToSys( uint32_t uDev ); + static uint32_t sysToDev( dev_t uDev ); private: class RawStat @@ -144,7 +156,7 @@ namespace Bu int32_t iGroup; uint16_t uPerms; int16_t iLinks; - int32_t iStreamIndex; + uint32_t uStreamIndex; int32_t iParentNode; int64_t iATime; int64_t iMTime; @@ -160,9 +172,9 @@ namespace Bu Dir readDir( int32_t iNode ); MyriadStream openByInode( int32_t iNode ); int32_t create( int32_t iParent, const Bu::String &sName, - uint16_t uPerms ); + uint16_t uPerms, uint32_t uSpecial ); int32_t allocInode( const Bu::String &sName, int32_t iParent, - uint16_t uPerms ); + uint16_t uPerms, uint32_t uSpecial ); void stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ); void writeHeader(); diff --git a/src/tests/myriadfs.cpp b/src/tests/myriadfs.cpp index fd96c02..5946b27 100644 --- a/src/tests/myriadfs.cpp +++ b/src/tests/myriadfs.cpp @@ -8,19 +8,41 @@ using namespace Bu; int main( int argc, char *argv[] ) { - Bu::MemBuf mb; +// Bu::MemBuf mb; + Bu::File mb("store.myr", File::Read|File::Write|File::Create ); Bu::MyriadFs mfs( mb, 512 ); + sio << "Creating dirs..." << sio.nl; + mfs.create("/etc", Bu::MyriadFs::typeDir|0755 ); + mfs.create("/dev", Bu::MyriadFs::typeDir|0755 ); + mfs.create("/usr", Bu::MyriadFs::typeDir|0755 ); + + mfs.create("/dev/null", Bu::MyriadFs::typeChrDev|0666, 1, 3 ); + mfs.create("/dev/zero", Bu::MyriadFs::typeChrDev|0666, 1, 5 ); + mfs.create("/dev/sda", Bu::MyriadFs::typeBlkDev|0660, 8, 0 ); + + sio << "Creating files..." << sio.nl; { Bu::MyriadStream ms = mfs.open("/hello", Bu::MyriadFs::Read ); ms.write("world!"); } + { + Bu::MyriadStream ms = mfs.open("/etc/hello", Bu::MyriadFs::Read ); + ms.write("world, again!"); + } + sio << "Reading files..." << sio.nl; { Bu::MyriadStream ms = mfs.open("/hello", Bu::MyriadFs::Read ); char buf[512]; buf[ms.read( buf, 512 )] = '\0'; sio << "read: '" << buf << "'" << sio.nl; } + { + Bu::MyriadStream ms = mfs.open("/etc/hello", Bu::MyriadFs::Read ); + char buf[512]; + buf[ms.read( buf, 512 )] = '\0'; + sio << "read: '" << buf << "'" << sio.nl; + } } diff --git a/src/tests/uuid.cpp b/src/tests/uuid.cpp index b6470fa..d2f67b1 100644 --- a/src/tests/uuid.cpp +++ b/src/tests/uuid.cpp @@ -15,6 +15,7 @@ int main() Uuid i = Uuid::gen(); sio << i.toString() << sio.nl; + sio << "Version: " << i.getVersion() << sio.nl; return 0; } diff --git a/src/tools/myriadfs.cpp b/src/tools/myriadfs.cpp index 88db0c0..3956311 100644 --- a/src/tools/myriadfs.cpp +++ b/src/tools/myriadfs.cpp @@ -10,36 +10,156 @@ #include #include +#include + +#include +#include +#include +#include + +Bu::File *pF = NULL; +Bu::MyriadFs *pFs = NULL; + +typedef Bu::Hash FileHash; +FileHash hOpenFiles; +int64_t iNextFileId = 0; extern "C" { static int myriadfs_getattr( const char *sPath, struct stat *stbuf ) { - + try + { + printf("myriadfs_getattr: Statting file: %s\n", sPath ); + Bu::MyriadFs::Stat st; + pFs->stat( sPath, st ); + stbuf->st_ino = st.iNode; + stbuf->st_mode = st.uPerms; + stbuf->st_nlink = st.iLinks; + stbuf->st_uid = st.iUser; + stbuf->st_gid = st.iGroup; + stbuf->st_rdev = Bu::MyriadFs::devToSys( st.uDev ); + stbuf->st_size = st.iSize; + stbuf->st_blocks = 8; + stbuf->st_atime = st.iATime; + stbuf->st_mtime = st.iMTime; + stbuf->st_ctime = st.iCTime; + return 0; + } + catch(...) + { + return -ENOENT; + } } static int myriadfs_readdir( const char *sPath, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi ) { + fprintf( stderr, "Reading dir...\n"); + Bu::MyriadFs::Dir lDir = pFs->readDir( sPath ); + filler( buf, ".", NULL, 0 ); + filler( buf, "..", NULL, 0 ); + for( Bu::MyriadFs::Dir::iterator i = lDir.begin(); i; i++ ) + { + fprintf( stderr, "Adding file: '%s'\n", (*i).sName.getStr() ); + filler( buf, (*i).sName.getStr(), NULL, 0 ); + } + + return 0; + } + + static int myriadfs_mkdir( const char *sPath, mode_t uMode ) + { + pFs->mkDir( sPath, uMode ); + return 0; } static int myriadfs_open( const char *sPath, struct fuse_file_info *fi ) { + try + { + Bu::MyriadStream ms = pFs->open( sPath, 0 ); + fi->fh = iNextFileId; + hOpenFiles.insert( iNextFileId++, ms ); + return 0; + } + catch(...) + { + return -EACCES; + } } static int myriadfs_read( const char *sPath, char *buf, size_t iSize, off_t iOffset, struct fuse_file_info *fi ) { + Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); + ms.setPos( iOffset ); + return ms.read( buf, iSize ); + } + + static int myriadfs_write( const char *sPath, const char *buf, size_t iSize, + off_t iOffset, struct fuse_file_info *fi ) + { + Bu::MyriadStream &ms = hOpenFiles.get( fi->fh ); + ms.setPos( iOffset ); + return ms.write( buf, iSize ); + } + + static int myriadfs_create( const char *sPath, mode_t uPerms, + struct fuse_file_info *fi ) + { + try + { + Bu::MyriadStream ms = pFs->open( sPath, 0 ); + fi->fh = iNextFileId; + hOpenFiles.insert( iNextFileId++, ms ); + return 0; + } + catch(...) + { + return -EACCES; + } + } + + static int myriadfs_mknod( const char *sPath, mode_t uPerms, dev_t Dev ) + { + try + { + pFs->create( sPath, uPerms, Bu::MyriadFs::sysToDev( Dev ) ); + return 0; + } + catch(...) + { + return -EACCES; + } + } + + static int myriadfs_release( const char *sPath, struct fuse_file_info *fi ) + { + hOpenFiles.erase( fi->fh ); + + return 0; } static struct fuse_operations myriadfs_oper; int main( int argc, char *argv[] ) { + pF = new Bu::File("store.myr", Bu::File::Read|Bu::File::Write|Bu::File::Create ); + pFs = new Bu::MyriadFs( *pF, 512 ); memset( &myriadfs_oper, sizeof(myriadfs_oper), 0 ); myriadfs_oper.getattr = myriadfs_getattr; myriadfs_oper.readdir = myriadfs_readdir; + myriadfs_oper.mkdir = myriadfs_mkdir; myriadfs_oper.open = myriadfs_open; myriadfs_oper.read = myriadfs_read; - return fuse_main( argc, argv, &myriadfs_oper, NULL ); + myriadfs_oper.write = myriadfs_write; + myriadfs_oper.create = myriadfs_create; + myriadfs_oper.mknod = myriadfs_mknod; + printf("Starting fuse_main.\n"); + int iRet = fuse_main( argc, argv, &myriadfs_oper, NULL ); + printf("Done with fuse_main.\n"); + delete pFs; + delete pF; + return iRet; } } diff --git a/src/uuid.cpp b/src/uuid.cpp index 69af5b4..d34a989 100644 --- a/src/uuid.cpp +++ b/src/uuid.cpp @@ -45,6 +45,16 @@ Bu::String Bu::Uuid::toString() return mb.getString(); } +Bu::String Bu::Uuid::toUrn() +{ + return "urn:uuid:" + toString(); +} + +int Bu::Uuid::getVersion() +{ + return (data[6]&((8|4|2|1)<<4))>>4; +} + #define msb( i ) (1<<(7-i)) void Bu::Uuid::clear() diff --git a/src/uuid.h b/src/uuid.h index 327686f..ee7469b 100644 --- a/src/uuid.h +++ b/src/uuid.h @@ -21,6 +21,9 @@ namespace Bu Bu::String toRawString(); Bu::String toString(); + Bu::String toUrn(); + + int getVersion(); static Uuid gen(); static Uuid genV1(); -- cgit v1.2.3