feat: add sfsReadlink and sfsLink to sfs
This commit is contained in:
1 parent
b92f439ebc
commit
58b615e840
1 file changed
+160
@@ -1106,3 +1106,163 @@ int32 sfsCreateSymlink(const char* path, const char* target)
|
|||||||
if (newInode < 0)
|
if (newInode < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (sfsWriteAt(newInode, 0, target, targetLen) != (int64)targetLen) {
|
||||||
|
char parentBuf[256];
|
||||||
|
char leaf[sfsNameMax];
|
||||||
|
if (splitPath(path, parentBuf, sizeof(parentBuf), leaf, sizeof(leaf))) {
|
||||||
|
int32 parentInode = sfsLookup(parentBuf);
|
||||||
|
if (parentInode >= 0)
|
||||||
|
dirRemove(parentInode, leaf, strlen(leaf));
|
||||||
|
}
|
||||||
|
freeInodeNum(newInode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return newInode;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sfsReadlink(int32 inodeNum, char* buf, uint64 cap)
|
||||||
|
{
|
||||||
|
if (!isMounted || inodeNum <= 0)
|
||||||
|
return false;
|
||||||
|
return readSymlinkTarget(inodeNum, buf, cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 sfsLink(const char* existingPath, const char* newPath)
|
||||||
|
{
|
||||||
|
if (!isMounted)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int32 target = sfsLookup(existingPath);
|
||||||
|
if (target < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
SfsInode inode;
|
||||||
|
if (!readInode(target, &inode))
|
||||||
|
return -1;
|
||||||
|
if (inode.type == sfsTypeDir)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char parentBuf[256];
|
||||||
|
char leaf[sfsNameMax];
|
||||||
|
if (!splitPath(newPath, parentBuf, sizeof(parentBuf), leaf, sizeof(leaf)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int32 parentInode = sfsLookup(parentBuf);
|
||||||
|
if (parentInode < 0 || sfsTypeOf(parentInode) != sfsTypeDir)
|
||||||
|
return -1;
|
||||||
|
/* Same parent-directory write check as createNode/sfsRemove above --
|
||||||
|
adding a new hardlink NAME needs write permission on the PARENT of
|
||||||
|
the new name, not on the existing target being linked to. */
|
||||||
|
if (!vfsPermitted(sfsModeOf(parentInode), sfsUidOf(parentInode), sfsGidOf(parentInode),
|
||||||
|
currentThreadUid(), currentThreadGid(), fsModeOwnerWrite))
|
||||||
|
return -1;
|
||||||
|
if (dirFind(parentInode, leaf, strlen(leaf)) >= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
inode.linkCount++;
|
||||||
|
inode.ctime = (uint32)rtcNow();
|
||||||
|
if (!writeInodeRaw(target, &inode))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!dirAdd(parentInode, leaf, strlen(leaf), target, inode.type)) {
|
||||||
|
inode.linkCount--;
|
||||||
|
writeInodeRaw(target, &inode);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 sfsLinkCountOf(int32 inodeNum)
|
||||||
|
{
|
||||||
|
if (!isMounted || inodeNum <= 0)
|
||||||
|
return 0;
|
||||||
|
SfsInode inode;
|
||||||
|
if (!readInode(inodeNum, &inode))
|
||||||
|
return 0;
|
||||||
|
return inode.linkCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sfsRemove(const char* path)
|
||||||
|
{
|
||||||
|
if (!isMounted)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char parentBuf[256];
|
||||||
|
char leaf[sfsNameMax];
|
||||||
|
if (!splitPath(path, parentBuf, sizeof(parentBuf), leaf, sizeof(leaf)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int32 parentInode = sfsLookup(parentBuf);
|
||||||
|
if (parentInode < 0)
|
||||||
|
return false;
|
||||||
|
/* Same parent-directory write check as createNode above -- removing an
|
||||||
|
entry needs write permission on the PARENT, not the entry itself,
|
||||||
|
mirroring vfs.c's vfsUnlink/vfsRmdir's own equivalent tmpfs check. */
|
||||||
|
if (!vfsPermitted(sfsModeOf(parentInode), sfsUidOf(parentInode), sfsGidOf(parentInode),
|
||||||
|
currentThreadUid(), currentThreadGid(), fsModeOwnerWrite))
|
||||||
|
return false;
|
||||||
|
int32 target = dirFind(parentInode, leaf, strlen(leaf));
|
||||||
|
if (target < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SfsInode inode;
|
||||||
|
if (!readInode(target, &inode))
|
||||||
|
return false;
|
||||||
|
if (inode.type == sfsTypeDir && inode.size > 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!dirRemove(parentInode, leaf, strlen(leaf)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (inode.linkCount > 1) {
|
||||||
|
inode.linkCount--;
|
||||||
|
inode.ctime = (uint32)rtcNow();
|
||||||
|
return writeInodeRaw(target, &inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sfsTruncateInode(&inode, target, 0))
|
||||||
|
return false;
|
||||||
|
freeInodeNum(target);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 sfsSizeOf(int32 inodeNum)
|
||||||
|
{
|
||||||
|
if (!isMounted || inodeNum <= 0)
|
||||||
|
return 0;
|
||||||
|
SfsInode inode;
|
||||||
|
if (!readInode(inodeNum, &inode))
|
||||||
|
return 0;
|
||||||
|
return inode.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 sfsTypeOf(int32 inodeNum)
|
||||||
|
{
|
||||||
|
if (!isMounted || inodeNum <= 0)
|
||||||
|
return sfsTypeFree;
|
||||||
|
SfsInode inode;
|
||||||
|
if (!readInode(inodeNum, &inode))
|
||||||
|
return sfsTypeFree;
|
||||||
|
return inode.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 sfsMtimeOf(int32 inodeNum)
|
||||||
|
{
|
||||||
|
if (!isMounted || inodeNum <= 0)
|
||||||
|
return 0;
|
||||||
|
SfsInode inode;
|
||||||
|
if (!readInode(inodeNum, &inode))
|
||||||
|
return 0;
|
||||||
|
return inode.mtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 sfsCtimeOf(int32 inodeNum)
|
||||||
|
{
|
||||||
|
if (!isMounted || inodeNum <= 0)
|
||||||
|
return 0;
|
||||||
|
SfsInode inode;
|
||||||
|
if (!readInode(inodeNum, &inode))
|
||||||
|
return 0;
|
||||||
|
return inode.ctime;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user