diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/myriadfs.cpp | 292 | ||||
| -rw-r--r-- | src/myriadfs.h | 100 |
2 files changed, 375 insertions, 17 deletions
diff --git a/src/myriadfs.cpp b/src/myriadfs.cpp index c8d23b6..4e2a0f6 100644 --- a/src/myriadfs.cpp +++ b/src/myriadfs.cpp | |||
| @@ -10,6 +10,11 @@ | |||
| 10 | 10 | ||
| 11 | #include <string.h> | 11 | #include <string.h> |
| 12 | #include <unistd.h> | 12 | #include <unistd.h> |
| 13 | #include <time.h> | ||
| 14 | |||
| 15 | #include "bu/sio.h" | ||
| 16 | using Bu::sio; | ||
| 17 | using Bu::Fmt; | ||
| 13 | 18 | ||
| 14 | namespace Bu { subExceptionDef( MyriadFsException ) } | 19 | namespace Bu { subExceptionDef( MyriadFsException ) } |
| 15 | 20 | ||
| @@ -17,8 +22,15 @@ namespace Bu { subExceptionDef( MyriadFsException ) } | |||
| 17 | 22 | ||
| 18 | Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : | 23 | Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : |
| 19 | rStore( rStore ), | 24 | rStore( rStore ), |
| 20 | mStore( rStore, iBlockSize ) | 25 | mStore( rStore, iBlockSize ), |
| 26 | iUser( 0 ), | ||
| 27 | iGroup( 0 ) | ||
| 21 | { | 28 | { |
| 29 | #ifndef WIN32 | ||
| 30 | iUser = getuid(); | ||
| 31 | iGroup = getgid(); | ||
| 32 | #endif | ||
| 33 | |||
| 22 | if( mStore.hasStream( 1 ) ) | 34 | if( mStore.hasStream( 1 ) ) |
| 23 | { | 35 | { |
| 24 | // Check to see if this is a MyriadFs stream. | 36 | // Check to see if this is a MyriadFs stream. |
| @@ -32,6 +44,8 @@ Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : | |||
| 32 | "a MyriadFs stream."); | 44 | "a MyriadFs stream."); |
| 33 | 45 | ||
| 34 | int8_t iVer; | 46 | int8_t iVer; |
| 47 | ms.read( &iVer, 1 ); | ||
| 48 | throw MyriadFsException("You totally have a MyriadFs stream, version %d, but they can't be loaded yet.", iVer ); | ||
| 35 | } | 49 | } |
| 36 | else | 50 | else |
| 37 | { | 51 | { |
| @@ -43,43 +57,299 @@ Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : | |||
| 43 | int8_t iVer = 1; | 57 | int8_t iVer = 1; |
| 44 | int32_t iTmp = 1; | 58 | int32_t iTmp = 1; |
| 45 | ms.write( &iVer, 1 ); | 59 | ms.write( &iVer, 1 ); |
| 46 | ms.write( &iBlockSize, 4 ); | ||
| 47 | ms.write( &iTmp, 4 ); // iNumNodes | 60 | ms.write( &iTmp, 4 ); // iNumNodes |
| 48 | iTmp = 0; | 61 | iTmp = 0; |
| 49 | ms.write( &iTmp, 4 ); // iInode | 62 | ms.write( &iTmp, 4 ); // iInode |
| 50 | ms.write( &iTmp, 0 ); // iPosition | 63 | ms.write( &iTmp, 4 ); // iPosition |
| 64 | hNodeIndex.insert( 0, 0 ); | ||
| 51 | } | 65 | } |
| 52 | 66 | ||
| 53 | // Create initial inode stream, with one root node. | 67 | // Create initial inode stream, with one root node. |
| 54 | { | 68 | { |
| 55 | mStore.createStream( 2 ); | 69 | mStore.createStream( 2 ); |
| 56 | Bu::MyriadStream ms = mStore.openStream( 2 ); | 70 | Bu::MyriadStream ms = mStore.openStream( 2 ); |
| 57 | int32_t iUser = 0, iGroup = 0; | ||
| 58 | #ifndef WIN32 | ||
| 59 | iUser = getuid(); | ||
| 60 | iGroup = getgid(); | ||
| 61 | #endif | ||
| 62 | int32_t iTmp32 = 0; | 71 | int32_t iTmp32 = 0; |
| 63 | int16_t iTmp16 = 0; | 72 | int16_t iTmp16 = 0; |
| 73 | uint16_t uPerms = 775|typeDir; | ||
| 64 | ms.write( &iUser, 4 ); // User | 74 | ms.write( &iUser, 4 ); // User |
| 65 | ms.write( &iGroup, 4 ); // Group | 75 | ms.write( &iGroup, 4 ); // Group |
| 66 | ms.write( &iTmp16, 2 ); // Meta? I...don't remember this | 76 | ms.write( &uPerms, 2 ); // Permissions/types |
| 67 | ms.write( &iTmp16, 2 ); // Permissions/types | 77 | ms.write( &iTmp16, 2 ); // Link count |
| 68 | iTmp32 = 3; | 78 | iTmp32 = 3; |
| 69 | ms.write( &iTmp32, 4 ); // Stream index | 79 | ms.write( &iTmp32, 4 ); // Stream index |
| 70 | iTmp32 = 0; | 80 | iTmp32 = 0; |
| 71 | ms.write( &iTmp32, 4 ); // Parent inode | 81 | ms.write( &iTmp32, 4 ); // Parent inode (root's it's own parent) |
| 82 | int64_t iTime = time(NULL); | ||
| 83 | ms.write( &iTime, 8 ); // atime | ||
| 84 | ms.write( &iTime, 8 ); // mtime | ||
| 85 | ms.write( &iTime, 8 ); // ctime | ||
| 72 | ms.write( &iTmp16, 2 ); // Name size | 86 | ms.write( &iTmp16, 2 ); // Name size |
| 73 | } | 87 | } |
| 74 | 88 | ||
| 75 | // Create inode 0's storage stream. | 89 | // Create inode 0's storage stream. |
| 76 | { | 90 | { |
| 77 | mStore.createStream( 3 ); | 91 | mStore.createStream( 3 ); |
| 92 | Bu::MyriadStream ms = mStore.openStream( 3 ); | ||
| 93 | int32_t iTmp32 = 0; | ||
| 94 | ms.write( &iTmp32, 4 ); // iChildCount | ||
| 78 | } | 95 | } |
| 79 | } | 96 | } |
| 80 | } | 97 | } |
| 81 | 98 | ||
| 82 | Bu::MyriadFs::~MyriadFs() | 99 | Bu::MyriadFs::~MyriadFs() |
| 83 | { | 100 | { |
| 101 | writeHeader(); | ||
| 102 | } | ||
| 103 | |||
| 104 | void Bu::MyriadFs::stat( const Bu::String &sPath, Bu::MyriadFs::Stat &rBuf ) | ||
| 105 | { | ||
| 106 | int32_t iParent; | ||
| 107 | int32_t iNode = lookupInode( sPath, iParent ); | ||
| 108 | Bu::MyriadStream is = mStore.openStream( 2 ); | ||
| 109 | stat( iNode, rBuf, is ); | ||
| 110 | } | ||
| 111 | |||
| 112 | Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int iMode ) | ||
| 113 | { | ||
| 114 | int32_t iParent = -1; | ||
| 115 | int32_t iNode; | ||
| 116 | try | ||
| 117 | { | ||
| 118 | iNode = lookupInode( sPath, iParent ); | ||
| 119 | sio << "File found." << sio.nl; | ||
| 120 | // The file was found | ||
| 121 | return openByInode( iNode ); | ||
| 122 | } | ||
| 123 | catch( Bu::MyriadFsException &e ) | ||
| 124 | { | ||
| 125 | if( iParent < 0 ) | ||
| 126 | throw; | ||
| 127 | |||
| 128 | // The file wasn't found, but the path leading up to it was. | ||
| 129 | // first, figure out the final path element... | ||
| 130 | Bu::String::const_iterator iStart = sPath.begin(); | ||
| 131 | if( *iStart == '/' ) | ||
| 132 | iStart++; | ||
| 133 | sio << "Scanning for filename:" << sio.nl; | ||
| 134 | for( Bu::String::const_iterator iEnd = iStart.find('/')+1; iEnd; iStart = iEnd ) { } | ||
| 135 | Bu::String sName( iStart, sPath.end() ); | ||
| 136 | sio << "End filename: " << sName << sio.nl; | ||
| 137 | sio << "Parent inode: " << iParent << sio.nl; | ||
| 138 | iNode = create( iParent, sName, 0664|typeRegFile ); | ||
| 139 | sio << "New iNode: " << iNode << sio.nl; | ||
| 140 | return openByInode( iNode ); | ||
| 141 | } | ||
| 142 | |||
| 143 | return mStore.openStream( 2 ); | ||
| 144 | } | ||
| 145 | |||
| 146 | int32_t Bu::MyriadFs::lookupInode( const Bu::String &sPath, int32_t &iParent ) | ||
| 147 | { | ||
| 148 | if( sPath[0] == '/' ) | ||
| 149 | { | ||
| 150 | // Absolute lookup | ||
| 151 | return lookupInode( sPath.begin()+1, 0, iParent ); | ||
| 152 | } | ||
| 153 | else | ||
| 154 | { | ||
| 155 | // Relative lookup | ||
| 156 | throw Bu::ExceptionBase( | ||
| 157 | "Relative lookups in MyriadFs are not working yet."); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart, | ||
| 162 | int32_t iNode, int32_t &iParent ) | ||
| 163 | { | ||
| 164 | iParent = iNode; | ||
| 165 | |||
| 166 | Bu::String::const_iterator iEnd = iStart.find('/'); | ||
| 167 | Bu::String sTok( iStart, iEnd ); | ||
| 168 | |||
| 169 | sio << "Direcotry component: " << sTok << sio.nl; | ||
| 170 | |||
| 171 | Dir lDir = readDir( iNode ); | ||
| 172 | |||
| 173 | for( Dir::iterator i = lDir.begin(); i; i++ ) | ||
| 174 | { | ||
| 175 | if( (*i).sName == sTok ) | ||
| 176 | { | ||
| 177 | // We found an item | ||
| 178 | if( !iEnd ) | ||
| 179 | { | ||
| 180 | // It's the last one in the requested path, return it | ||
| 181 | return (*i).iNode; | ||
| 182 | } | ||
| 183 | else | ||
| 184 | { | ||
| 185 | // Not the last one in our path, double check it's a dir | ||
| 186 | if( ((*i).uPerms&typeMask) == typeDir ) | ||
| 187 | { | ||
| 188 | return lookupInode( iEnd+1, (*i).iNode ); | ||
| 189 | } | ||
| 190 | else | ||
| 191 | { | ||
| 192 | iParent = -1; | ||
| 193 | throw Bu::MyriadFsException( | ||
| 194 | "Element '%s' in given path is not a directory.", | ||
| 195 | sTok.getStr() ); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | throw Bu::MyriadFsException( 1, "Path not found"); | ||
| 202 | } | ||
| 203 | |||
| 204 | Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode ) | ||
| 205 | { | ||
| 206 | Bu::MyriadStream ms = openByInode( iNode ); | ||
| 207 | int32_t iNumChildren; | ||
| 208 | ms.read( &iNumChildren, 4 ); | ||
| 209 | |||
| 210 | Bu::MyriadStream is = mStore.openStream( 2 ); | ||
| 211 | Dir lDir; | ||
| 212 | sio << "Reading dir, " << iNumChildren << " entries:" << sio.nl; | ||
| 213 | for( int32_t j = 0; j < iNumChildren; j++ ) | ||
| 214 | { | ||
| 215 | int32_t iChildNode; | ||
| 216 | ms.read( &iChildNode, 4 ); | ||
| 217 | Stat s; | ||
| 218 | stat( iChildNode, s, is ); | ||
| 219 | lDir.append( s ); | ||
| 220 | |||
| 221 | sio << " " << s.sName << sio.nl; | ||
| 222 | } | ||
| 223 | |||
| 224 | return lDir; | ||
| 225 | } | ||
| 226 | |||
| 227 | Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode ) | ||
| 228 | { | ||
| 229 | int32_t iIndex = hNodeIndex.get( iNode ); | ||
| 230 | Bu::MyriadStream ms = mStore.openStream( 2 ); | ||
| 231 | ms.setPos( mStore.getBlockSize()*iIndex ); | ||
| 232 | RawStat rs; | ||
| 233 | ms.read( &rs, sizeof(RawStat) ); | ||
| 234 | switch( (rs.uPerms&typeMask) ) | ||
| 235 | { | ||
| 236 | case typeDir: | ||
| 237 | case typeSymLink: | ||
| 238 | case typeRegFile: | ||
| 239 | return mStore.openStream( rs.iStreamIndex ); | ||
| 240 | |||
| 241 | default: | ||
| 242 | throw Bu::MyriadFsException( | ||
| 243 | "inode incorrect type for low-level openByInode."); | ||
| 244 | } | ||
| 245 | } | ||
| 246 | |||
| 247 | int32_t Bu::MyriadFs::create( int32_t iParent, const Bu::String &sName, | ||
| 248 | uint16_t uPerms ) | ||
| 249 | { | ||
| 250 | Bu::MyriadStream ms = openByInode( iParent ); | ||
| 251 | int32_t iNumChildren; | ||
| 252 | ms.read( &iNumChildren, 4 ); | ||
| 253 | iNumChildren++; | ||
| 254 | ms.setPos( 0 ); | ||
| 255 | ms.write( &iNumChildren, 4 ); | ||
| 256 | ms.setPos( iNumChildren*4 ); // Actually 4+(iNumChildren-1)*4 :-P | ||
| 257 | int32_t iNode = allocInode( sName, iParent, uPerms ); | ||
| 258 | ms.write( &iNode, 4 ); | ||
| 259 | return iNode; | ||
| 260 | } | ||
| 261 | |||
| 262 | int32_t Bu::MyriadFs::allocInode( const Bu::String &sName, int32_t iParent, | ||
| 263 | uint16_t uPerms ) | ||
| 264 | { | ||
| 265 | int32_t iNode = 0; | ||
| 266 | for(; iNode < 0xfffffff; iNode++ ) | ||
| 267 | { | ||
| 268 | if( !hNodeIndex.has( iNode ) ) | ||
| 269 | { | ||
| 270 | Bu::MyriadStream is = mStore.openStream( 2 ); | ||
| 271 | is.setSize( (hNodeIndex.getSize()+1)*mStore.getBlockSize() ); | ||
| 272 | is.setPos( hNodeIndex.getSize()*mStore.getBlockSize() ); | ||
| 273 | |||
| 274 | hNodeIndex.insert( iNode, hNodeIndex.getSize() ); | ||
| 275 | RawStat rs; | ||
| 276 | rs.iUser = iUser; | ||
| 277 | rs.iGroup = iGroup; | ||
| 278 | rs.uPerms = uPerms; | ||
| 279 | rs.iLinks = 1; | ||
| 280 | switch( (uPerms&typeMask) ) | ||
| 281 | { | ||
| 282 | case typeDir: | ||
| 283 | case typeRegFile: | ||
| 284 | case typeSymLink: | ||
| 285 | rs.iStreamIndex = mStore.createStream(); | ||
| 286 | break; | ||
| 287 | |||
| 288 | default: | ||
| 289 | rs.iStreamIndex = 0; | ||
| 290 | break; | ||
| 291 | } | ||
| 292 | rs.iParentNode = iParent; | ||
| 293 | rs.iATime = time(NULL); | ||
| 294 | rs.iMTime = time(NULL); | ||
| 295 | rs.iCTime = time(NULL); | ||
| 296 | rs.iNameSize = sName.getSize(); | ||
| 297 | is.write( &rs, sizeof(RawStat) ); | ||
| 298 | is.write( sName.getStr(), sName.getSize() ); | ||
| 299 | |||
| 300 | return iNode; | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | throw Bu::MyriadFsException( | ||
| 305 | "No inode could be allocated. You've run out!"); | ||
| 306 | } | ||
| 307 | |||
| 308 | void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ) | ||
| 309 | { | ||
| 310 | rIs.setPos( hNodeIndex.get( iNode )*mStore.getBlockSize() ); | ||
| 311 | RawStat rs; | ||
| 312 | rIs.read( &rs, sizeof(RawStat) ); | ||
| 313 | rBuf.sName.setSize( rs.iNameSize ); | ||
| 314 | rIs.read( rBuf.sName.getStr(), rs.iNameSize ); | ||
| 315 | rBuf.iNode = iNode; | ||
| 316 | rBuf.iUser = rs.iUser; | ||
| 317 | rBuf.iGroup = rs.iGroup; | ||
| 318 | rBuf.uPerms = rs.uPerms; | ||
| 319 | rBuf.iLinks = rs.iLinks; | ||
| 320 | rBuf.iATime = rs.iATime; | ||
| 321 | rBuf.iMTime = rs.iMTime; | ||
| 322 | rBuf.iCTime = rs.iCTime; | ||
| 323 | switch( (rBuf.uPerms&typeMask) ) | ||
| 324 | { | ||
| 325 | case typeRegFile: | ||
| 326 | case typeSymLink: | ||
| 327 | rBuf.iSize = mStore.getStreamSize( rs.iStreamIndex ); | ||
| 328 | break; | ||
| 329 | |||
| 330 | default: | ||
| 331 | rBuf.iSize = 0; | ||
| 332 | break; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | void Bu::MyriadFs::writeHeader() | ||
| 337 | { | ||
| 338 | Bu::MyriadStream ms = mStore.openStream( 1 ); | ||
| 339 | ms.write( Myriad_Fs_MAGIC_CODE, 4 ); | ||
| 340 | int8_t iVer = 1; | ||
| 341 | int32_t iNumNodes = hNodeIndex.getSize(); | ||
| 342 | ms.write( &iVer, 1 ); | ||
| 343 | ms.write( &iNumNodes, 4 ); // iNumNodes | ||
| 344 | for( NodeIndex::iterator i = hNodeIndex.begin(); i; i++ ) | ||
| 345 | { | ||
| 346 | int32_t iNode = i.getKey(); | ||
| 347 | int32_t iPosition = i.getValue(); | ||
| 348 | ms.write( &iNode, 4 ); | ||
| 349 | ms.write( &iPosition, 4 ); | ||
| 350 | } | ||
| 351 | |||
| 352 | // Truncate the stream afterwards so we don't use up too much space. | ||
| 353 | ms.setSize( ms.tell() ); | ||
| 84 | } | 354 | } |
| 85 | 355 | ||
diff --git a/src/myriadfs.h b/src/myriadfs.h index 856137c..808444b 100644 --- a/src/myriadfs.h +++ b/src/myriadfs.h | |||
| @@ -19,13 +19,10 @@ namespace Bu | |||
| 19 | /** | 19 | /** |
| 20 | * A POSIX compliant, node based filesystem built on top of Myriad. | 20 | * A POSIX compliant, node based filesystem built on top of Myriad. |
| 21 | * | 21 | * |
| 22 | * Think about putting this all in one stream, on block boundaries. | ||
| 23 | * | ||
| 24 | * A header is placed into stream 1. | 22 | * A header is placed into stream 1. |
| 25 | * Header format: | 23 | * Header format: |
| 26 | * int32_t iMagicHeader (A7188B39) | 24 | * int32_t iMagicHeader (A7188B39) |
| 27 | * int8_t iVersion (1) | 25 | * int8_t iVersion (1) |
| 28 | * int32_t iNodeSize | ||
| 29 | * int32_t iNumNodes | 26 | * int32_t iNumNodes |
| 30 | * NodeLookup[iNumNodes] nNode | 27 | * NodeLookup[iNumNodes] nNode |
| 31 | * | 28 | * |
| @@ -33,10 +30,10 @@ namespace Bu | |||
| 33 | * int32_t iInode | 30 | * int32_t iInode |
| 34 | * int32_t iPosition | 31 | * int32_t iPosition |
| 35 | * | 32 | * |
| 36 | * The node headers or inode structures have a base size of 22 bytes. | 33 | * The node headers or inode structures have a base size of 46 bytes. |
| 37 | * Everything else in the block is used for the name. I.e. if you have | 34 | * Everything else in the block is used for the name. I.e. if you have |
| 38 | * a blocksize of 512 bytes then you wind up with a max name size of | 35 | * a blocksize of 512 bytes then you wind up with a max name size of |
| 39 | * 512-22=490 characters, or a blocksize of 256 gives you 234 chraacters | 36 | * 512-46=466 characters, or a blocksize of 256 gives you 210 chraacters |
| 40 | * as a max. The node headers are all stored in stream 2. | 37 | * as a max. The node headers are all stored in stream 2. |
| 41 | * Basic node header format: | 38 | * Basic node header format: |
| 42 | * int32_t iUser | 39 | * int32_t iUser |
| @@ -50,6 +47,27 @@ namespace Bu | |||
| 50 | * int64_t iCTime | 47 | * int64_t iCTime |
| 51 | * int16_t iNameSize | 48 | * int16_t iNameSize |
| 52 | * char[iNameSize] sName | 49 | * char[iNameSize] sName |
| 50 | * | ||
| 51 | * Some types get special formats for their assosiated data stream, or | ||
| 52 | * other special considerations, here's a list: | ||
| 53 | * | ||
| 54 | * - typeFifo: No stream, iStreamIndex unused (probably) | ||
| 55 | * - typeChrDev: No stream, iStreamIndex is device hi/lo | ||
| 56 | * - typeDir: The stream contains a directory contents listing, described | ||
| 57 | * below | ||
| 58 | * - typeBlkDev: No stream, iStreamIndex is device hi/lo | ||
| 59 | * - typeRegFile: The stream is the file data | ||
| 60 | * - typeSymLink: The stream is the destination of the symlink | ||
| 61 | * - typeSocket: No steram, iStreamIndex unused (probably) | ||
| 62 | * | ||
| 63 | * Directory streams have this simple listing format. They contain a list | ||
| 64 | * of all child elements, with no particular order at the moment. The . and | ||
| 65 | * .. entries are not listed, they are implicit: | ||
| 66 | * int32_t iNumNodes | ||
| 67 | * NodeTable[iNumNodes] nChildren | ||
| 68 | * | ||
| 69 | * NodeTable: | ||
| 70 | * int32_t iInode | ||
| 53 | */ | 71 | */ |
| 54 | class MyriadFs | 72 | class MyriadFs |
| 55 | { | 73 | { |
| @@ -79,11 +97,81 @@ namespace Bu | |||
| 79 | typeSymLink = 0120000, | 97 | typeSymLink = 0120000, |
| 80 | typeSocket = 0140000, | 98 | typeSocket = 0140000, |
| 81 | typeMask = 0170000 | 99 | typeMask = 0170000 |
| 82 | } | 100 | }; |
| 101 | |||
| 102 | enum | ||
| 103 | { | ||
| 104 | Read = 0x01, ///< Open file for reading | ||
| 105 | Write = 0x02, ///< Open file for writing | ||
| 106 | Create = 0x04, ///< Create file if it doesn't exist | ||
| 107 | Truncate = 0x08, ///< Truncate file if it does exist | ||
| 108 | Append = 0x10, ///< Always append on every write | ||
| 109 | NonBlock = 0x20, ///< Open file in non-blocking mode | ||
| 110 | Exclusive = 0x44, ///< Create file, if it exists then fail | ||
| 111 | |||
| 112 | // Helpful mixes | ||
| 113 | ReadWrite = 0x03, ///< Open for reading and writing | ||
| 114 | WriteNew = 0x0E ///< Create a file (or truncate) for writing. | ||
| 115 | /// Same as Write|Create|Truncate | ||
| 116 | }; | ||
| 117 | |||
| 118 | class Stat | ||
| 119 | { | ||
| 120 | public: | ||
| 121 | int32_t iNode; | ||
| 122 | int32_t iUser; | ||
| 123 | int32_t iGroup; | ||
| 124 | uint16_t uPerms; | ||
| 125 | int16_t iLinks; | ||
| 126 | int64_t iATime; | ||
| 127 | int64_t iMTime; | ||
| 128 | int64_t iCTime; | ||
| 129 | int32_t iSize; | ||
| 130 | Bu::String sName; | ||
| 131 | }; | ||
| 132 | typedef Bu::List<Stat> Dir; | ||
| 133 | |||
| 134 | void stat( const Bu::String &sPath, Stat &rBuf ); | ||
| 135 | MyriadStream open( const Bu::String &sPath, int iMode ); | ||
| 136 | // void create( const Bu::String &sPath, uint16_t iPerms ); | ||
| 137 | |||
| 138 | |||
| 139 | private: | ||
| 140 | class RawStat | ||
| 141 | { | ||
| 142 | public: | ||
| 143 | int32_t iUser; | ||
| 144 | int32_t iGroup; | ||
| 145 | uint16_t uPerms; | ||
| 146 | int16_t iLinks; | ||
| 147 | int32_t iStreamIndex; | ||
| 148 | int32_t iParentNode; | ||
| 149 | int64_t iATime; | ||
| 150 | int64_t iMTime; | ||
| 151 | int64_t iCTime; | ||
| 152 | int16_t iNameSize; | ||
| 153 | }; | ||
| 154 | typedef Bu::Hash<int32_t, int32_t> NodeIndex; | ||
| 155 | |||
| 156 | private: | ||
| 157 | int32_t lookupInode( const Bu::String &sPath, int32_t &iParent ); | ||
| 158 | int32_t lookupInode( Bu::String::const_iterator iStart, | ||
| 159 | int32_t iNode, int32_t &iParent ); | ||
| 160 | Dir readDir( int32_t iNode ); | ||
| 161 | MyriadStream openByInode( int32_t iNode ); | ||
| 162 | int32_t create( int32_t iParent, const Bu::String &sName, | ||
| 163 | uint16_t uPerms ); | ||
| 164 | int32_t allocInode( const Bu::String &sName, int32_t iParent, | ||
| 165 | uint16_t uPerms ); | ||
| 166 | void stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ); | ||
| 167 | void writeHeader(); | ||
| 83 | 168 | ||
| 84 | private: | 169 | private: |
| 85 | Bu::Stream &rStore; | 170 | Bu::Stream &rStore; |
| 86 | Bu::Myriad mStore; | 171 | Bu::Myriad mStore; |
| 172 | NodeIndex hNodeIndex; | ||
| 173 | int32_t iUser; | ||
| 174 | int32_t iGroup; | ||
| 87 | }; | 175 | }; |
| 88 | }; | 176 | }; |
| 89 | 177 | ||
