From 01402052f656e954be1deb4b17a1c7709ce57359 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Mon, 5 May 2014 21:36:40 +0200 Subject: [PATCH] Add tcgetblob(2) and tcsetblob(2). --- kernel/descriptor.cpp | 18 ++++++++ kernel/fs/user.cpp | 53 +++++++++++++++++++++++ kernel/include/sortix/kernel/descriptor.h | 2 + kernel/include/sortix/kernel/inode.h | 4 ++ kernel/include/sortix/kernel/vnode.h | 2 + kernel/include/sortix/syscallnum.h | 4 +- kernel/inode.cpp | 10 +++++ kernel/io.cpp | 34 +++++++++++++++ kernel/logterminal.cpp | 25 +++++++++++ kernel/logterminal.h | 3 ++ kernel/vnode.cpp | 10 +++++ libc/Makefile | 2 + libc/include/fsmarshall-msg.h | 33 +++++++++++++- libc/include/termios.h | 11 ++++- libc/termios/tcgetblob.cpp | 34 +++++++++++++++ libc/termios/tcsetblob.cpp | 34 +++++++++++++++ 16 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 libc/termios/tcgetblob.cpp create mode 100644 libc/termios/tcsetblob.cpp diff --git a/kernel/descriptor.cpp b/kernel/descriptor.cpp index 19fd6ec6..3a2c0dd0 100644 --- a/kernel/descriptor.cpp +++ b/kernel/descriptor.cpp @@ -640,4 +640,22 @@ int Descriptor::setsockopt(ioctx_t* ctx, int level, int option_name, return vnode->setsockopt(ctx, level, option_name, option_value, option_size); } +ssize_t Descriptor::tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count) +{ + if ( name && !name[0] ) + name = NULL; + if ( (size_t) SSIZE_MAX < count ) + count = (size_t) SSIZE_MAX; + return vnode->tcgetblob(ctx, name, buffer, count); +} + +ssize_t Descriptor::tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count) +{ + if ( name && !name[0] ) + name = NULL; + if ( (size_t) SSIZE_MAX < count ) + return errno = EFBIG, -1; + return vnode->tcsetblob(ctx, name, buffer, count); +} + } // namespace Sortix diff --git a/kernel/fs/user.cpp b/kernel/fs/user.cpp index b9ff82cc..bbd00c98 100644 --- a/kernel/fs/user.cpp +++ b/kernel/fs/user.cpp @@ -236,6 +236,8 @@ public: void* option_value, size_t* option_size_ptr); virtual int setsockopt(ioctx_t* ctx, int level, int option_name, const void* option_value, size_t option_size); + virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count); + virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count); private: bool SendMessage(Channel* channel, size_t type, void* ptr, size_t size, @@ -1348,6 +1350,57 @@ int Unode::setsockopt(ioctx_t* ctx, int level, int option_name, return ret; } +ssize_t Unode::tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count) +{ + Channel* channel = server->Connect(); + if ( !channel ) + return -1; + if ( !buffer ) + count = SSIZE_MAX; + ssize_t ret = -1; + size_t namelen = name ? strlen(name) : 0; + struct fsm_req_tcgetblob msg; + struct fsm_resp_tcgetblob resp; + msg.ino = ino; + msg.namelen = namelen; + if ( SendMessage(channel, FSM_REQ_TCGETBLOB, &msg, sizeof(msg), namelen) && + channel->KernelSend(&kctx, name, namelen) && + RecvMessage(channel, FSM_RESP_TCGETBLOB, &resp, sizeof(resp)) ) + { + if ( resp.count < count ) + count = resp.count; + if ( count < resp.count ) + errno = ERANGE; + else if ( !buffer || channel->KernelRecv(ctx, buffer, count) ) + ret = (ssize_t) count; + } + channel->KernelClose(); + return ret; +} + +ssize_t Unode::tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count) +{ + Channel* channel = server->Connect(); + if ( !channel ) + return -1; + ssize_t ret = -1; + size_t namelen = name ? strlen(name) : 0; + if ( SIZE_MAX - count < namelen ) + return errno = EOVERFLOW, -1; + struct fsm_req_tcsetblob msg; + struct fsm_resp_tcsetblob resp; + msg.ino = ino; + msg.namelen = namelen; + msg.count = count; + if ( SendMessage(channel, FSM_REQ_TCSETBLOB, &msg, sizeof(msg), namelen + count) && + channel->KernelSend(&kctx, name, namelen) && + channel->KernelSend(ctx, buffer, count) && + RecvMessage(channel, FSM_RESP_TCSETBLOB, &resp, sizeof(resp)) ) + ret = (ssize_t) resp.count; + channel->KernelClose(); + return ret; +} + // // Initialization. // diff --git a/kernel/include/sortix/kernel/descriptor.h b/kernel/include/sortix/kernel/descriptor.h index 664ff1e9..07c7c410 100644 --- a/kernel/include/sortix/kernel/descriptor.h +++ b/kernel/include/sortix/kernel/descriptor.h @@ -100,6 +100,8 @@ public: void* option_value, size_t* option_size_ptr); int setsockopt(ioctx_t* ctx, int level, int option_name, const void* option_value, size_t option_size); + ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count); + ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count); private: Ref open_elem(ioctx_t* ctx, const char* filename, int flags, diff --git a/kernel/include/sortix/kernel/inode.h b/kernel/include/sortix/kernel/inode.h index 29033d3b..7f6360b8 100644 --- a/kernel/include/sortix/kernel/inode.h +++ b/kernel/include/sortix/kernel/inode.h @@ -110,6 +110,8 @@ public: void* option_value, size_t* option_size_ptr) = 0; virtual int setsockopt(ioctx_t* ctx, int level, int option_name, const void* option_value, size_t option_size) = 0; + virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count) = 0; + virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count) = 0; }; @@ -194,6 +196,8 @@ public: void* option_value, size_t* option_size_ptr); virtual int setsockopt(ioctx_t* ctx, int level, int option_name, const void* option_value, size_t option_size); + virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count); + virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count); }; diff --git a/kernel/include/sortix/kernel/vnode.h b/kernel/include/sortix/kernel/vnode.h index af69d68d..549b39ee 100644 --- a/kernel/include/sortix/kernel/vnode.h +++ b/kernel/include/sortix/kernel/vnode.h @@ -100,6 +100,8 @@ public: void* option_value, size_t* option_size_ptr); int setsockopt(ioctx_t* ctx, int level, int option_name, const void* option_value, size_t option_size); + ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count); + ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count); public /*TODO: private*/: Ref inode; diff --git a/kernel/include/sortix/syscallnum.h b/kernel/include/sortix/syscallnum.h index a77069dd..e704d860 100644 --- a/kernel/include/sortix/syscallnum.h +++ b/kernel/include/sortix/syscallnum.h @@ -167,6 +167,8 @@ #define SYSCALL_RECVMSG 139 #define SYSCALL_GETSOCKOPT 140 #define SYSCALL_SETSOCKOPT 141 -#define SYSCALL_MAX_NUM 142 /* index of highest constant + 1 */ +#define SYSCALL_TCGETBLOB 142 +#define SYSCALL_TCSETBLOB 143 +#define SYSCALL_MAX_NUM 144 /* index of highest constant + 1 */ #endif diff --git a/kernel/inode.cpp b/kernel/inode.cpp index 8eee915b..17852eea 100644 --- a/kernel/inode.cpp +++ b/kernel/inode.cpp @@ -396,4 +396,14 @@ int AbstractInode::setsockopt(ioctx_t* /*ctx*/, int /*level*/, int /*option_name return errno = ENOTSOCK, -1; } +ssize_t AbstractInode::tcgetblob(ioctx_t* /*ctx*/, const char* /*name*/, void* /*buffer*/, size_t /*count*/) +{ + return errno = ENOTTY, -1; +} + +ssize_t AbstractInode::tcsetblob(ioctx_t* /*ctx*/, const char* /*name*/, const void* /*buffer*/, size_t /*count*/) +{ + return errno = ENOTTY, -1; +} + } // namespace Sortix diff --git a/kernel/io.cpp b/kernel/io.cpp index 952974d7..27cdeeb5 100644 --- a/kernel/io.cpp +++ b/kernel/io.cpp @@ -1032,6 +1032,38 @@ static int sys_setsockopt(int fd, int level, int option_name, return desc->setsockopt(&ctx, level, option_name, option_value, option_size); } +static ssize_t sys_tcgetblob(int fd, const char* name, void* buffer, size_t count) +{ + Ref desc = CurrentProcess()->GetDescriptor(fd); + if ( !desc ) + return -1; + + char* name_copy = NULL; + if ( name && !(name_copy = GetStringFromUser(name)) ) + return -1; + + ioctx_t ctx; SetupUserIOCtx(&ctx); + ssize_t result = desc->tcgetblob(&ctx, name_copy, buffer, count); + delete[] name_copy; + return result; +} + +static ssize_t sys_tcsetblob(int fd, const char* name, const void* buffer, size_t count) +{ + Ref desc = CurrentProcess()->GetDescriptor(fd); + if ( !desc ) + return -1; + + char* name_copy = NULL; + if ( name && !(name_copy = GetStringFromUser(name)) ) + return -1; + + ioctx_t ctx; SetupUserIOCtx(&ctx); + ssize_t result = desc->tcsetblob(&ctx, name_copy, buffer, count); + delete[] name_copy; + return result; +} + void Init() { Syscall::Register(SYSCALL_ACCEPT4, (void*) sys_accept4); @@ -1084,9 +1116,11 @@ void Init() Syscall::Register(SYSCALL_SETSOCKOPT, (void*) sys_setsockopt); Syscall::Register(SYSCALL_SETTERMMODE, (void*) sys_settermmode); Syscall::Register(SYSCALL_SYMLINKAT, (void*) sys_symlinkat); + Syscall::Register(SYSCALL_TCGETBLOB, (void*) sys_tcgetblob); Syscall::Register(SYSCALL_TCGETPGRP, (void*) sys_tcgetpgrp); Syscall::Register(SYSCALL_TCGETWINCURPOS, (void*) sys_tcgetwincurpos); Syscall::Register(SYSCALL_TCGETWINSIZE, (void*) sys_tcgetwinsize); + Syscall::Register(SYSCALL_TCSETBLOB, (void*) sys_tcsetblob); Syscall::Register(SYSCALL_TCSETPGRP, (void*) sys_tcsetpgrp); Syscall::Register(SYSCALL_TRUNCATEAT, (void*) sys_truncateat); Syscall::Register(SYSCALL_UNLINKAT, (void*) sys_unlinkat); diff --git a/kernel/logterminal.cpp b/kernel/logterminal.cpp index 7ca70022..f3ac5781 100644 --- a/kernel/logterminal.cpp +++ b/kernel/logterminal.cpp @@ -444,4 +444,29 @@ int LogTerminal::poll(ioctx_t* /*ctx*/, PollNode* node) return errno = EAGAIN, -1; } +ssize_t LogTerminal::tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count) +{ + if ( !name ) + { + char index[] = ""; + if ( buffer && count < sizeof(index) ) + return errno = ERANGE, -1; + if ( buffer && !ctx->copy_to_dest(buffer, &index, sizeof(index)) ) + return -1; + return (ssize_t) sizeof(index); + } + else + return errno = ENOENT, -1; +} + +ssize_t LogTerminal::tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count) +{ + (void) ctx; + (void) buffer; + (void) count; + if ( !name ) + return errno = EPERM, -1; + else + return errno = ENOENT, -1; +} } // namespace Sortix diff --git a/kernel/logterminal.h b/kernel/logterminal.h index 9afb0236..9355e3ab 100644 --- a/kernel/logterminal.h +++ b/kernel/logterminal.h @@ -51,6 +51,9 @@ public: virtual int settermmode(ioctx_t* ctx, unsigned termmode); virtual int gettermmode(ioctx_t* ctx, unsigned* termmode); virtual int poll(ioctx_t* ctx, PollNode* node); + virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count); + virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count); + public: virtual void OnKeystroke(Keyboard* keyboard, void* user); diff --git a/kernel/vnode.cpp b/kernel/vnode.cpp index 659d8039..e3624552 100644 --- a/kernel/vnode.cpp +++ b/kernel/vnode.cpp @@ -306,4 +306,14 @@ int Vnode::setsockopt(ioctx_t* ctx, int level, int option_name, return inode->setsockopt(ctx, level, option_name, option_value, option_size); } +ssize_t Vnode::tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count) +{ + return inode->tcgetblob(ctx, name, buffer, count); +} + +ssize_t Vnode::tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count) +{ + return inode->tcsetblob(ctx, name, buffer, count); +} + } // namespace Sortix diff --git a/libc/Makefile b/libc/Makefile index 85a17d71..bafd43f8 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -511,8 +511,10 @@ sys/uio/writev.o \ sys/utsname/uname.o \ sys/wait/wait.o \ sys/wait/waitpid.o \ +termios/tcgetblob.o \ termios/tcgetwincurpos.o \ termios/tcgetwinsize.o \ +termios/tcsetblob.o \ time/clock_getres.o \ time/clock_gettime.o \ time/clock_gettimeres.o \ diff --git a/libc/include/fsmarshall-msg.h b/libc/include/fsmarshall-msg.h index 158a073f..b53426e6 100644 --- a/libc/include/fsmarshall-msg.h +++ b/libc/include/fsmarshall-msg.h @@ -394,7 +394,38 @@ struct fsm_resp_getsockopt /*uint8_t option[option_size];*/ }; -#define FSM_MSG_NUM 49 +#define FSM_REQ_TCGETBLOB 49 +struct fsm_req_tcgetblob +{ + ino_t ino; + size_t namelen; + /*char name[namelen];*/ +}; + +#define FSM_RESP_TCGETBLOB 50 +struct fsm_resp_tcgetblob +{ + size_t count; + /*uint8_t data[count];*/ +}; + +#define FSM_REQ_TCSETBLOB 51 +struct fsm_req_tcsetblob +{ + ino_t ino; + size_t namelen; + size_t count; + /*char name[namelen];*/ + /*uint8_t data[count];*/ +}; + +#define FSM_RESP_TCSETBLOB 52 +struct fsm_resp_tcsetblob +{ + size_t count; +}; + +#define FSM_MSG_NUM 53 #if defined(__cplusplus) } /* extern "C" */ diff --git a/libc/include/termios.h b/libc/include/termios.h index 6799cd07..e6019b54 100644 --- a/libc/include/termios.h +++ b/libc/include/termios.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. This file is part of the Sortix C Library. @@ -29,12 +29,21 @@ #include +#include + #include #include __BEGIN_DECLS +#ifndef __ssize_t_defined +#define __ssize_t_defined +typedef __ssize_t ssize_t; +#endif + +ssize_t tcgetblob(int fd, const char* name, void* buffer, size_t count); +ssize_t tcsetblob(int fd, const char* name, const void* buffer, size_t count); int tcgetwincurpos(int fd, struct wincurpos* wcp); int tcgetwinsize(int fd, struct winsize* ws); diff --git a/libc/termios/tcgetblob.cpp b/libc/termios/tcgetblob.cpp new file mode 100644 index 00000000..83fd8cc2 --- /dev/null +++ b/libc/termios/tcgetblob.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2014. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + termios/tcgetblob.cpp + Download a blob from a terminal. + +*******************************************************************************/ + +#include + +#include + +DEFN_SYSCALL4(int, sys_tcgetblob, SYSCALL_TCGETBLOB, int, const char*, void*, size_t); + +extern "C" ssize_t tcgetblob(int fd, const char* name, void* buffer, size_t count) +{ + return sys_tcgetblob(fd, name, buffer, count); +} diff --git a/libc/termios/tcsetblob.cpp b/libc/termios/tcsetblob.cpp new file mode 100644 index 00000000..8faad547 --- /dev/null +++ b/libc/termios/tcsetblob.cpp @@ -0,0 +1,34 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2014. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + termios/tcsetblob.cpp + Upload a blob to a terminal. + +*******************************************************************************/ + +#include + +#include + +DEFN_SYSCALL4(int, sys_tcsetblob, SYSCALL_TCSETBLOB, int, const char*, const void*, size_t); + +extern "C" ssize_t tcsetblob(int fd, const char* name, const void* buffer, size_t count) +{ + return sys_tcsetblob(fd, name, buffer, count); +}