Skip to content

Commit

Permalink
lxfs: implemented file reading
Browse files Browse the repository at this point in the history
  • Loading branch information
jewelcodes committed Sep 30, 2024
1 parent 5483202 commit b143b66
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 0 deletions.
1 change: 1 addition & 0 deletions fs/lxfs/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ int main() {
switch(msg->header.command) {
case COMMAND_MOUNT: lxfsMount((MountCommand *) msg); break;
case COMMAND_OPEN: lxfsOpen((OpenCommand *) msg); break;
case COMMAND_READ: lxfsRead((RWCommand *) msg); break;
default:
luxLogf(KPRINT_LEVEL_WARNING, "unimplemented command 0x%04X, dropping message...\n", msg->header.command);
}
Expand Down
138 changes: 138 additions & 0 deletions fs/lxfs/src/read.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* luxOS - a unix-like operating system
* Omar Elghoul, 2024
*
* lxfs: Driver for the lxfs file system
*/

#include <liblux/liblux.h>
#include <lxfs/lxfs.h>
#include <vfs.h>
#include <string.h>
#include <stdlib.h>
#include <fnctl.h>
#include <unistd.h>
#include <errno.h>

/* lxfsRead(): reads from an opened file on an lxfs volume
* params: rcmd - read command message
* returns: nothing, response relayed to vfs
*/

void lxfsRead(RWCommand *rcmd) {
rcmd->header.header.response = 1;
rcmd->header.header.length = sizeof(RWCommand);

// get the mountpoint
Mountpoint *mp = findMP(rcmd->device);
if(!mp) {
rcmd->header.header.status = -EIO;
luxSendDependency(rcmd);
return;
}

// and the file entry
LXFSDirectoryEntry entry;
if(!lxfsFind(&entry, mp, rcmd->path)) {
rcmd->header.header.status = -ENOENT;
luxSendDependency(rcmd);
return;
}

// use the file entry to read metadata as well as find the first file block
uint64_t first = lxfsReadNextBlock(mp, entry.block, mp->meta);
if(!first) {
rcmd->header.header.status = -EIO;
luxSendDependency(rcmd);
return;
}

LXFSFileHeader *metadata = (LXFSFileHeader *) mp->meta;

// input validation
if(rcmd->position >= metadata->size) {
rcmd->header.header.status = -EOVERFLOW;
luxSendDependency(rcmd);
return;
}

size_t truelen;
if((rcmd->position + rcmd->length) > metadata->size)
truelen = metadata->size - rcmd->position;
else
truelen = rcmd->length;

RWCommand *res = calloc(1, sizeof(RWCommand) + truelen);
if(!res) {
rcmd->header.header.status = -ENOMEM;
luxSendDependency(rcmd);
return;
}

// copy the header
memcpy(res, rcmd, sizeof(RWCommand));

// now calculate which block to start from and offset into the firsty block
uint64_t startBlock = rcmd->position / mp->blockSizeBytes;
uint64_t startOffset = rcmd->position % mp->blockSizeBytes;
uint64_t block = first;

// find the starting block
while(startBlock) {
block = lxfsNextBlock(mp, block);
if(!block) {
free(res);
rcmd->header.header.status = -EIO;
luxSendDependency(rcmd);
return;
}

startBlock--;
}

// and begin - we will use separate counters for this, because even though
// we have an ideal "true length" to read, we cannot guarantee that we will
// actually read that many bytes due to things like I/O errors, file system
// corruption, missing blocks, etc
size_t readCount = 0;
size_t remaining = truelen;
while(readCount < truelen) {
size_t s;

// here and ONLY here we're allowed to break out of the loop without
// throwing errors, provided we've read at least some of the file
if(block == LXFS_BLOCK_EOF) break;
block = lxfsReadNextBlock(mp, block, mp->dataBuffer);
if(!block) break;

if(!readCount) {
// special case for starting block
if(remaining >= (mp->blockSizeBytes - startOffset)) s = mp->blockSizeBytes - startOffset;
else s = remaining;

memcpy((void *)((uintptr_t)res->data + readCount), mp->dataBuffer+startOffset, s);
} else {
// for all other blocks
if(remaining > mp->blockSizeBytes) s = mp->blockSizeBytes;
else s = remaining;

memcpy((void *)((uintptr_t)res->data + readCount), mp->dataBuffer, s);
}

readCount += s;
remaining -= s;
}

// appropriately update the file descriptor position and status flags
if(readCount) {
res->position += readCount;
res->length = readCount;
res->header.header.status = readCount;
res->header.header.length += readCount;
} else {
res->header.header.status = -EIO;
}

luxSendDependency(res);
free(res);
}

0 comments on commit b143b66

Please sign in to comment.