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--;
|
||||
}
|
||||
|
||||
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