feat: extend vfs with vfsPipe and vfsPipeCreateHandle
This commit is contained in:
1 parent
560d0c6aca
commit
3124635682
1 file changed
+187
@@ -903,6 +903,175 @@ int vfsClose(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfsPipe(int* readFd, int* writeFd)
|
||||
{
|
||||
int rfd = allocFd();
|
||||
if (rfd < 0)
|
||||
return -1;
|
||||
currentThread()->fds[rfd].kind = fdPipeRead;
|
||||
|
||||
int wfd = allocFd();
|
||||
if (wfd < 0) {
|
||||
currentThread()->fds[rfd].kind = fdFree;
|
||||
return -1;
|
||||
}
|
||||
currentThread()->fds[wfd].kind = fdPipeWrite;
|
||||
|
||||
int handle = pipeCreate();
|
||||
if (handle < 0) {
|
||||
currentThread()->fds[rfd].kind = fdFree;
|
||||
currentThread()->fds[wfd].kind = fdFree;
|
||||
return -1;
|
||||
}
|
||||
|
||||
currentThread()->fds[rfd].pipeHandle = handle;
|
||||
currentThread()->fds[wfd].pipeHandle = handle;
|
||||
*readFd = rfd;
|
||||
*writeFd = wfd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vfsPipeCreateHandle(void)
|
||||
{
|
||||
return pipeCreateDetached();
|
||||
}
|
||||
|
||||
int vfsPipeAttach(int handle, bool wantWrite)
|
||||
{
|
||||
if (!pipeValid(handle))
|
||||
return -1;
|
||||
|
||||
int fd = allocFd();
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
FileDescriptor* d = ¤tThread()->fds[fd];
|
||||
d->node = nullptr;
|
||||
d->offset = 0;
|
||||
d->kind = wantWrite ? fdPipeWrite : fdPipeRead;
|
||||
d->flags = fdFlagBlocking;
|
||||
d->pipeHandle = handle;
|
||||
|
||||
if (wantWrite)
|
||||
pipeAddWriter(handle);
|
||||
else
|
||||
pipeAddReader(handle);
|
||||
return fd;
|
||||
}
|
||||
|
||||
void vfsPipeAttachInto(FileDescriptor* targetFds, int fd, int handle, bool wantWrite)
|
||||
{
|
||||
if (!pipeValid(handle))
|
||||
return;
|
||||
|
||||
FileDescriptor* d = &targetFds[fd];
|
||||
d->node = nullptr;
|
||||
d->offset = 0;
|
||||
d->kind = wantWrite ? fdPipeWrite : fdPipeRead;
|
||||
d->flags = fdFlagBlocking;
|
||||
d->pipeHandle = handle;
|
||||
|
||||
if (wantWrite)
|
||||
pipeAddWriter(handle);
|
||||
else
|
||||
pipeAddReader(handle);
|
||||
}
|
||||
|
||||
int vfsPidfdOpen(uint32 targetId)
|
||||
{
|
||||
int handle = pidfdOpen(targetId);
|
||||
if (handle < 0)
|
||||
return -1;
|
||||
|
||||
int fd = allocFd();
|
||||
if (fd < 0) {
|
||||
pidfdClose(handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FileDescriptor* d = ¤tThread()->fds[fd];
|
||||
d->node = nullptr;
|
||||
d->offset = 0;
|
||||
d->kind = fdPidfd;
|
||||
d->flags = 0;
|
||||
d->pipeHandle = handle;
|
||||
return fd;
|
||||
}
|
||||
|
||||
uint32 vfsPidfdTarget(int fd)
|
||||
{
|
||||
FileDescriptor* d = fdAt(fd);
|
||||
if (!d || d->kind != fdPidfd)
|
||||
return threadInvalidId;
|
||||
return pidfdTarget(d->pipeHandle);
|
||||
}
|
||||
|
||||
const void* vfsBlockingChannel(int fd, bool forWrite)
|
||||
{
|
||||
FileDescriptor* d = fdAt(fd);
|
||||
if (!d || !(d->flags & fdFlagBlocking))
|
||||
return nullptr;
|
||||
|
||||
if (d->kind == fdPipeRead || d->kind == fdPipeWrite) {
|
||||
if (forWrite) {
|
||||
if (d->kind != fdPipeWrite || pipeWriteBroken(d->pipeHandle))
|
||||
return nullptr;
|
||||
} else if (d->kind != fdPipeRead) {
|
||||
return nullptr;
|
||||
}
|
||||
return pipeChannel(d->pipeHandle);
|
||||
}
|
||||
|
||||
if (d->kind == fdConsole) {
|
||||
/* Console writes (kputchar) are never buffered and never block. */
|
||||
if (forWrite)
|
||||
return nullptr;
|
||||
return keyboardReaderChannel(d->pipeHandle);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool vfsPollReady(int fd, int16 events, int16* outRevents)
|
||||
{
|
||||
int16 revents = 0;
|
||||
FileDescriptor* d = fdAt(fd);
|
||||
if (!d) {
|
||||
*outRevents = pollNval;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (d->kind) {
|
||||
case fdPipeRead:
|
||||
if ((events & pollIn) && pipeHasData(d->pipeHandle))
|
||||
revents |= pollIn;
|
||||
break;
|
||||
case fdPipeWrite:
|
||||
if (pipeWriteBroken(d->pipeHandle))
|
||||
revents |= pollErr;
|
||||
else if ((events & pollOut) && pipeHasSpace(d->pipeHandle))
|
||||
revents |= pollOut;
|
||||
break;
|
||||
case fdConsole:
|
||||
if ((events & pollIn) && keyboardReaderHasData(d->pipeHandle))
|
||||
revents |= pollIn;
|
||||
/* Console writes (kputchar) are never buffered and never block --
|
||||
see vfsBlockingChannel above. */
|
||||
if (events & pollOut)
|
||||
revents |= pollOut;
|
||||
break;
|
||||
default:
|
||||
/* fdFile, fdBlockDev, fdSfs: every read/write on these runs to
|
||||
completion synchronously (see vfsRead/vfsWrite below), exactly
|
||||
like a real local filesystem always reports poll-ready. */
|
||||
revents |= (int16)(events & (pollIn | pollOut));
|
||||
break;
|
||||
}
|
||||
|
||||
*outRevents = revents;
|
||||
return revents != 0;
|
||||
}
|
||||
|
||||
int64 vfsWrite(int fd, const void* buffer, uint64 length)
|
||||
{
|
||||
FileDescriptor* d = fdAt(fd);
|
||||
@@ -916,6 +1085,15 @@ int64 vfsWrite(int fd, const void* buffer, uint64 length)
|
||||
return (int64)length;
|
||||
}
|
||||
|
||||
if (d->kind == fdPipeWrite)
|
||||
return pipeWrite(d->pipeHandle, buffer, length);
|
||||
if (d->kind == fdPipeRead)
|
||||
return -1;
|
||||
if (d->kind == fdBlockDev)
|
||||
return blockDevWrite(d, buffer, length);
|
||||
if (d->kind == fdSfs)
|
||||
return sfsFdWrite(d, buffer, length);
|
||||
|
||||
VfsNode* node = d->node;
|
||||
if (node->type != fsTypeFile || !node->writable)
|
||||
return -1;
|
||||
@@ -934,6 +1112,15 @@ int64 vfsRead(int fd, void* buffer, uint64 length)
|
||||
if (!d)
|
||||
return -1;
|
||||
|
||||
if (d->kind == fdPipeRead)
|
||||
return pipeRead(d->pipeHandle, buffer, length);
|
||||
if (d->kind == fdPipeWrite)
|
||||
return -1;
|
||||
if (d->kind == fdBlockDev)
|
||||
return blockDevRead(d, buffer, length);
|
||||
if (d->kind == fdSfs)
|
||||
return sfsFdRead(d, buffer, length);
|
||||
|
||||
if (d->kind == fdConsole) {
|
||||
char* text = (char*)buffer;
|
||||
uint64 count = 0;
|
||||
|
||||
Reference in new issue
Block a user