kernel: add modes and offsets to file descriptors

This commit is contained in:
K. Lange 2018-10-29 20:57:17 +09:00
parent 26801b76fd
commit 886f5797fb
6 changed files with 68 additions and 29 deletions

View File

@ -89,7 +89,6 @@ typedef struct fs_node {
readlink_type_t readlink; readlink_type_t readlink;
struct fs_node *ptr; /* Alias pointer, for symlinks. */ struct fs_node *ptr; /* Alias pointer, for symlinks. */
uint32_t offset; /* Offset for read operations XXX move this to new "file descriptor" entry */
int32_t refcount; int32_t refcount;
uint32_t nlink; uint32_t nlink;

View File

@ -53,6 +53,8 @@ typedef struct image {
/* Resizable descriptor table */ /* Resizable descriptor table */
typedef struct descriptor_table { typedef struct descriptor_table {
fs_node_t ** entries; fs_node_t ** entries;
size_t * offsets;
int * modes;
size_t length; size_t length;
size_t capacity; size_t capacity;
size_t refs; size_t refs;

View File

@ -462,8 +462,8 @@ fs_node_t * pty_slave_create(pty_t * pty) {
sprintf(fnode->name, "pty slave"); sprintf(fnode->name, "pty slave");
fnode->uid = current_process->user; fnode->uid = current_process->user;
fnode->gid = 0; fnode->gid = 0;
fnode->mask = 0666; fnode->mask = 0620;
fnode->flags = FS_PIPE; fnode->flags = FS_CHARDEVICE;
fnode->read = read_pty_slave; fnode->read = read_pty_slave;
fnode->write = write_pty_slave; fnode->write = write_pty_slave;
fnode->open = open_pty_slave; fnode->open = open_pty_slave;

View File

@ -278,6 +278,8 @@ process_t * spawn_init(void) {
init->fds->length = 0; /* Initialize the file descriptors */ init->fds->length = 0; /* Initialize the file descriptors */
init->fds->capacity = 4; init->fds->capacity = 4;
init->fds->entries = malloc(sizeof(fs_node_t *) * init->fds->capacity); init->fds->entries = malloc(sizeof(fs_node_t *) * init->fds->capacity);
init->fds->modes = malloc(sizeof(int) * init->fds->capacity);
init->fds->offsets = malloc(sizeof(size_t) * init->fds->capacity);
/* Set the working directory */ /* Set the working directory */
init->wd_node = clone_fs(fs_root); init->wd_node = clone_fs(fs_root);
@ -426,10 +428,14 @@ process_t * spawn_process(volatile process_t * parent, int reuse_fds) {
proc->fds->capacity = parent->fds->capacity; proc->fds->capacity = parent->fds->capacity;
debug_print(INFO," fds / files {"); debug_print(INFO," fds / files {");
proc->fds->entries = malloc(sizeof(fs_node_t *) * proc->fds->capacity); proc->fds->entries = malloc(sizeof(fs_node_t *) * proc->fds->capacity);
proc->fds->modes = malloc(sizeof(int) * proc->fds->capacity);
proc->fds->offsets = malloc(sizeof(size_t) * proc->fds->capacity);
assert(proc->fds->entries && "Failed to allocate file descriptor table for new process."); assert(proc->fds->entries && "Failed to allocate file descriptor table for new process.");
debug_print(INFO," ---"); debug_print(INFO," ---");
for (uint32_t i = 0; i < parent->fds->length; ++i) { for (uint32_t i = 0; i < parent->fds->length; ++i) {
proc->fds->entries[i] = clone_fs(parent->fds->entries[i]); proc->fds->entries[i] = clone_fs(parent->fds->entries[i]);
proc->fds->modes[i] = parent->fds->modes[i];
proc->fds->offsets[i] = parent->fds->offsets[i];
} }
debug_print(INFO," }"); debug_print(INFO," }");
} }
@ -581,6 +587,9 @@ uint32_t process_append_fd(process_t * proc, fs_node_t * node) {
for (unsigned int i = 0; i < proc->fds->length; ++i) { for (unsigned int i = 0; i < proc->fds->length; ++i) {
if (!proc->fds->entries[i]) { if (!proc->fds->entries[i]) {
proc->fds->entries[i] = node; proc->fds->entries[i] = node;
/* modes, offsets must be set by caller */
proc->fds->modes[i] = 0;
proc->fds->offsets[i] = 0;
return i; return i;
} }
} }
@ -588,8 +597,13 @@ uint32_t process_append_fd(process_t * proc, fs_node_t * node) {
if (proc->fds->length == proc->fds->capacity) { if (proc->fds->length == proc->fds->capacity) {
proc->fds->capacity *= 2; proc->fds->capacity *= 2;
proc->fds->entries = realloc(proc->fds->entries, sizeof(fs_node_t *) * proc->fds->capacity); proc->fds->entries = realloc(proc->fds->entries, sizeof(fs_node_t *) * proc->fds->capacity);
proc->fds->modes = realloc(proc->fds->modes, sizeof(int) * proc->fds->capacity);
proc->fds->offsets = realloc(proc->fds->offsets, sizeof(size_t) * proc->fds->capacity);
} }
proc->fds->entries[proc->fds->length] = node; proc->fds->entries[proc->fds->length] = node;
/* modes, offsets must be set by caller */
proc->fds->modes[proc->fds->length] = 0;
proc->fds->offsets[proc->fds->length] = 0;
proc->fds->length++; proc->fds->length++;
return proc->fds->length-1; return proc->fds->length-1;
} }
@ -613,6 +627,8 @@ uint32_t process_move_fd(process_t * proc, int src, int dest) {
if (proc->fds->entries[dest] != proc->fds->entries[src]) { if (proc->fds->entries[dest] != proc->fds->entries[src]) {
close_fs(proc->fds->entries[dest]); close_fs(proc->fds->entries[dest]);
proc->fds->entries[dest] = proc->fds->entries[src]; proc->fds->entries[dest] = proc->fds->entries[src];
proc->fds->modes[dest] = proc->fds->modes[src];
proc->fds->offsets[dest] = proc->fds->offsets[src];
open_fs(proc->fds->entries[dest], 0); open_fs(proc->fds->entries[dest], 0);
} }
return dest; return dest;
@ -765,6 +781,8 @@ void cleanup_process(process_t * proc, int retval) {
} }
debug_print(INFO, "... and their storage %d", proc->id); debug_print(INFO, "... and their storage %d", proc->id);
free(proc->fds->entries); free(proc->fds->entries);
free(proc->fds->offsets);
free(proc->fds->modes);
free(proc->fds); free(proc->fds);
debug_print(INFO, "... and the kernel stack (hope this ain't us) %d", proc->id); debug_print(INFO, "... and the kernel stack (hope this ain't us) %d", proc->id);
free((void *)(proc->image.stack - KERNEL_STACK_SIZE)); free((void *)(proc->image.stack - KERNEL_STACK_SIZE));

View File

@ -29,6 +29,10 @@ static size_t hostname_len = 0;
(current_process->fds->entries[(FD)]) (current_process->fds->entries[(FD)])
#define FD_CHECK(FD) \ #define FD_CHECK(FD) \
(FD_INRANGE(FD) && FD_ENTRY(FD)) (FD_INRANGE(FD) && FD_ENTRY(FD))
#define FD_OFFSET(FD) \
(current_process->fds->offsets[(FD)])
#define FD_MODE(FD) \
(current_process->fds->modes[(FD)])
#define PTR_INRANGE(PTR) \ #define PTR_INRANGE(PTR) \
((uintptr_t)(PTR) > current_process->image.entry) ((uintptr_t)(PTR) > current_process->image.entry)
@ -62,8 +66,12 @@ static int sys_read(int fd, char * ptr, int len) {
PTR_VALIDATE(ptr); PTR_VALIDATE(ptr);
fs_node_t * node = FD_ENTRY(fd); fs_node_t * node = FD_ENTRY(fd);
uint32_t out = read_fs(node, node->offset, len, (uint8_t *)ptr); if (!(FD_MODE(fd) & 01)) {
node->offset += out; debug_print(WARNING, "access denied (read, fd=%d, mode=%d, %s, %s)", fd, FD_MODE(fd), node->name, current_process->name);
return -EACCES;
}
uint32_t out = read_fs(node, FD_OFFSET(fd), len, (uint8_t *)ptr);
FD_OFFSET(fd) += out;
return (int)out; return (int)out;
} }
return -EBADF; return -EBADF;
@ -96,12 +104,12 @@ static int sys_write(int fd, char * ptr, int len) {
if (FD_CHECK(fd)) { if (FD_CHECK(fd)) {
PTR_VALIDATE(ptr); PTR_VALIDATE(ptr);
fs_node_t * node = FD_ENTRY(fd); fs_node_t * node = FD_ENTRY(fd);
if (!has_permission(node, 02)) { if (!(FD_MODE(fd) & 02)) {
debug_print(WARNING, "access denied (write, fd=%d)", fd); debug_print(WARNING, "access denied (write, fd=%d)", fd);
return -EACCES; return -EACCES;
} }
uint32_t out = write_fs(node, node->offset, len, (uint8_t *)ptr); uint32_t out = write_fs(node, FD_OFFSET(fd), len, (uint8_t *)ptr);
node->offset += out; FD_OFFSET(fd) += out;
return out; return out;
} }
return -EBADF; return -EBADF;
@ -119,17 +127,24 @@ static int sys_open(const char * file, int flags, int mode) {
debug_print(NOTICE, "open(%s) flags=0x%x; mode=0x%x", file, flags, mode); debug_print(NOTICE, "open(%s) flags=0x%x; mode=0x%x", file, flags, mode);
fs_node_t * node = kopen((char *)file, flags); fs_node_t * node = kopen((char *)file, flags);
if (node && !has_permission(node, 04)) { int access_bits = 0;
debug_print(WARNING, "access denied (read, sys_open, file=%s)", file);
close_fs(node); if (!(flags & O_WRONLY) || (flags & O_RDWR)) {
return -EACCES; if (node && !has_permission(node, 04)) {
debug_print(WARNING, "access denied (read, sys_open, file=%s)", file);
close_fs(node);
return -EACCES;
} else {
access_bits |= 01;
}
} }
if (node && ((flags & O_RDWR) || (flags & O_APPEND) || (flags & O_WRONLY) || (flags & O_TRUNC))) { if ((flags & O_RDWR) || (flags & O_APPEND) || (flags & O_WRONLY) || (flags & O_TRUNC)) {
if (!has_permission(node, 02)) { if (node && !has_permission(node, 02)) {
debug_print(WARNING, "access denied (write, sys_open, file=%s)", file); debug_print(WARNING, "access denied (write, sys_open, file=%s)", file);
close_fs(node); close_fs(node);
return -EACCES; return -EACCES;
} }
access_bits |= 02;
} }
if (!node && (flags & O_CREAT)) { if (!node && (flags & O_CREAT)) {
@ -147,12 +162,13 @@ static int sys_open(const char * file, int flags, int mode) {
debug_print(NOTICE, "File does not exist; someone should be setting errno?"); debug_print(NOTICE, "File does not exist; someone should be setting errno?");
return -ENOENT; return -ENOENT;
} }
if (flags & O_APPEND) {
node->offset = node->length;
} else {
node->offset = 0;
}
int fd = process_append_fd((process_t *)current_process, node); int fd = process_append_fd((process_t *)current_process, node);
FD_MODE(fd) = access_bits;
if (flags & O_APPEND) {
FD_OFFSET(fd) = node->length;
} else {
FD_OFFSET(fd) = 0;
}
debug_print(INFO, "[open] pid=%d %s -> %d", getpid(), file, fd); debug_print(INFO, "[open] pid=%d %s -> %d", getpid(), file, fd);
return fd; return fd;
} }
@ -271,16 +287,16 @@ static int sys_seek(int fd, int offset, int whence) {
} }
switch (whence) { switch (whence) {
case 0: case 0:
FD_ENTRY(fd)->offset = offset; FD_OFFSET(fd) = offset;
break; break;
case 1: case 1:
FD_ENTRY(fd)->offset += offset; FD_OFFSET(fd) += offset;
break; break;
case 2: case 2:
FD_ENTRY(fd)->offset = FD_ENTRY(fd)->length + offset; FD_OFFSET(fd) = FD_ENTRY(fd)->length + offset;
break; break;
} }
return FD_ENTRY(fd)->offset; return FD_OFFSET(fd);
} }
return -EBADF; return -EBADF;
} }
@ -385,7 +401,9 @@ static int sys_stat(int fd, uintptr_t st) {
static int sys_mkpipe(void) { static int sys_mkpipe(void) {
fs_node_t * node = make_pipe(4096 * 2); fs_node_t * node = make_pipe(4096 * 2);
open_fs(node, 0); open_fs(node, 0);
return process_append_fd((process_t *)current_process, node); int fd = process_append_fd((process_t *)current_process, node);
FD_MODE(fd) = 03; /* read write */
return fd;
} }
static int sys_dup2(int old, int new) { static int sys_dup2(int old, int new) {
@ -811,6 +829,9 @@ static int sys_openpty(int * master, int * slave, char * name, void * _ign0, voi
*master = process_append_fd((process_t *)current_process, fs_master); *master = process_append_fd((process_t *)current_process, fs_master);
*slave = process_append_fd((process_t *)current_process, fs_slave); *slave = process_append_fd((process_t *)current_process, fs_slave);
FD_MODE(*master) = 03;
FD_MODE(*slave) = 03;
open_fs(fs_master, 0); open_fs(fs_master, 0);
open_fs(fs_slave, 0); open_fs(fs_slave, 0);
@ -832,6 +853,8 @@ static int sys_pipe(int pipes[2]) {
pipes[0] = process_append_fd((process_t *)current_process, outpipes[0]); pipes[0] = process_append_fd((process_t *)current_process, outpipes[0]);
pipes[1] = process_append_fd((process_t *)current_process, outpipes[1]); pipes[1] = process_append_fd((process_t *)current_process, outpipes[1]);
FD_MODE(pipes[0]) = 03;
FD_MODE(pipes[1]) = 03;
return 0; return 0;
} }

View File

@ -780,18 +780,15 @@ static void debug_shell_run(void * data, char * name) {
/* Set the device to be the actual TTY slave */ /* Set the device to be the actual TTY slave */
tty = fs_slave; tty = fs_slave;
int fd = process_append_fd((process_t *)current_process, tty); int fd = process_append_fd((process_t *)current_process, tty);
current_process->fds->modes[fd] = 03; /* rw */
process_move_fd((process_t *)current_process, fd, 0); process_move_fd((process_t *)current_process, fd, 0);
process_move_fd((process_t *)current_process, fd, 1); process_move_fd((process_t *)current_process, fd, 1);
process_move_fd((process_t *)current_process, fd, 2);
fs_master->refcount = -1; fs_master->refcount = -1;
fs_slave->refcount = -1; fs_slave->refcount = -1;
current_process->fds->entries[0] = tty;
current_process->fds->entries[1] = tty;
current_process->fds->entries[2] = tty;
current_process->fds->length = 3;
tty_set_vintr(tty, 0x02); tty_set_vintr(tty, 0x02);
fprintf(tty, "\n\n" fprintf(tty, "\n\n"