aboutsummaryrefslogtreecommitdiff
path: root/src/myriadfs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/myriadfs.cpp')
-rw-r--r--src/myriadfs.cpp292
1 files changed, 281 insertions, 11 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"
16using Bu::sio;
17using Bu::Fmt;
13 18
14namespace Bu { subExceptionDef( MyriadFsException ) } 19namespace Bu { subExceptionDef( MyriadFsException ) }
15 20
@@ -17,8 +22,15 @@ namespace Bu { subExceptionDef( MyriadFsException ) }
17 22
18Bu::MyriadFs::MyriadFs( Bu::Stream &rStore, int iBlockSize ) : 23Bu::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
82Bu::MyriadFs::~MyriadFs() 99Bu::MyriadFs::~MyriadFs()
83{ 100{
101 writeHeader();
102}
103
104void 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
112Bu::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
146int32_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
161int32_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
204Bu::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
227Bu::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
247int32_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
262int32_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
308void 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
336void 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