diff --git a/src/sfs.c b/src/sfs.c index a003d7e..6c5d6f2 100644 --- a/src/sfs.c +++ b/src/sfs.c @@ -1266,3 +1266,161 @@ uint64 sfsCtimeOf(int32 inodeNum) return inode.ctime; } +uint32 sfsModeOf(int32 inodeNum) +{ + if (!isMounted || inodeNum <= 0) + return 0; + SfsInode inode; + if (!readInode(inodeNum, &inode)) + return 0; + return inode.mode; +} + +bool sfsChmod(int32 inodeNum, uint32 mode) +{ + if (!isMounted || inodeNum <= 0) + return false; + SfsInode inode; + if (!readInode(inodeNum, &inode)) + return false; + inode.mode = mode; + inode.ctime = (uint32)rtcNow(); + return writeInodeRaw(inodeNum, &inode); +} + +uint32 sfsUidOf(int32 inodeNum) +{ + if (!isMounted || inodeNum <= 0) + return 0; + SfsInode inode; + if (!readInode(inodeNum, &inode)) + return 0; + return inode.uid; +} + +bool sfsChown(int32 inodeNum, uint32 newUid) +{ + if (!isMounted || inodeNum <= 0) + return false; + SfsInode inode; + if (!readInode(inodeNum, &inode)) + return false; + inode.uid = newUid; + inode.ctime = (uint32)rtcNow(); + return writeInodeRaw(inodeNum, &inode); +} + +uint32 sfsGidOf(int32 inodeNum) +{ + if (!isMounted || inodeNum <= 0) + return 0; + SfsInode inode; + if (!readInode(inodeNum, &inode)) + return 0; + return inode.gid; +} + +bool sfsChgrp(int32 inodeNum, uint32 newGid) +{ + if (!isMounted || inodeNum <= 0) + return false; + SfsInode inode; + if (!readInode(inodeNum, &inode)) + return false; + inode.gid = newGid; + inode.ctime = (uint32)rtcNow(); + return writeInodeRaw(inodeNum, &inode); +} + +bool sfsTruncate(int32 inodeNum, uint64 newSize) +{ + if (!isMounted || inodeNum <= 0 || newSize > 0xFFFFFFFFu) + return false; + SfsInode inode; + if (!readInode(inodeNum, &inode)) + return false; + if (inode.type != sfsTypeFile) + return false; + return sfsTruncateInode(&inode, inodeNum, (uint32)newSize); +} + +int64 sfsReadAt(int32 inodeNum, uint64 offset, void* buffer, uint64 length) +{ + if (!isMounted || inodeNum <= 0) + return -1; + SfsInode inode; + if (!readInode(inodeNum, &inode)) + return -1; + if (inode.type != sfsTypeFile && inode.type != sfsTypeDir && inode.type != sfsTypeSymlink) + return -1; + if (offset >= inode.size) + return 0; + + uint64 want = length; + if (want > (uint64)inode.size - offset) + want = (uint64)inode.size - offset; + + uint8* dst = (uint8*)buffer; + uint64 done = 0; + while (done < want) { + uint64 pos = offset + done; + uint32 logicalBlock = (uint32)(pos / sfsBlockSize); + uint32 within = (uint32)(pos % sfsBlockSize); + uint32 chunk = sfsBlockSize - within; + if ((uint64)chunk > want - done) + chunk = (uint32)(want - done); + + uint32 blockAbs; + if (getBlockForRead(&inode, logicalBlock, &blockAbs)) { + uint8 blockBuf[sfsBlockSize]; + if (!blockRead(blockAbs, blockBuf)) + break; + memcpy(dst + done, blockBuf + within, chunk); + } else { + memset(dst + done, 0, chunk); + } + done += chunk; + } + return (int64)done; +} + +int64 sfsWriteAt(int32 inodeNum, uint64 offset, const void* buffer, uint64 length) +{ + if (!isMounted || inodeNum <= 0) + return -1; + SfsInode inode; + if (!readInode(inodeNum, &inode)) + return -1; + if (inode.type != sfsTypeFile && inode.type != sfsTypeDir && inode.type != sfsTypeSymlink) + return -1; + if (length == 0) + return 0; + + if (offset > inode.size) { + if (!sfsWriteRaw(&inode, inodeNum, inode.size, nullptr, offset - inode.size)) + return -1; + } + if (!sfsWriteRaw(&inode, inodeNum, offset, buffer, length)) + return -1; + return (int64)length; +} + +bool sfsReaddirAt(int32 dirInode, uint32 index, char* nameOut, uint32 nameCap, uint32* typeOut) +{ + if (!isMounted || sfsTypeOf(dirInode) != sfsTypeDir) + return false; + + SfsDirEntry entry; + uint64 pos = (uint64)index * sizeof(SfsDirEntry); + if (sfsReadAt(dirInode, pos, &entry, sizeof(entry)) != (int64)sizeof(entry)) + return false; + + uint64 nlen = strlen(entry.name); + if (nlen >= nameCap) + nlen = nameCap - 1; + memcpy(nameOut, entry.name, nlen); + nameOut[nlen] = 0; + if (typeOut) + *typeOut = entry.type; + return true; +}