diff --git a/TESTFS.PAS b/TESTFS.PAS index 779c497..431a435 100755 --- a/TESTFS.PAS +++ b/TESTFS.PAS @@ -192,5 +192,5 @@ writeln('sizeof(diskSuperBlock): ',sizeof(TdiskSuperBlock)); writeln('sizeof(ubixfsInode): ',sizeof(TubixfsInode)); writeln('sizeof(dataStream): ', sizeof(TdataStream)); - writeln('sizeof(TSmallData): ', sizeof(TSmallData)); + writeln('sizeof(TSmallData): ', sizeof(TSmallDataNode)); end. \ No newline at end of file diff --git a/UBIXFS.PAS b/UBIXFS.PAS index 1798580..63cf616 100755 --- a/UBIXFS.PAS +++ b/UBIXFS.PAS @@ -207,8 +207,23 @@ blockCount : uInt32; end; // TDataStream + PSmallDataNode = ^TSmallDataNode; + TSmallDataNode = packed object + public + nameSize : uInt16; + dataSize : uInt16; + dataType : treeTypes; + reserved : array[0..2] of uInt8; + name : array[0..0] of char; + function align(size:uInt32):uInt32; + function dataPtr:pointer; + function isEmpty:boolean; + function next:PSmallDataNode; + end; // TSmallDataNode + PUbixfsInode = ^TUbixfsInode; - TUbixfsInode = packed record + TUbixfsInode = packed object + public magic : int32; inodeNum : inodeAddr; uid : uInt32; @@ -224,19 +239,11 @@ data : uPtr; {this was the etc field in bfs} blocks : TDataStream; name : array[0..255] of char; - smallData : array[0..0] of byte; + smallData : TSmallDataNode; + function addAttr(attribute:PChar; attrType:treeTypes; buffer:pointer; count:uInt32):PSmallDataNode; + function delAttr(attribute:PChar):boolean; end; // TUbixfsInode - PSmallData = ^TSmallData; - TSmallData = packed object - public - nameSize : uInt16; - dataSize : uInt16; - dataType : treeTypes; - reserved : array[0..2] of uInt8; - name : array[0..0] of char; - end; // TSmallData - PCacheNode = ^TCacheNode; TCacheNode = object public @@ -247,7 +254,7 @@ dirty : boolean; locked : boolean; constructor init(_address, _lastUsed:int64; _dataSize:uInt32); - destructor done; + destructor done; end; // TCacheNode PVNode = ^TVNode; @@ -426,7 +433,52 @@ if (key = NIL) then result := 0 else result := sizeof(TBlockRun); end; // keySizeBlockRun +// TSmallDataNode methods +function TSmallDataNode.align; result := (size+3) and not 3; // round up to nearest dword address +function TSmallDataNode.dataPtr; result := @self + align(nameSize) + (sizeof(TSmallDataNode)-sizeof(name)); +function TSmallDataNode.isEmpty; result := (nameSize = 0) and (dataSize = 0); +function TSmallDataNode.next; result := @self + align(nameSize) + align(dataSize) + (sizeof(TSmallDataNode)-sizeof(name)); +// TUbixfsInode methods +function TUbixfsInode.addAttr; +var + smallDataNode:PSmallDataNode; + attrSize:uInt32; + ptr:pointer; +begin + result := NIL; // failure by default; + if (attribute = NIL) or (buffer = NIL) or (count = 0) then exit; + smallDataNode := @smallData; + while not smallDataNode^.isEmpty() do + smallDataNode := smallDataNode^.next(); + attrSize := strlen(attribute)+1; + // double-check that there's enough room to the end of the inode + if (dword(smallDataNode - @self) + smallDataNode^.align(attrSize) + smallDataNode^.align(count) + (sizeof(TSmallDataNode)-1) > inodeSize) then exit; + // Okay, it'll fit + with smallDataNode^ do + begin + nameSize := attrSize; // include null + dataSize := count; + dataType := attrType; + fillchar(reserved, sizeof(reserved), 0); + fillchar(name, align(nameSize), 0); // better safe than sorry? + move(attribute^, name, nameSize); + fillchar(dataPtr^, align(count), 0); // better safe than sorry + move(buffer^, dataPtr^, count); + end; // with + result := smallDataNode; +end; // TUbixfsInode.addAttri + +function TUbixfsInode.delAttr; +var + smallDataNode:PSmallDataNode; +begin + result := FALSE; // failure by default + if (attribute = NIL) then exit; + +end; // TUbixfsInode.delAttr + +// TCacheNode methods constructor TCacheNode.init; begin address := _address; @@ -3315,12 +3367,42 @@ function TUbixFS.writeAttr; var inode:PUbixfsInode; + dataNode:PSmallDataNode; + attrTree:PbTree; + found, smallDataArea:boolean; + + u:uPtr; begin result := -1; if (attribute = NIL) or (buffer = NIL) then exit; if not isValidIAddr(iAddr) then exit; inode := loadBlock(iAddr); if (inode = NIL) then exit; + dataNode := @inode^.smallData; + found := FALSE; + writeln('looking for ', attribute); + smallDataArea := TRUE; + while not found and not dataNode^.isEmpty() do + if (strcomp(@dataNode^.name, attribute) = 0) then + found := TRUE + else + dataNode := dataNode^.next(); + + if not found then + begin + // we looked through the small data area and didn't find it. Check the attr dir (if there is one) + if isValidIAddr(inode^.attributes) then + begin + new(attrTree, open(iAddrToStr(inode^.attributes), new(PUbixBTreeVFS, init(@self)))); + if (attrTree = NIL) then exit; // danger will robinson! + if (attrTree^.Find(attribute, u)) then + begin + found := FALSE; + smallDataArea := FALSE; + end; + dispose(attrTree, done); + end; + end; end; // TUbixFS.readAttr function TUbixFS.writeDataStream;