summaryrefslogtreecommitdiff
path: root/src/unstable/myriadfs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/unstable/myriadfs.cpp')
-rw-r--r--src/unstable/myriadfs.cpp1078
1 files changed, 539 insertions, 539 deletions
diff --git a/src/unstable/myriadfs.cpp b/src/unstable/myriadfs.cpp
index 6ed176d..3680c3f 100644
--- a/src/unstable/myriadfs.cpp
+++ b/src/unstable/myriadfs.cpp
@@ -19,686 +19,686 @@ using Bu::Fmt;
19 19
20namespace Bu { subExceptionDef( MyriadFsException ) } 20namespace Bu { subExceptionDef( MyriadFsException ) }
21 21
22#define Myriad_Fs_MAGIC_CODE ((char *)"\xa7\x18\x8b\x39") 22#define Myriad_Fs_MAGIC_CODE ((char *)"\xa7\x18\x8b\x39")
23 23
24Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : 24Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) :
25 rStore( rStore ), 25 rStore( rStore ),
26 mStore( rStore, iBlockSize ), 26 mStore( rStore, iBlockSize ),
27 iUser( 0 ), 27 iUser( 0 ),
28 iGroup( 0 ) 28 iGroup( 0 )
29{ 29{
30#ifndef WIN32 30#ifndef WIN32
31 iUser = getuid(); 31 iUser = getuid();
32 iGroup = getgid(); 32 iGroup = getgid();
33#endif 33#endif
34 34
35 if( mStore.hasStream( 1 ) ) 35 if( mStore.hasStream( 1 ) )
36 { 36 {
37 // Check to see if this is a MyriadFs stream. 37 // Check to see if this is a MyriadFs stream.
38 Bu::MyriadStream ms = mStore.openStream( 1 ); 38 Bu::MyriadStream ms = mStore.openStream( 1 );
39 char sMagic[4]; 39 char sMagic[4];
40 if( ms.read( sMagic, 4 ) < 4 ) 40 if( ms.read( sMagic, 4 ) < 4 )
41 throw MyriadFsException("The provided stream does not appear to be " 41 throw MyriadFsException("The provided stream does not appear to be "
42 "a MyriadFs stream."); 42 "a MyriadFs stream.");
43 if( ::strncmp( sMagic, Myriad_Fs_MAGIC_CODE, 4 ) ) 43 if( ::strncmp( sMagic, Myriad_Fs_MAGIC_CODE, 4 ) )
44 throw MyriadFsException("The provided stream does not appear to be " 44 throw MyriadFsException("The provided stream does not appear to be "
45 "a MyriadFs stream."); 45 "a MyriadFs stream.");
46 46
47 int8_t iVer; 47 int8_t iVer;
48 ms.read( &iVer, 1 ); 48 ms.read( &iVer, 1 );
49 49
50 int32_t iNumNodes; 50 int32_t iNumNodes;
51 ms.read( &iNumNodes, 4 ); 51 ms.read( &iNumNodes, 4 );
52 for( int32_t j = 0; j < iNumNodes; j++ ) 52 for( int32_t j = 0; j < iNumNodes; j++ )
53 { 53 {
54 int32_t iNode; 54 int32_t iNode;
55 int32_t iPos; 55 int32_t iPos;
56 ms.read( &iNode, 4 ); 56 ms.read( &iNode, 4 );
57 ms.read( &iPos, 4 ); 57 ms.read( &iPos, 4 );
58 hNodeIndex.insert( iNode, iPos ); 58 hNodeIndex.insert( iNode, iPos );
59 } 59 }
60 } 60 }
61 else 61 else
62 { 62 {
63 // Create initial header stream 63 // Create initial header stream
64 { 64 {
65 mStore.createStream( 1 ); 65 mStore.createStream( 1 );
66 Bu::MyriadStream ms = mStore.openStream( 1 ); 66 Bu::MyriadStream ms = mStore.openStream( 1 );
67 ms.write( Myriad_Fs_MAGIC_CODE, 4 ); 67 ms.write( Myriad_Fs_MAGIC_CODE, 4 );
68 int8_t iVer = 1; 68 int8_t iVer = 1;
69 int32_t iTmp = 1; 69 int32_t iTmp = 1;
70 ms.write( &iVer, 1 ); 70 ms.write( &iVer, 1 );
71 ms.write( &iTmp, 4 ); // iNumNodes 71 ms.write( &iTmp, 4 ); // iNumNodes
72 iTmp = 0; 72 iTmp = 0;
73 ms.write( &iTmp, 4 ); // iInode 73 ms.write( &iTmp, 4 ); // iInode
74 ms.write( &iTmp, 4 ); // iPosition 74 ms.write( &iTmp, 4 ); // iPosition
75 hNodeIndex.insert( 0, 0 ); 75 hNodeIndex.insert( 0, 0 );
76 } 76 }
77 77
78 // Create initial inode stream, with one root node. 78 // Create initial inode stream, with one root node.
79 { 79 {
80 mStore.createStream( 2 ); 80 mStore.createStream( 2 );
81 Bu::MyriadStream ms = mStore.openStream( 2 ); 81 Bu::MyriadStream ms = mStore.openStream( 2 );
82 RawStat rs; 82 RawStat rs;
83 rs.iNode = 0; 83 rs.iNode = 0;
84 rs.iUser = iUser; 84 rs.iUser = iUser;
85 rs.iGroup = iGroup; 85 rs.iGroup = iGroup;
86 rs.uPerms = 0755|typeDir; 86 rs.uPerms = 0755|typeDir;
87 rs.iLinks = 1; 87 rs.iLinks = 1;
88 rs.uStreamIndex = 3; 88 rs.uStreamIndex = 3;
89 rs.iCTime = rs.iMTime = rs.iATime = time(NULL); 89 rs.iCTime = rs.iMTime = rs.iATime = time(NULL);
90 ms.write( &rs, sizeof(RawStat) ); 90 ms.write( &rs, sizeof(RawStat) );
91 } 91 }
92 92
93 // Create inode 0's storage stream. 93 // Create inode 0's storage stream.
94 { 94 {
95 mStore.createStream( 3 ); 95 mStore.createStream( 3 );
96 Bu::MyriadStream ms = mStore.openStream( 3 ); 96 Bu::MyriadStream ms = mStore.openStream( 3 );
97 int32_t iTmp32 = 0; 97 int32_t iTmp32 = 0;
98 ms.write( &iTmp32, 4 ); // iChildCount 98 ms.write( &iTmp32, 4 ); // iChildCount
99 } 99 }
100 } 100 }
101} 101}
102 102
103Bu::MyriadFs::~MyriadFs() 103Bu::MyriadFs::~MyriadFs()
104{ 104{
105 writeHeader(); 105 writeHeader();
106} 106}
107 107
108void Bu::MyriadFs::stat( const Bu::String &sPath, Bu::MyriadFs::Stat &rBuf ) 108void Bu::MyriadFs::stat( const Bu::String &sPath, Bu::MyriadFs::Stat &rBuf )
109{ 109{
110 int32_t iParent; 110 int32_t iParent;
111 int32_t iNode = lookupInode( sPath, iParent ); 111 int32_t iNode = lookupInode( sPath, iParent );
112 Bu::MyriadStream is = mStore.openStream( 2 ); 112 Bu::MyriadStream is = mStore.openStream( 2 );
113 stat( iNode, rBuf, is ); 113 stat( iNode, rBuf, is );
114} 114}
115 115
116Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int /*iMode*/, 116Bu::MyriadStream Bu::MyriadFs::open( const Bu::String &sPath, int /*iMode*/,
117 uint16_t uPerms ) 117 uint16_t uPerms )
118{ 118{
119 int32_t iParent = -1; 119 int32_t iParent = -1;
120 int32_t iNode; 120 int32_t iNode;
121 try 121 try
122 { 122 {
123 iNode = lookupInode( sPath, iParent ); 123 iNode = lookupInode( sPath, iParent );
124 sio << "File found." << sio.nl; 124 sio << "File found." << sio.nl;
125 // The file was found 125 // The file was found
126 return openByInode( iNode ); 126 return openByInode( iNode );
127 } 127 }
128 catch( Bu::MyriadFsException &e ) 128 catch( Bu::MyriadFsException &e )
129 { 129 {
130 if( iParent < 0 ) 130 if( iParent < 0 )
131 throw; 131 throw;
132 132
133 // This means that an intermediate path component couldn't be found 133 // This means that an intermediate path component couldn't be found
134 if( e.getErrorCode() == 1 ) 134 if( e.getErrorCode() == 1 )
135 throw; 135 throw;
136 136
137 // The file wasn't found, but the path leading up to it was. 137 // The file wasn't found, but the path leading up to it was.
138 // first, figure out the final path element... 138 // first, figure out the final path element...
139 Bu::String sName = filePart( sPath ); 139 Bu::String sName = filePart( sPath );
140 sio << "End filename: " << sName << sio.nl; 140 sio << "End filename: " << sName << sio.nl;
141 sio << "Parent inode: " << iParent << sio.nl; 141 sio << "Parent inode: " << iParent << sio.nl;
142 iNode = create( iParent, sName, (uPerms&permMask)|typeRegFile, 0 ); 142 iNode = create( iParent, sName, (uPerms&permMask)|typeRegFile, 0 );
143 sio << "New iNode: " << iNode << sio.nl; 143 sio << "New iNode: " << iNode << sio.nl;
144 return openByInode( iNode ); 144 return openByInode( iNode );
145 } 145 }
146} 146}
147 147
148void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms ) 148void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms )
149{ 149{
150 create( sPath, iPerms, 0 ); 150 create( sPath, iPerms, 0 );
151} 151}
152 152
153void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, 153void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms,
154 uint16_t iDevHi, uint16_t iDevLo ) 154 uint16_t iDevHi, uint16_t iDevLo )
155{ 155{
156 create( sPath, iPerms, ((uint32_t)iDevHi<<16)|(uint32_t)iDevLo ); 156 create( sPath, iPerms, ((uint32_t)iDevHi<<16)|(uint32_t)iDevLo );
157} 157}
158 158
159void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms, 159void Bu::MyriadFs::create( const Bu::String &sPath, uint16_t iPerms,
160 uint32_t uSpecial ) 160 uint32_t uSpecial )
161{ 161{
162 int32_t iParent = -1; 162 int32_t iParent = -1;
163 int32_t iNode; 163 int32_t iNode;
164 try 164 try
165 { 165 {
166 iNode = lookupInode( sPath, iParent ); 166 iNode = lookupInode( sPath, iParent );
167 sio << "File found." << sio.nl; 167 sio << "File found." << sio.nl;
168 // The file was found 168 // The file was found
169 throw Bu::MyriadFsException("Path already exists."); 169 throw Bu::MyriadFsException("Path already exists.");
170 } 170 }
171 catch( Bu::MyriadFsException &e ) 171 catch( Bu::MyriadFsException &e )
172 { 172 {
173 if( iParent < 0 ) 173 if( iParent < 0 )
174 throw; 174 throw;
175 175
176 // This means that an intermediate path component couldn't be found 176 // This means that an intermediate path component couldn't be found
177 if( e.getErrorCode() == 1 ) 177 if( e.getErrorCode() == 1 )
178 throw; 178 throw;
179 179
180 // The file wasn't found, but the path leading up to it was. 180 // The file wasn't found, but the path leading up to it was.
181 // first, figure out the final path element... 181 // first, figure out the final path element...
182 Bu::String sName = filePart( sPath ); 182 Bu::String sName = filePart( sPath );
183 sio << "End filename: " << sName << sio.nl; 183 sio << "End filename: " << sName << sio.nl;
184 sio << "Parent inode: " << iParent << sio.nl; 184 sio << "Parent inode: " << iParent << sio.nl;
185 iNode = create( iParent, sName, iPerms, uSpecial ); 185 iNode = create( iParent, sName, iPerms, uSpecial );
186 sio << "New iNode: " << iNode << sio.nl; 186 sio << "New iNode: " << iNode << sio.nl;
187 } 187 }
188} 188}
189 189
190void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms ) 190void Bu::MyriadFs::mkDir( const Bu::String &sPath, uint16_t iPerms )
191{ 191{
192 create( sPath, (iPerms&permMask)|typeDir, 0 ); 192 create( sPath, (iPerms&permMask)|typeDir, 0 );
193} 193}
194 194
195void Bu::MyriadFs::mkSymLink( const Bu::String &sTarget, 195void Bu::MyriadFs::mkSymLink( const Bu::String &sTarget,
196 const Bu::String &sPath ) 196 const Bu::String &sPath )
197{ 197{
198 int32_t iParent = -1; 198 int32_t iParent = -1;
199 int32_t iNode; 199 int32_t iNode;
200 try 200 try
201 { 201 {
202 iNode = lookupInode( sPath, iParent ); 202 iNode = lookupInode( sPath, iParent );
203 throw Bu::MyriadFsException("Path already exists."); 203 throw Bu::MyriadFsException("Path already exists.");
204 } 204 }
205 catch( Bu::MyriadFsException &e ) 205 catch( Bu::MyriadFsException &e )
206 { 206 {
207 if( iParent < 0 ) 207 if( iParent < 0 )
208 throw; 208 throw;
209 209
210 // This means that an intermediate path component couldn't be found 210 // This means that an intermediate path component couldn't be found
211 if( e.getErrorCode() == 1 ) 211 if( e.getErrorCode() == 1 )
212 throw; 212 throw;
213 213
214 // The file wasn't found, but the path leading up to it was. 214 // The file wasn't found, but the path leading up to it was.
215 // first, figure out the final path element... 215 // first, figure out the final path element...
216 Bu::String sName = filePart( sPath ); 216 Bu::String sName = filePart( sPath );
217 sio << "End filename: " << sName << sio.nl; 217 sio << "End filename: " << sName << sio.nl;
218 sio << "Parent inode: " << iParent << sio.nl; 218 sio << "Parent inode: " << iParent << sio.nl;
219 iNode = create( iParent, sName, 0777|typeSymLink, 0 ); 219 iNode = create( iParent, sName, 0777|typeSymLink, 0 );
220 sio << "New iNode: " << iNode << sio.nl; 220 sio << "New iNode: " << iNode << sio.nl;
221 MyriadStream ms = openByInode( iNode ); 221 MyriadStream ms = openByInode( iNode );
222 ms.write( sTarget ); 222 ms.write( sTarget );
223 } 223 }
224} 224}
225 225
226void Bu::MyriadFs::mkHardLink( const Bu::String &sTarget, 226void Bu::MyriadFs::mkHardLink( const Bu::String &sTarget,
227 const Bu::String &sPath ) 227 const Bu::String &sPath )
228{ 228{
229 int32_t iParent = -1; 229 int32_t iParent = -1;
230 int32_t iNode; 230 int32_t iNode;
231 231
232 iNode = lookupInode( sTarget, iParent ); 232 iNode = lookupInode( sTarget, iParent );
233 233
234 try 234 try
235 { 235 {
236 lookupInode( sPath, iParent ); 236 lookupInode( sPath, iParent );
237 throw Bu::MyriadFsException("Path already exists."); 237 throw Bu::MyriadFsException("Path already exists.");
238 } 238 }
239 catch( Bu::MyriadFsException &e ) 239 catch( Bu::MyriadFsException &e )
240 { 240 {
241 if( iParent < 0 ) 241 if( iParent < 0 )
242 throw; 242 throw;
243 243
244 // This means that an intermediate path component couldn't be found 244 // This means that an intermediate path component couldn't be found
245 if( e.getErrorCode() == 1 ) 245 if( e.getErrorCode() == 1 )
246 throw; 246 throw;
247 247
248 // The file wasn't found, but the path leading up to it was. 248 // The file wasn't found, but the path leading up to it was.
249 // first, figure out the final path element... 249 // first, figure out the final path element...
250 Bu::String sName = filePart( sPath ); 250 Bu::String sName = filePart( sPath );
251 sio << "End filename: " << sName << sio.nl; 251 sio << "End filename: " << sName << sio.nl;
252 sio << "Parent inode: " << iParent << sio.nl; 252 sio << "Parent inode: " << iParent << sio.nl;
253 addToDir( iParent, iNode, sName ); 253 addToDir( iParent, iNode, sName );
254 MyriadStream is = mStore.openStream( 2 ); 254 MyriadStream is = mStore.openStream( 2 );
255 RawStat rs; 255 RawStat rs;
256 readInode( iNode, rs, is ); 256 readInode( iNode, rs, is );
257 rs.iLinks++; 257 rs.iLinks++;
258 writeInode( rs, is ); 258 writeInode( rs, is );
259 } 259 }
260} 260}
261 261
262Bu::String Bu::MyriadFs::readSymLink( const Bu::String &sPath ) 262Bu::String Bu::MyriadFs::readSymLink( const Bu::String &sPath )
263{ 263{
264 int32_t iParent = -1; 264 int32_t iParent = -1;
265 int32_t iNode; 265 int32_t iNode;
266 iNode = lookupInode( sPath, iParent ); 266 iNode = lookupInode( sPath, iParent );
267 MyriadStream ms = openByInode( iNode ); 267 MyriadStream ms = openByInode( iNode );
268 Bu::String sRet; 268 Bu::String sRet;
269 sRet.setSize( ms.getSize() ); 269 sRet.setSize( ms.getSize() );
270 ms.read( sRet.getStr(), ms.getSize() ); 270 ms.read( sRet.getStr(), ms.getSize() );
271 return sRet; 271 return sRet;
272} 272}
273 273
274Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath ) 274Bu::MyriadFs::Dir Bu::MyriadFs::readDir( const Bu::String &sPath )
275{ 275{
276 int32_t iParent = -1; 276 int32_t iParent = -1;
277 int32_t iNode = lookupInode( sPath, iParent ); 277 int32_t iNode = lookupInode( sPath, iParent );
278 return readDir( iNode ); 278 return readDir( iNode );
279} 279}
280 280
281void Bu::MyriadFs::setTimes( const Bu::String &sPath, int64_t iATime, 281void Bu::MyriadFs::setTimes( const Bu::String &sPath, int64_t iATime,
282 int64_t iMTime ) 282 int64_t iMTime )
283{ 283{
284 int32_t iParent = -1; 284 int32_t iParent = -1;
285 int32_t iNode; 285 int32_t iNode;
286 286
287 iNode = lookupInode( sPath, iParent ); 287 iNode = lookupInode( sPath, iParent );
288 288
289 setTimes( iNode, iATime, iMTime ); 289 setTimes( iNode, iATime, iMTime );
290} 290}
291 291
292void Bu::MyriadFs::unlink( const Bu::String &sPath ) 292void Bu::MyriadFs::unlink( const Bu::String &sPath )
293{ 293{
294 int32_t iParent = -1; 294 int32_t iParent = -1;
295// int32_t iNode; 295// int32_t iNode;
296 296
297 /*iNode =*/ lookupInode( sPath, iParent ); 297 /*iNode =*/ lookupInode( sPath, iParent );
298 298
299 Dir lDir = readDir( iParent ); 299 Dir lDir = readDir( iParent );
300 300
301 Bu::String sName = filePart( sPath ); 301 Bu::String sName = filePart( sPath );
302 302
303 for( Dir::iterator i = lDir.begin(); i; i++ ) 303 for( Dir::iterator i = lDir.begin(); i; i++ )
304 { 304 {
305 if( sName == (*i).sName ) 305 if( sName == (*i).sName )
306 { 306 {
307 RawStat rs; 307 RawStat rs;
308 readInode( (*i).iNode, rs ); 308 readInode( (*i).iNode, rs );
309 if( (rs.uPerms&typeMask) == typeDir ) 309 if( (rs.uPerms&typeMask) == typeDir )
310 { 310 {
311 MyriadStream msDir = mStore.openStream( rs.uStreamIndex ); 311 MyriadStream msDir = mStore.openStream( rs.uStreamIndex );
312 int32_t iCount; 312 int32_t iCount;
313 msDir.read( &iCount, 4 ); 313 msDir.read( &iCount, 4 );
314 if( iCount > 0 ) 314 if( iCount > 0 )
315 { 315 {
316 throw Bu::MyriadFsException("Directory not empty."); 316 throw Bu::MyriadFsException("Directory not empty.");
317 } 317 }
318 } 318 }
319 if( --rs.iLinks == 0 ) 319 if( --rs.iLinks == 0 )
320 { 320 {
321 destroyNode( (*i).iNode ); 321 destroyNode( (*i).iNode );
322 } 322 }
323 else 323 else
324 { 324 {
325 writeInode( rs ); 325 writeInode( rs );
326 } 326 }
327 lDir.erase( i ); 327 lDir.erase( i );
328 break; 328 break;
329 } 329 }
330 } 330 }
331 331
332 Bu::MyriadStream ms = openByInode( iParent ); 332 Bu::MyriadStream ms = openByInode( iParent );
333 int32_t iNumChildren = lDir.getSize(); 333 int32_t iNumChildren = lDir.getSize();
334 ms.write( &iNumChildren, 4 ); 334 ms.write( &iNumChildren, 4 );
335 for( Dir::iterator i = lDir.begin(); i; i++ ) 335 for( Dir::iterator i = lDir.begin(); i; i++ )
336 { 336 {
337 ms.write( &(*i).iNode, 4 ); 337 ms.write( &(*i).iNode, 4 );
338 uint8_t iSize = (*i).sName.getSize(); 338 uint8_t iSize = (*i).sName.getSize();
339 ms.write( &iSize, 1 ); 339 ms.write( &iSize, 1 );
340 ms.write( (*i).sName.getStr(), iSize ); 340 ms.write( (*i).sName.getStr(), iSize );
341 } 341 }
342 ms.setSize( ms.tell() ); 342 ms.setSize( ms.tell() );
343} 343}
344 344
345void Bu::MyriadFs::setFileSize( const Bu::String &sPath, int32_t iSize ) 345void Bu::MyriadFs::setFileSize( const Bu::String &sPath, int32_t iSize )
346{ 346{
347 int32_t iParent = -1; 347 int32_t iParent = -1;
348 int32_t iNode; 348 int32_t iNode;
349 iNode = lookupInode( sPath, iParent ); 349 iNode = lookupInode( sPath, iParent );
350 MyriadStream ms = openByInode( iNode ); 350 MyriadStream ms = openByInode( iNode );
351 ms.setSize( iSize ); 351 ms.setSize( iSize );
352} 352}
353 353
354void Bu::MyriadFs::rename( const Bu::String &sFrom, const Bu::String &sTo ) 354void Bu::MyriadFs::rename( const Bu::String &sFrom, const Bu::String &sTo )
355{ 355{
356 mkHardLink( sFrom, sTo ); 356 mkHardLink( sFrom, sTo );
357 unlink( sFrom ); 357 unlink( sFrom );
358} 358}
359 359
360dev_t Bu::MyriadFs::devToSys( uint32_t uDev ) 360dev_t Bu::MyriadFs::devToSys( uint32_t uDev )
361{ 361{
362 return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF)); 362 return (((uDev&0xFFFF0000)>>8)&0xFF00) | ((uDev&0xFF));
363} 363}
364 364
365uint32_t Bu::MyriadFs::sysToDev( dev_t uDev ) 365uint32_t Bu::MyriadFs::sysToDev( dev_t uDev )
366{ 366{
367 return (((uint32_t)uDev&0xFF00)<<8) | ((uint32_t)uDev&0xFF); 367 return (((uint32_t)uDev&0xFF00)<<8) | ((uint32_t)uDev&0xFF);
368} 368}
369 369
370int32_t Bu::MyriadFs::lookupInode( const Bu::String &sPath, int32_t &iParent ) 370int32_t Bu::MyriadFs::lookupInode( const Bu::String &sPath, int32_t &iParent )
371{ 371{
372 if( sPath == "/" ) 372 if( sPath == "/" )
373 { 373 {
374 return 0; 374 return 0;
375 } 375 }
376 if( sPath[0] == '/' ) 376 if( sPath[0] == '/' )
377 { 377 {
378 // Absolute lookup 378 // Absolute lookup
379 return lookupInode( sPath.begin()+1, 0, iParent ); 379 return lookupInode( sPath.begin()+1, 0, iParent );
380 } 380 }
381 else 381 else
382 { 382 {
383 // Relative lookup 383 // Relative lookup
384 throw Bu::ExceptionBase( 384 throw Bu::ExceptionBase(
385 "Relative lookups in MyriadFs are not working yet."); 385 "Relative lookups in MyriadFs are not working yet.");
386 } 386 }
387} 387}
388 388
389int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart, 389int32_t Bu::MyriadFs::lookupInode( Bu::String::const_iterator iStart,
390 int32_t iNode, int32_t &iParent ) 390 int32_t iNode, int32_t &iParent )
391{ 391{
392 iParent = iNode; 392 iParent = iNode;
393 393
394 Bu::String::const_iterator iEnd = iStart.find('/'); 394 Bu::String::const_iterator iEnd = iStart.find('/');
395 Bu::String sTok( iStart, iEnd ); 395 Bu::String sTok( iStart, iEnd );
396 396
397// sio << "Direcotry component: " << sTok << sio.nl; 397// sio << "Direcotry component: " << sTok << sio.nl;
398 398
399 Dir lDir = readDir( iNode ); 399 Dir lDir = readDir( iNode );
400 400
401 for( Dir::iterator i = lDir.begin(); i; i++ ) 401 for( Dir::iterator i = lDir.begin(); i; i++ )
402 { 402 {
403 if( (*i).sName == sTok ) 403 if( (*i).sName == sTok )
404 { 404 {
405 // We found an item 405 // We found an item
406 if( !iEnd ) 406 if( !iEnd )
407 { 407 {
408 // It's the last one in the requested path, return it 408 // It's the last one in the requested path, return it
409 return (*i).iNode; 409 return (*i).iNode;
410 } 410 }
411 else 411 else
412 { 412 {
413 // Not the last one in our path, double check it's a dir 413 // Not the last one in our path, double check it's a dir
414 if( ((*i).uPerms&typeMask) == typeDir ) 414 if( ((*i).uPerms&typeMask) == typeDir )
415 { 415 {
416 return lookupInode( iEnd+1, (*i).iNode, iParent ); 416 return lookupInode( iEnd+1, (*i).iNode, iParent );
417 } 417 }
418 else 418 else
419 { 419 {
420 iParent = -1; 420 iParent = -1;
421 throw Bu::MyriadFsException( 421 throw Bu::MyriadFsException(
422 "Element '%s' in given path is not a directory.", 422 "Element '%s' in given path is not a directory.",
423 sTok.getStr() ); 423 sTok.getStr() );
424 } 424 }
425 } 425 }
426 } 426 }
427 } 427 }
428 428
429 if( iEnd ) 429 if( iEnd )
430 throw Bu::MyriadFsException( 1, "Path not found"); 430 throw Bu::MyriadFsException( 1, "Path not found");
431 else 431 else
432 throw Bu::MyriadFsException( 2, "Path not found"); 432 throw Bu::MyriadFsException( 2, "Path not found");
433} 433}
434 434
435void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs ) 435void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs, MyriadStream &rIs )
436{ 436{
437 rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) ); 437 rIs.setPos( hNodeIndex.get( iNode )*sizeof(RawStat) );
438 if( rIs.read( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) ) 438 if( rIs.read( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) )
439 throw Bu::MyriadFsException("Filesystem corruption detected."); 439 throw Bu::MyriadFsException("Filesystem corruption detected.");
440 if( rs.iNode != iNode ) 440 if( rs.iNode != iNode )
441 throw Bu::MyriadFsException("Filesystem corruption detected."); 441 throw Bu::MyriadFsException("Filesystem corruption detected.");
442} 442}
443 443
444void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs ) 444void Bu::MyriadFs::readInode( int32_t iNode, RawStat &rs )
445{ 445{
446 MyriadStream ms = mStore.openStream( 2 ); 446 MyriadStream ms = mStore.openStream( 2 );
447 readInode( iNode, rs, ms ); 447 readInode( iNode, rs, ms );
448} 448}
449 449
450void Bu::MyriadFs::writeInode( const RawStat &rs, 450void Bu::MyriadFs::writeInode( const RawStat &rs,
451 MyriadStream &rOs ) 451 MyriadStream &rOs )
452{ 452{
453 rOs.setSize( hNodeIndex.getSize()*sizeof(RawStat) ); 453 rOs.setSize( hNodeIndex.getSize()*sizeof(RawStat) );
454 rOs.setPos( hNodeIndex.get( rs.iNode )*sizeof(RawStat) ); 454 rOs.setPos( hNodeIndex.get( rs.iNode )*sizeof(RawStat) );
455 if( rOs.write( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) ) 455 if( rOs.write( &rs, sizeof(RawStat) ) < (int)sizeof(RawStat) )
456 throw Bu::MyriadFsException("Error writing inode to header stream."); 456 throw Bu::MyriadFsException("Error writing inode to header stream.");
457} 457}
458 458
459void Bu::MyriadFs::writeInode( const RawStat &rs ) 459void Bu::MyriadFs::writeInode( const RawStat &rs )
460{ 460{
461 MyriadStream ms = mStore.openStream( 2 ); 461 MyriadStream ms = mStore.openStream( 2 );
462 writeInode( rs, ms ); 462 writeInode( rs, ms );
463} 463}
464 464
465Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode ) 465Bu::MyriadFs::Dir Bu::MyriadFs::readDir( int32_t iNode )
466{ 466{
467 Bu::MyriadStream ms = openByInode( iNode ); 467 Bu::MyriadStream ms = openByInode( iNode );
468 int32_t iNumChildren = 0; 468 int32_t iNumChildren = 0;
469 ms.read( &iNumChildren, 4 ); 469 ms.read( &iNumChildren, 4 );
470 470
471 Bu::MyriadStream is = mStore.openStream( 2 ); 471 Bu::MyriadStream is = mStore.openStream( 2 );
472 Dir lDir; 472 Dir lDir;
473// sio << "Reading dir, " << iNumChildren << " entries:" << sio.nl; 473// sio << "Reading dir, " << iNumChildren << " entries:" << sio.nl;
474 for( int32_t j = 0; j < iNumChildren; j++ ) 474 for( int32_t j = 0; j < iNumChildren; j++ )
475 { 475 {
476 int32_t iChildNode; 476 int32_t iChildNode;
477 ms.read( &iChildNode, 4 ); 477 ms.read( &iChildNode, 4 );
478 Stat s; 478 Stat s;
479 stat( iChildNode, s, is ); 479 stat( iChildNode, s, is );
480 uint8_t uLen; 480 uint8_t uLen;
481 ms.read( &uLen, 1 ); 481 ms.read( &uLen, 1 );
482 s.sName.setSize( uLen ); 482 s.sName.setSize( uLen );
483 ms.read( s.sName.getStr(), uLen ); 483 ms.read( s.sName.getStr(), uLen );
484 lDir.append( s ); 484 lDir.append( s );
485 485
486// sio << " " << s.sName << sio.nl; 486// sio << " " << s.sName << sio.nl;
487 } 487 }
488 488
489 return lDir; 489 return lDir;
490} 490}
491 491
492Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode ) 492Bu::MyriadStream Bu::MyriadFs::openByInode( int32_t iNode )
493{ 493{
494 RawStat rs; 494 RawStat rs;
495 readInode( iNode, rs ); 495 readInode( iNode, rs );
496 switch( (rs.uPerms&typeMask) ) 496 switch( (rs.uPerms&typeMask) )
497 { 497 {
498 case typeDir: 498 case typeDir:
499 case typeSymLink: 499 case typeSymLink:
500 case typeRegFile: 500 case typeRegFile:
501 return mStore.openStream( rs.uStreamIndex ); 501 return mStore.openStream( rs.uStreamIndex );
502 502
503 default: 503 default:
504 throw Bu::MyriadFsException( 504 throw Bu::MyriadFsException(
505 "inode incorrect type for low-level openByInode."); 505 "inode incorrect type for low-level openByInode.");
506 } 506 }
507} 507}
508 508
509void Bu::MyriadFs::addToDir( int32_t iDir, int32_t iNode, 509void Bu::MyriadFs::addToDir( int32_t iDir, int32_t iNode,
510 const Bu::String &sName ) 510 const Bu::String &sName )
511{ 511{
512 if( sName.getSize() > 255 ) 512 if( sName.getSize() > 255 )
513 { 513 {
514 throw Bu::MyriadFsException("Filename too long, max is 255 bytes."); 514 throw Bu::MyriadFsException("Filename too long, max is 255 bytes.");
515 } 515 }
516 Bu::MyriadStream ms = openByInode( iDir ); 516 Bu::MyriadStream ms = openByInode( iDir );
517 int32_t iNumChildren = 0; 517 int32_t iNumChildren = 0;
518 ms.read( &iNumChildren, 4 ); 518 ms.read( &iNumChildren, 4 );
519 iNumChildren++; 519 iNumChildren++;
520 ms.setPos( 0 ); 520 ms.setPos( 0 );
521 ms.write( &iNumChildren, 4 ); 521 ms.write( &iNumChildren, 4 );
522 ms.setPosEnd( 0 ); 522 ms.setPosEnd( 0 );
523 ms.write( &iNode, 4 ); 523 ms.write( &iNode, 4 );
524 uint8_t uLen = sName.getSize(); 524 uint8_t uLen = sName.getSize();
525 ms.write( &uLen, 1 ); 525 ms.write( &uLen, 1 );
526 ms.write( sName.getStr(), uLen ); 526 ms.write( sName.getStr(), uLen );
527} 527}
528 528
529int32_t Bu::MyriadFs::create( int32_t iParent, const Bu::String &sName, 529int32_t Bu::MyriadFs::create( int32_t iParent, const Bu::String &sName,
530 uint16_t uPerms, uint32_t uSpecial ) 530 uint16_t uPerms, uint32_t uSpecial )
531{ 531{
532 int32_t iNode = allocInode( uPerms, uSpecial ); 532 int32_t iNode = allocInode( uPerms, uSpecial );
533 addToDir( iParent, iNode, sName ); 533 addToDir( iParent, iNode, sName );
534 return iNode; 534 return iNode;
535} 535}
536 536
537int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial ) 537int32_t Bu::MyriadFs::allocInode( uint16_t uPerms, uint32_t uSpecial )
538{ 538{
539 int32_t iNode = 0; 539 int32_t iNode = 0;
540 for(; iNode < 0xfffffff; iNode++ ) 540 for(; iNode < 0xfffffff; iNode++ )
541 { 541 {
542 if( !hNodeIndex.has( iNode ) ) 542 if( !hNodeIndex.has( iNode ) )
543 { 543 {
544 hNodeIndex.insert( iNode, hNodeIndex.getSize() ); 544 hNodeIndex.insert( iNode, hNodeIndex.getSize() );
545 RawStat rs; 545 RawStat rs;
546 rs.iNode = iNode; 546 rs.iNode = iNode;
547 rs.iUser = iUser; 547 rs.iUser = iUser;
548 rs.iGroup = iGroup; 548 rs.iGroup = iGroup;
549 rs.uPerms = uPerms; 549 rs.uPerms = uPerms;
550 rs.iLinks = 1; 550 rs.iLinks = 1;
551 switch( (uPerms&typeMask) ) 551 switch( (uPerms&typeMask) )
552 { 552 {
553 case typeRegFile: 553 case typeRegFile:
554 case typeSymLink: 554 case typeSymLink:
555 rs.uStreamIndex = mStore.createStream(); 555 rs.uStreamIndex = mStore.createStream();
556 break; 556 break;
557 557
558 case typeDir: 558 case typeDir:
559 rs.uStreamIndex = mStore.createStream(); 559 rs.uStreamIndex = mStore.createStream();
560 sio << "Creating directory node, storage: " 560 sio << "Creating directory node, storage: "
561 << rs.uStreamIndex << sio.nl; 561 << rs.uStreamIndex << sio.nl;
562 { 562 {
563 Bu::MyriadStream msDir = mStore.openStream( 563 Bu::MyriadStream msDir = mStore.openStream(
564 rs.uStreamIndex 564 rs.uStreamIndex
565 ); 565 );
566 uint32_t uSize = 0; 566 uint32_t uSize = 0;
567 msDir.write( &uSize, 4 ); 567 msDir.write( &uSize, 4 );
568 } 568 }
569 break; 569 break;
570 570
571 case typeChrDev: 571 case typeChrDev:
572 case typeBlkDev: 572 case typeBlkDev:
573 rs.uStreamIndex = uSpecial; 573 rs.uStreamIndex = uSpecial;
574 break; 574 break;
575 575
576 default: 576 default:
577 rs.uStreamIndex = 0; 577 rs.uStreamIndex = 0;
578 break; 578 break;
579 } 579 }
580 rs.iATime = time(NULL); 580 rs.iATime = time(NULL);
581 rs.iMTime = time(NULL); 581 rs.iMTime = time(NULL);
582 rs.iCTime = time(NULL); 582 rs.iCTime = time(NULL);
583 writeInode( rs ); 583 writeInode( rs );
584 584
585 return iNode; 585 return iNode;
586 } 586 }
587 } 587 }
588 588
589 throw Bu::MyriadFsException( 589 throw Bu::MyriadFsException(
590 "No inode could be allocated. You've run out!"); 590 "No inode could be allocated. You've run out!");
591} 591}
592 592
593void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs ) 593void Bu::MyriadFs::stat( int32_t iNode, Stat &rBuf, MyriadStream &rIs )
594{ 594{
595 RawStat rs; 595 RawStat rs;
596 readInode( iNode, rs, rIs ); 596 readInode( iNode, rs, rIs );
597 rBuf.iNode = iNode; 597 rBuf.iNode = iNode;
598 rBuf.iUser = rs.iUser; 598 rBuf.iUser = rs.iUser;
599 rBuf.iGroup = rs.iGroup; 599 rBuf.iGroup = rs.iGroup;
600 rBuf.uPerms = rs.uPerms; 600 rBuf.uPerms = rs.uPerms;
601 rBuf.iLinks = rs.iLinks; 601 rBuf.iLinks = rs.iLinks;
602 rBuf.iATime = rs.iATime; 602 rBuf.iATime = rs.iATime;
603 rBuf.iMTime = rs.iMTime; 603 rBuf.iMTime = rs.iMTime;
604 rBuf.iCTime = rs.iCTime; 604 rBuf.iCTime = rs.iCTime;
605 rBuf.uDev = 0; 605 rBuf.uDev = 0;
606 rBuf.iSize = 0; 606 rBuf.iSize = 0;
607 switch( (rBuf.uPerms&typeMask) ) 607 switch( (rBuf.uPerms&typeMask) )
608 { 608 {
609 case typeRegFile: 609 case typeRegFile:
610 case typeSymLink: 610 case typeSymLink:
611 rBuf.iSize = mStore.getStreamSize( rs.uStreamIndex ); 611 rBuf.iSize = mStore.getStreamSize( rs.uStreamIndex );
612 break; 612 break;
613 613
614 case typeChrDev: 614 case typeChrDev:
615 case typeBlkDev: 615 case typeBlkDev:
616 rBuf.uDev = rs.uStreamIndex; 616 rBuf.uDev = rs.uStreamIndex;
617 break; 617 break;
618 618
619 default: 619 default:
620 rBuf.iSize = 0; 620 rBuf.iSize = 0;
621 break; 621 break;
622 } 622 }
623} 623}
624 624
625void Bu::MyriadFs::writeHeader() 625void Bu::MyriadFs::writeHeader()
626{ 626{
627 Bu::MyriadStream ms = mStore.openStream( 1 ); 627 Bu::MyriadStream ms = mStore.openStream( 1 );
628 ms.write( Myriad_Fs_MAGIC_CODE, 4 ); 628 ms.write( Myriad_Fs_MAGIC_CODE, 4 );
629 int8_t iVer = 1; 629 int8_t iVer = 1;
630 int32_t iNumNodes = hNodeIndex.getSize(); 630 int32_t iNumNodes = hNodeIndex.getSize();
631 ms.write( &iVer, 1 ); 631 ms.write( &iVer, 1 );
632 ms.write( &iNumNodes, 4 ); // iNumNodes 632 ms.write( &iNumNodes, 4 ); // iNumNodes
633 for( NodeIndex::iterator i = hNodeIndex.begin(); i; i++ ) 633 for( NodeIndex::iterator i = hNodeIndex.begin(); i; i++ )
634 { 634 {
635 int32_t iNode = i.getKey(); 635 int32_t iNode = i.getKey();
636 int32_t iPosition = i.getValue(); 636 int32_t iPosition = i.getValue();
637 ms.write( &iNode, 4 ); 637 ms.write( &iNode, 4 );
638 ms.write( &iPosition, 4 ); 638 ms.write( &iPosition, 4 );
639 } 639 }
640 640
641 // Truncate the stream afterwards so we don't use up too much space. 641 // Truncate the stream afterwards so we don't use up too much space.
642 ms.setSize( ms.tell() ); 642 ms.setSize( ms.tell() );
643} 643}
644 644
645void Bu::MyriadFs::setTimes( int32_t iNode, int64_t iATime, int64_t iMTime ) 645void Bu::MyriadFs::setTimes( int32_t iNode, int64_t iATime, int64_t iMTime )
646{ 646{
647 RawStat rs; 647 RawStat rs;
648 Bu::MyriadStream is = mStore.openStream( 2 ); 648 Bu::MyriadStream is = mStore.openStream( 2 );
649 649
650 readInode( iNode, rs, is ); 650 readInode( iNode, rs, is );
651 rs.iATime = iATime; 651 rs.iATime = iATime;
652 rs.iMTime = iMTime; 652 rs.iMTime = iMTime;
653 writeInode( rs, is ); 653 writeInode( rs, is );
654} 654}
655 655
656void Bu::MyriadFs::destroyNode( int32_t iNode ) 656void Bu::MyriadFs::destroyNode( int32_t iNode )
657{ 657{
658 if( iNode == 0 ) 658 if( iNode == 0 )
659 throw Bu::MyriadFsException("You cannot destroy the root."); 659 throw Bu::MyriadFsException("You cannot destroy the root.");
660 660
661 Bu::MyriadStream is = mStore.openStream( 2 ); 661 Bu::MyriadStream is = mStore.openStream( 2 );
662 662
663 // This will be overwritten with the last node 663 // This will be overwritten with the last node
664 uint32_t iPosition = hNodeIndex.get( iNode ); 664 uint32_t iPosition = hNodeIndex.get( iNode );
665 RawStat rsOld; 665 RawStat rsOld;
666 readInode( iNode, rsOld, is ); 666 readInode( iNode, rsOld, is );
667 switch( (rsOld.uPerms&typeMask) ) 667 switch( (rsOld.uPerms&typeMask) )
668 { 668 {
669 case typeRegFile: 669 case typeRegFile:
670 case typeDir: 670 case typeDir:
671 case typeSymLink: 671 case typeSymLink:
672 mStore.deleteStream( rsOld.uStreamIndex ); 672 mStore.deleteStream( rsOld.uStreamIndex );
673 break; 673 break;
674 } 674 }
675 675
676 hNodeIndex.erase( iNode ); 676 hNodeIndex.erase( iNode );
677 677
678 // Read the last node, can't use the helpers, because we don't know the 678 // Read the last node, can't use the helpers, because we don't know the
679 // iNode yet. 679 // iNode yet.
680 if( iPosition != hNodeIndex.getSize() ) 680 if( iPosition != hNodeIndex.getSize() )
681 { 681 {
682 // If this is the last node, then we don't need to do anything, but 682 // If this is the last node, then we don't need to do anything, but
683 // this case handles what to do if we aren't on the last node 683 // this case handles what to do if we aren't on the last node
684 RawStat rs; 684 RawStat rs;
685 is.setPos( (hNodeIndex.getSize())*sizeof(RawStat) ); 685 is.setPos( (hNodeIndex.getSize())*sizeof(RawStat) );
686 is.read( &rs, sizeof(RawStat) ); 686 is.read( &rs, sizeof(RawStat) );
687 687
688 hNodeIndex.get( rs.iNode ) = iPosition; 688 hNodeIndex.get( rs.iNode ) = iPosition;
689 writeInode( rs, is ); 689 writeInode( rs, is );
690 } 690 }
691 691
692 is.setSize( hNodeIndex.getSize() * sizeof(RawStat) ); 692 is.setSize( hNodeIndex.getSize() * sizeof(RawStat) );
693} 693}
694 694
695Bu::String Bu::MyriadFs::filePart( const Bu::String &sPath ) 695Bu::String Bu::MyriadFs::filePart( const Bu::String &sPath )
696{ 696{
697 Bu::String::const_iterator iStart = sPath.begin(); 697 Bu::String::const_iterator iStart = sPath.begin();
698 if( *iStart == '/' ) 698 if( *iStart == '/' )
699 iStart++; 699 iStart++;
700 for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd; 700 for( Bu::String::const_iterator iEnd = iStart.find('/'); iEnd;
701 iStart = iEnd+1, iEnd = iStart.find('/') ) { } 701 iStart = iEnd+1, iEnd = iStart.find('/') ) { }
702 return Bu::String( iStart, sPath.end() ); 702 return Bu::String( iStart, sPath.end() );
703} 703}
704 704