feat: add splitPath and dirFind to sfs
This commit is contained in:
1 parent
c13e57d322
commit
39520e6183
1 file changed
+157
@@ -636,3 +636,160 @@ static bool sfsTruncateInode(SfsInode* inode, int32 inodeNum, uint32 newSize)
|
|||||||
inode->blockCount--;
|
inode->blockCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (neededBlocks <= sfsDirectBlocks + sfsPtrsPerBlock && inode->doubleIndirect != 0) {
|
||||||
|
uint8 outerBuf[sfsBlockSize];
|
||||||
|
if (blockRead(inode->doubleIndirect, outerBuf)) {
|
||||||
|
uint32* outerPtrs = (uint32*)outerBuf;
|
||||||
|
for (uint32 j = 0; j < sfsPtrsPerBlock; j++) {
|
||||||
|
if (outerPtrs[j] != 0) {
|
||||||
|
freeDataBlockAbs(outerPtrs[j]);
|
||||||
|
inode->blockCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freeDataBlockAbs(inode->doubleIndirect);
|
||||||
|
inode->doubleIndirect = 0;
|
||||||
|
inode->blockCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (neededBlocks <= sfsDirectBlocks && inode->indirect != 0) {
|
||||||
|
freeDataBlockAbs(inode->indirect);
|
||||||
|
inode->indirect = 0;
|
||||||
|
inode->blockCount--;
|
||||||
|
}
|
||||||
|
|
||||||
|
inode->size = newSize;
|
||||||
|
inode->mtime = inode->ctime = (uint32)rtcNow();
|
||||||
|
return writeInodeRaw(inodeNum, inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool splitPath(const char* path, char* parentOut, uint64 parentCap, char* leafOut, uint64 leafCap)
|
||||||
|
{
|
||||||
|
uint64 len = strlen(path);
|
||||||
|
while (len > 0 && path[len - 1] == '/')
|
||||||
|
len--;
|
||||||
|
if (len == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int64 slash = -1;
|
||||||
|
for (int64 i = (int64)len - 1; i >= 0; i--)
|
||||||
|
if (path[i] == '/') {
|
||||||
|
slash = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 leafStart, leafLen;
|
||||||
|
if (slash < 0) {
|
||||||
|
parentOut[0] = 0;
|
||||||
|
leafStart = 0;
|
||||||
|
leafLen = len;
|
||||||
|
} else {
|
||||||
|
uint64 plen = (uint64)slash;
|
||||||
|
if (plen >= parentCap)
|
||||||
|
plen = parentCap - 1;
|
||||||
|
memcpy(parentOut, path, plen);
|
||||||
|
parentOut[plen] = 0;
|
||||||
|
leafStart = (uint64)slash + 1;
|
||||||
|
leafLen = len - leafStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leafLen == 0 || leafLen >= leafCap)
|
||||||
|
return false;
|
||||||
|
memcpy(leafOut, path + leafStart, leafLen);
|
||||||
|
leafOut[leafLen] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 dirFind(int32 dirInode, const char* name, uint64 nameLen)
|
||||||
|
{
|
||||||
|
SfsDirEntry entry;
|
||||||
|
uint64 pos = 0;
|
||||||
|
for (;;) {
|
||||||
|
int64 got = sfsReadAt(dirInode, pos, &entry, sizeof(entry));
|
||||||
|
if (got != (int64)sizeof(entry))
|
||||||
|
break;
|
||||||
|
if (strlen(entry.name) == nameLen && memcmp(entry.name, name, nameLen) == 0)
|
||||||
|
return (int32)entry.inode;
|
||||||
|
pos += sizeof(entry);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool dirAdd(int32 dirInode, const char* name, uint64 nameLen, int32 childInode, uint32 type)
|
||||||
|
{
|
||||||
|
if (nameLen == 0 || nameLen >= sfsNameMax)
|
||||||
|
return false;
|
||||||
|
if (dirFind(dirInode, name, nameLen) >= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SfsDirEntry entry;
|
||||||
|
memset(&entry, 0, sizeof(entry));
|
||||||
|
entry.inode = (uint32)childInode;
|
||||||
|
entry.type = type;
|
||||||
|
memcpy(entry.name, name, nameLen);
|
||||||
|
entry.name[nameLen] = 0;
|
||||||
|
|
||||||
|
uint64 size = sfsSizeOf(dirInode);
|
||||||
|
return sfsWriteAt(dirInode, size, &entry, sizeof(entry)) == (int64)sizeof(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool dirRemove(int32 dirInode, const char* name, uint64 nameLen)
|
||||||
|
{
|
||||||
|
SfsDirEntry entry;
|
||||||
|
uint64 pos = 0;
|
||||||
|
int64 foundPos = -1;
|
||||||
|
for (;;) {
|
||||||
|
int64 got = sfsReadAt(dirInode, pos, &entry, sizeof(entry));
|
||||||
|
if (got != (int64)sizeof(entry))
|
||||||
|
break;
|
||||||
|
if (strlen(entry.name) == nameLen && memcmp(entry.name, name, nameLen) == 0) {
|
||||||
|
foundPos = (int64)pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos += sizeof(entry);
|
||||||
|
}
|
||||||
|
if (foundPos < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint64 size = sfsSizeOf(dirInode);
|
||||||
|
uint64 lastPos = size - sizeof(SfsDirEntry);
|
||||||
|
if ((uint64)foundPos != lastPos) {
|
||||||
|
SfsDirEntry last;
|
||||||
|
if (sfsReadAt(dirInode, lastPos, &last, sizeof(last)) != (int64)sizeof(last))
|
||||||
|
return false;
|
||||||
|
if (sfsWriteAt(dirInode, (uint64)foundPos, &last, sizeof(last)) != (int64)sizeof(last))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SfsInode inode;
|
||||||
|
if (!readInode(dirInode, &inode))
|
||||||
|
return false;
|
||||||
|
return sfsTruncateInode(&inode, dirInode, (uint32)lastPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32 createNode(const char* path, uint32 type)
|
||||||
|
{
|
||||||
|
if (!isMounted)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char parentBuf[256];
|
||||||
|
char leaf[sfsNameMax];
|
||||||
|
if (!splitPath(path, parentBuf, sizeof(parentBuf), leaf, sizeof(leaf)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int32 parentInode = sfsLookup(parentBuf);
|
||||||
|
if (parentInode < 0 || sfsTypeOf(parentInode) != sfsTypeDir)
|
||||||
|
return -1;
|
||||||
|
/* Real Unix directory-write semantics: creating a NEW entry needs
|
||||||
|
write permission on the PARENT directory, mirroring vfs.c's
|
||||||
|
vfsMkdir/resolveOpen create-branch's own equivalent tmpfs check. */
|
||||||
|
if (!vfsPermitted(sfsModeOf(parentInode), sfsUidOf(parentInode), sfsGidOf(parentInode),
|
||||||
|
currentThreadUid(), currentThreadGid(), fsModeOwnerWrite))
|
||||||
|
return -1;
|
||||||
|
if (dirFind(parentInode, leaf, strlen(leaf)) >= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int32 newInode = allocInodeNum();
|
||||||
|
if (newInode < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
Reference in new issue
Block a user