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)
|
||||
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