aboutsummaryrefslogtreecommitdiff
path: root/src/myriadfs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/myriadfs.cpp')
-rw-r--r--src/myriadfs.cpp223
1 files changed, 185 insertions, 38 deletions
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 )
112 stat( iNode, rBuf, is ); 112 stat( iNode, rBuf, is );
113} 113}
114 114
115Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int iMode ) 115Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int iMode,
116 uint16_t uPerms )
116{ 117{
117 int32_t iParent = -1; 118 int32_t iParent = -1;
118 int32_t iNode; 119 int32_t iNode;
@@ -134,16 +135,10 @@ Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int iMode )
134 135
135 // The file wasn't found, but the path leading up to it was. 136 // The file wasn't found, but the path leading up to it was.
136 // first, figure out the final path element... 137 // first, figure out the final path element...
137 Bu::String::const_iterator iStart = sPath.begin(); 138 Bu::String sName = filePart( sPath );
138 if( *iStart == '/' )
139 iStart++;
140 sio << "Scanning for filename:" << sio.nl;
141 for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd;
142 iStart = iEnd+1, iEnd = iStart.find('/') ) { }
143 Bu::String sName( iStart, sPath.end() );
144 sio << "End filename: " << sName << sio.nl; 139 sio << "End filename: " << sName << sio.nl;
145 sio << "Parent inode: " << iParent << sio.nl; 140 sio << "Parent inode: " << iParent << sio.nl;
146 iNode = create( iParent, sName, 0664|typeRegFile, 0 ); 141 iNode = create( iParent, sName, (uPerms&permMask)|typeRegFile, 0 );
147 sio << "New iNode: " << iNode << sio.nl; 142 sio << "New iNode: " << iNode << sio.nl;
148 return openByInode( iNode ); 143 return openByInode( iNode );
149 } 144 }
@@ -183,13 +178,7 @@ void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms,
183 178
184 // The file wasn't found, but the path leading up to it was. 179 // The file wasn't found, but the path leading up to it was.
185 // first, figure out the final path element... 180 // first, figure out the final path element...
186 Bu::String::const_iterator iStart = sPath.begin(); 181 Bu::String sName = filePart( sPath );
187 if( *iStart == '/' )
188 iStart++;
189 sio << "Scanning for filename:" << sio.nl;
190 for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd;
191 iStart = iEnd+1, iEnd = iStart.find('/') ) { }
192 Bu::String sName( iStart, sPath.end() );
193 sio << "End filename: " << sName << sio.nl; 182 sio << "End filename: " << sName << sio.nl;
194 sio << "Parent inode: " << iParent << sio.nl; 183 sio << "Parent inode: " << iParent << sio.nl;
195 iNode = create( iParent, sName, iPerms, uSpecial ); 184 iNode = create( iParent, sName, iPerms, uSpecial );
@@ -202,6 +191,49 @@ void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms )
202 create( sPath, (iPerms&permMask)|typeDir, 0 ); 191 create( sPath, (iPerms&permMask)|typeDir, 0 );
203} 192}
204 193
194void Bu::MyriadFs::mkSymLink( const Bu::String &sPath,
195 const Bu::String &sTarget )
196{
197 int32_t iParent = -1;
198 int32_t iNode;
199 try
200 {
201 iNode = lookupInode( sPath, iParent );
202 throw Bu::MyriadFsException("Path already exists.");
203 }
204 catch( Bu::MyriadFsException &e )
205 {
206 if( iParent < 0 )
207 throw;
208
209 // This means that an intermediate path component couldn't be found
210 if( e.getErrorCode() == 1 )
211 throw;
212
213 // The file wasn't found, but the path leading up to it was.
214 // first, figure out the final path element...
215 Bu::String sName = filePart( sPath );
216 sio << "End filename: " << sName << sio.nl;
217 sio << "Parent inode: " << iParent << sio.nl;
218 iNode = create( iParent, sName, 0777|typeSymLink, 0 );
219 sio << "New iNode: " << iNode << sio.nl;
220 MyriadStream ms = openByInode( iNode );
221 ms.write( sTarget );
222 }
223}
224
225Bu::String Bu::MyriadFs::readSymLink( const Bu::String &sPath )
226{
227 int32_t iParent = -1;
228 int32_t iNode;
229 iNode = lookupInode( sPath, iParent );
230 MyriadStream ms = openByInode( iNode );
231 Bu::String sRet;
232 sRet.setSize( ms.getSize() );
233 ms.read( sRet.getStr(), ms.getSize() );
234 return sRet;
235}
236
205Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath ) 237Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath )
206{ 238{
207 int32_t iParent = -1; 239 int32_t iParent = -1;
@@ -220,6 +252,59 @@ void Bu::MyriadFs::setTimes( const Bu::String &sPath, int64_t iATime,
220 setTimes( iNode, iATime, iMTime ); 252 setTimes( iNode, iATime, iMTime );
221} 253}
222 254
255void Bu::MyriadFs::unlink( const Bu::String &sPath )
256{
257 int32_t iParent = -1;
258 int32_t iNode;
259
260 iNode = lookupInode( sPath, iParent );
261
262 Dir lDir = readDir( iParent );
263
264 Bu::String sName = filePart( sPath );
265
266 for( Dir::iterator i = lDir.begin(); i; i++ )
267 {
268 if( sName == (*i).sName )
269 {
270 RawStat rs;
271 readInode( (*i).iNode, rs );
272 if( (rs.uPerms&typeMask) == typeDir )
273 {
274 MyriadStream msDir = mStore.openStream( rs.uStreamIndex );
275 int32_t iCount;
276 msDir.read( &iCount, 4 );
277 if( iCount > 0 )
278 {
279 throw Bu::MyriadFsException("Directory not empty.");
280 }
281 }
282 if( --rs.iLinks == 0 )
283 {
284 destroyNode( (*i).iNode );
285 }
286 else
287 {
288 writeInode( rs );
289 }
290 lDir.erase( i );
291 break;
292 }
293 }
294
295 Bu::MyriadStream ms = openByInode( iParent );
296 int32_t iNumChildren = lDir.getSize();
297 ms.write( &iNumChildren, 4 );
298 for( Dir::iterator i = lDir.begin(); i; i++ )
299 {
300 ms.write( &(*i).iNode, 4 );
301 uint8_t iSize = (*i).sName.getSize();
302 ms.write( &iSize, 1 );
303 ms.write( (*i).sName.getStr(), iSize );
304 }
305 ms.setSize( ms.tell() );
306}
307
223dev_t Bu::MyriadFs::devToSys( uint32_t uDev ) 308dev_t Bu::MyriadFs::devToSys( uint32_t uDev )
224{ 309{
225 return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF)); 310 return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF));
@@ -295,6 +380,36 @@ int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart,
295 throw Bu::MyriadFsException( 2, "Path not found"); 380 throw Bu::MyriadFsException( 2, "Path not found");
296} 381}
297 382
383void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs )
384{
385 rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) );
386 if( rIs.read( &rs, sizeof(RawStat) ) < sizeof(RawStat) )
387 throw Bu::MyriadFsException("Filesystem corruption detected.");
388 if( rs.iNode != iNode )
389 throw Bu::MyriadFsException("Filesystem corruption detected.");
390}
391
392void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs )
393{
394 MyriadStream ms = mStore.openStream( 2 );
395 readInode( iNode, rs, ms );
396}
397
398void Bu::MyriadFs::writeInode( const RawStat &rs,
399 MyriadStream &rOs )
400{
401 rOs.setSize( hNodeIndex.getSize()*sizeof(RawStat) );
402 rOs.setPos( hNodeIndex.get( rs.iNode )*sizeof(RawStat) );
403 if( rOs.write( &rs, sizeof(RawStat) ) < sizeof(RawStat) )
404 throw Bu::MyriadFsException("Error writing inode to header stream.");
405}
406
407void Bu::MyriadFs::writeInode( const RawStat &rs )
408{
409 MyriadStream ms = mStore.openStream( 2 );
410 writeInode( rs, ms );
411}
412
298Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode ) 413Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode )
299{ 414{
300 Bu::MyriadStream ms = openByInode( iNode ); 415 Bu::MyriadStream ms = openByInode( iNode );
@@ -324,11 +439,8 @@ Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode )
324 439
325Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode ) 440Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode )
326{ 441{
327 int32_t iIndex = hNodeIndex.get( iNode );
328 Bu::MyriadStream ms = mStore.openStream( 2 );
329 ms.setPos( iIndex*sizeof(RawStat) );
330 RawStat rs; 442 RawStat rs;
331 ms.read( &rs, sizeof(RawStat) ); 443 readInode( iNode, rs );
332 switch( (rs.uPerms&typeMask) ) 444 switch( (rs.uPerms&typeMask) )
333 { 445 {
334 case typeDir: 446 case typeDir:
@@ -371,10 +483,6 @@ int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial )
371 { 483 {
372 if( !hNodeIndex.has( iNode ) ) 484 if( !hNodeIndex.has( iNode ) )
373 { 485 {
374 Bu::MyriadStream is = mStore.openStream( 2 );
375 is.setSize( (hNodeIndex.getSize()+1)*sizeof(RawStat) );
376 is.setPos( hNodeIndex.getSize()*sizeof(RawStat) );
377
378 hNodeIndex.insert( iNode, hNodeIndex.getSize() ); 486 hNodeIndex.insert( iNode, hNodeIndex.getSize() );
379 RawStat rs; 487 RawStat rs;
380 rs.iNode = iNode; 488 rs.iNode = iNode;
@@ -414,7 +522,7 @@ int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial )
414 rs.iATime = time(NULL); 522 rs.iATime = time(NULL);
415 rs.iMTime = time(NULL); 523 rs.iMTime = time(NULL);
416 rs.iCTime = time(NULL); 524 rs.iCTime = time(NULL);
417 is.write( &rs, sizeof(RawStat) ); 525 writeInode( rs );
418 526
419 return iNode; 527 return iNode;
420 } 528 }
@@ -426,11 +534,8 @@ int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial )
426 534
427void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ) 535void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs )
428{ 536{
429 rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) );
430 RawStat rs; 537 RawStat rs;
431 rIs.read( &rs, sizeof(RawStat) ); 538 readInode( iNode, rs, rIs );
432 if( rs.iNode != iNode )
433 throw Bu::MyriadFsException("Filesystem corruption detected.");
434 rBuf.iNode = iNode; 539 rBuf.iNode = iNode;
435 rBuf.iUser = rs.iUser; 540 rBuf.iUser = rs.iUser;
436 rBuf.iGroup = rs.iGroup; 541 rBuf.iGroup = rs.iGroup;
@@ -459,11 +564,6 @@ void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs )
459 } 564 }
460} 565}
461 566
462void Bu::MyriadFs::unlink( int32_t iNode )
463{
464
465}
466
467void Bu::MyriadFs::writeHeader() 567void Bu::MyriadFs::writeHeader()
468{ 568{
469 Bu::MyriadStream ms = mStore.openStream( 1 ); 569 Bu::MyriadStream ms = mStore.openStream( 1 );
@@ -489,11 +589,58 @@ void Bu::MyriadFs::setTimes( int32_t iNode, int64_t iATime, int64_t iMTime )
489 RawStat rs; 589 RawStat rs;
490 Bu::MyriadStream is = mStore.openStream( 2 ); 590 Bu::MyriadStream is = mStore.openStream( 2 );
491 591
492 is.setPos( hNodeIndex.get(iNode)*sizeof(RawStat) ); 592 readInode( iNode, rs, is );
493 is.read( &rs, sizeof(RawStat) );
494 rs.iATime = iATime; 593 rs.iATime = iATime;
495 rs.iMTime = iMTime; 594 rs.iMTime = iMTime;
496 is.setPos( hNodeIndex.get(iNode)*sizeof(RawStat) ); 595 writeInode( rs, is );
497 is.write( &rs, sizeof(RawStat) ); 596}
597
598void Bu::MyriadFs::destroyNode( int32_t iNode )
599{
600 if( iNode == 0 )
601 throw Bu::MyriadFsException("You cannot destroy the root.");
602
603 Bu::MyriadStream is = mStore.openStream( 2 );
604
605 // This will be overwritten with the last node
606 int32_t iPosition = hNodeIndex.get( iNode );
607 RawStat rsOld;
608 readInode( iNode, rsOld, is );
609 switch( (rsOld.uPerms&typeMask) )
610 {
611 case typeRegFile:
612 case typeDir:
613 case typeSymLink:
614 mStore.deleteStream( rsOld.uStreamIndex );
615 break;
616 }
617
618 hNodeIndex.erase( iNode );
619
620 // Read the last node, can't use the helpers, because we don't know the
621 // iNode yet.
622 if( iPosition != hNodeIndex.getSize() )
623 {
624 // If this is the last node, then we don't need to do anything, but
625 // this case handles what to do if we aren't on the last node
626 RawStat rs;
627 is.setPos( (hNodeIndex.getSize())*sizeof(RawStat) );
628 is.read( &rs, sizeof(RawStat) );
629
630 hNodeIndex.get( rs.iNode ) = iPosition;
631 writeInode( rs, is );
632 }
633
634 is.setSize( hNodeIndex.getSize() * sizeof(RawStat) );
635}
636
637Bu::String Bu::MyriadFs::filePart( const Bu::String &sPath )
638{
639 Bu::String::const_iterator iStart = sPath.begin();
640 if( *iStart == '/' )
641 iStart++;
642 for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd;
643 iStart = iEnd+1, iEnd = iStart.find('/') ) { }
644 return Bu::String( iStart, sPath.end() );
498} 645}
499 646