Skip to content

Commit

Permalink
Implement ptys
Browse files Browse the repository at this point in the history
Also a bunch of somewhat related changes, I was too lazy to break this into more than one commit
  • Loading branch information
tbodt committed Jan 21, 2019
1 parent 21a2db3 commit 088e7b7
Show file tree
Hide file tree
Showing 38 changed files with 705 additions and 278 deletions.
14 changes: 7 additions & 7 deletions app/Terminal.m
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,16 @@ - (void)syncWindowSize {
}];
}

- (size_t)write:(const void *)buf length:(size_t)len {
- (int)write:(const void *)buf length:(size_t)len {
@synchronized (self) {
[self.pendingData appendData:[NSData dataWithBytes:buf length:len]];
[self.refreshTask schedule];
}
return len;
return 0;
}

- (void)sendInput:(const char *)buf length:(size_t)len {
tty_input(self.tty, buf, len);
tty_input(self.tty, buf, len, 0);
[self.scrollToBottomTask schedule];
}

Expand Down Expand Up @@ -229,7 +229,7 @@ + (Terminal *)terminalWithType:(int)type number:(int)number {

@end

static int ios_tty_open(struct tty *tty) {
static int ios_tty_init(struct tty *tty) {
Terminal *terminal = [Terminal terminalWithType:tty->type number:tty->num];
terminal.tty = tty;
tty->refcount++;
Expand Down Expand Up @@ -264,12 +264,12 @@ static ssize_t ios_tty_write(struct tty *tty, const void *buf, size_t len) {
return [terminal write:buf length:len];
}

static void ios_tty_close(struct tty *tty) {
static void ios_tty_cleanup(struct tty *tty) {
CFBridgingRelease(tty->data);
}

struct tty_driver ios_tty_driver = {
.open = ios_tty_open,
.init = ios_tty_init,
.write = ios_tty_write,
.close = ios_tty_close,
.cleanup = ios_tty_cleanup,
};
4 changes: 2 additions & 2 deletions fs/adhoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

static struct mount adhoc_mount;

struct fd *adhoc_fd_create() {
struct fd *fd = fd_create();
struct fd *adhoc_fd_create(const struct fd_ops *ops) {
struct fd *fd = fd_create(ops);
if (fd == NULL)
return NULL;
adhoc_mount.refcount++;
Expand Down
4 changes: 3 additions & 1 deletion fs/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ struct dev_ops *char_devs[256] = {
[1] = &mem_dev,
[4] = &tty_dev,
[5] = &tty_dev,
[TTY_PSEUDO_MASTER_MAJOR] = &tty_dev,
[TTY_PSEUDO_SLAVE_MAJOR] = &tty_dev,
};

int dev_open(int major, int minor, int type, struct fd *fd) {
Expand All @@ -20,5 +22,5 @@ int dev_open(int major, int minor, int type, struct fd *fd) {
fd->ops = &dev->fd;
if (!dev->open)
return 0;
return dev->open(major, minor, type, fd);
return dev->open(major, minor, fd);
}
2 changes: 1 addition & 1 deletion fs/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static inline dev_t_ dev_fake_from_real(dev_t dev) {
#define DEV_CHAR 1

struct dev_ops {
int (*open)(int major, int minor, int type, struct fd *fd);
int (*open)(int major, int minor, struct fd *fd);
struct fd_ops fd;
};

Expand Down
22 changes: 18 additions & 4 deletions fs/dir.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
#include <sys/stat.h>
#include <string.h>

#include "kernel/calls.h"
#include "kernel/errno.h"
#include "kernel/fs.h"
#include "fs/fd.h"

static unsigned long fd_telldir(struct fd *fd) {
unsigned long off = fd->offset;
if (fd->ops->telldir)
off = fd->ops->telldir(fd);
return off;
}

static void fd_seekdir(struct fd *fd, unsigned long off) {
fd->offset = off;
if (fd->ops->seekdir)
fd->ops->seekdir(fd, off);
}

struct linux_dirent64 {
qword_t inode;
qword_t offset;
Expand All @@ -18,7 +32,7 @@ int_t sys_getdents64(fd_t f, addr_t dirents, dword_t count) {
struct fd *fd = f_get(f);
if (fd == NULL)
return _EBADF;
if (fd->ops->readdir == NULL)
if (!S_ISDIR(fd->type) || fd->ops->readdir == NULL)
return _ENOTDIR;

dword_t orig_count = count;
Expand All @@ -27,7 +41,7 @@ int_t sys_getdents64(fd_t f, addr_t dirents, dword_t count) {
int err;
int printed = 0;
while (true) {
ptr = fd->ops->telldir(fd);
ptr = fd_telldir(fd);
struct dir_entry entry;
err = fd->ops->readdir(fd, &entry);
if (err < 0)
Expand All @@ -40,7 +54,7 @@ int_t sys_getdents64(fd_t f, addr_t dirents, dword_t count) {
char dirent_data[reclen];
struct linux_dirent64 *dirent = (struct linux_dirent64 *) dirent_data;
dirent->inode = entry.inode;
dirent->offset = fd->ops->telldir(fd);
dirent->offset = fd_telldir(fd);
dirent->reclen = reclen;
dirent->type = 0;
strcpy(dirent->name, entry.name);
Expand All @@ -58,6 +72,6 @@ int_t sys_getdents64(fd_t f, addr_t dirents, dword_t count) {
count -= reclen;
}

fd->ops->seekdir(fd, ptr);
fd_seekdir(fd, ptr);
return orig_count - count;
}
19 changes: 13 additions & 6 deletions fs/fd.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
#include "fs/poll.h"
#include "fs/fd.h"

struct fd *fd_create() {
struct fd *fd_create(const struct fd_ops *ops) {
struct fd *fd = malloc(sizeof(struct fd));
if (fd == NULL)
return NULL;
*fd = (struct fd) {};
fd->ops = ops;
fd->refcount = 1;
fd->flags = 0;
fd->mount = NULL;
fd->offset = 0;
list_init(&fd->poll_fds);
lock_init(&fd->poll_lock);
lock_init(&fd->lock);
Expand Down Expand Up @@ -251,6 +255,12 @@ dword_t sys_dup2(fd_t f, fd_t new_f) {
return new_f;
}

#define FD_ALLOWED_FLAGS (O_APPEND_ | O_NONBLOCK_)
static int fd_setflags(struct fd *fd, int flags) {
fd->flags = (fd->flags & ~FD_ALLOWED_FLAGS) | (flags & FD_ALLOWED_FLAGS);
return 0;
}

dword_t sys_fcntl64(fd_t f, dword_t cmd, dword_t arg) {
struct fdtable *table = current->files;
struct fd *fd = f_get(f);
Expand Down Expand Up @@ -280,11 +290,8 @@ dword_t sys_fcntl64(fd_t f, dword_t cmd, dword_t arg) {
return fd->ops->getflags(fd);
case F_SETFL_:
STRACE("fcntl(%d, F_SETFL, %#x)", f, arg);
if (fd->ops->setflags == NULL) {
arg &= O_APPEND_ | O_NONBLOCK_;
fd->flags = arg;
return 0;
}
if (fd->ops->setflags == NULL)
return fd_setflags(fd, arg);
return fd->ops->setflags(fd, arg);

default:
Expand Down
35 changes: 24 additions & 11 deletions fs/fd.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,14 @@
struct fd {
atomic_uint refcount;
unsigned flags;
mode_t_ type; // just the S_IFMT part, it can't change
const struct fd_ops *ops;
struct list poll_fds;
lock_t poll_lock;
off_t_ offset;
unsigned long offset;

// fd data
union {
// proc
struct {
struct proc_entry proc_entry;
unsigned proc_dir_index;
char *proc_data;
size_t proc_size;
};
// tty
struct {
struct tty *tty;
Expand All @@ -48,6 +42,20 @@ struct fd {
uint64_t expirations;
};
};
// fs data
union {
// proc
struct {
struct proc_entry proc_entry;
unsigned proc_dir_index;
char *proc_data;
size_t proc_size;
};
// devpts
struct {
int pty_num;
};
};

// fs/inode data
struct mount *mount;
Expand All @@ -63,7 +71,7 @@ struct fd {
typedef sdword_t fd_t;
#define AT_FDCWD_ -100

struct fd *fd_create(void);
struct fd *fd_create(const struct fd_ops *ops);
struct fd *fd_retain(struct fd *fd);
int fd_close(struct fd *fd);

Expand All @@ -78,16 +86,21 @@ struct dir_entry {
#define LSEEK_END 2

struct fd_ops {
// required for files
// TODO make optional for non-files
ssize_t (*read)(struct fd *fd, void *buf, size_t bufsize);
ssize_t (*write)(struct fd *fd, const void *buf, size_t bufsize);
off_t_ (*lseek)(struct fd *fd, off_t_ off, int whence);

// Reads a directory entry from the stream
// required for directories
int (*readdir)(struct fd *fd, struct dir_entry *entry);
// Return an opaque value representing the current point in the directory stream
long (*telldir)(struct fd *fd);
// optional, fd->offset will be used instead
unsigned long (*telldir)(struct fd *fd);
// Seek to the location represented by a pointer returned from telldir
int (*seekdir)(struct fd *fd, long ptr);
// optional, fd->offset will be used instead
void (*seekdir)(struct fd *fd, unsigned long ptr);

// map the file
int (*mmap)(struct fd *fd, struct mem *mem, page_t start, pages_t pages, off_t offset, int prot, int flags);
Expand Down
44 changes: 27 additions & 17 deletions fs/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,31 @@ struct fd *generic_openat(struct fd *at, const char *path_raw, int flags, int mo

struct statbuf stat;
err = fd->mount->fs->fstat(fd, &stat);
if (err >= 0) {
assert(!S_ISLNK(stat.mode)); // would mean path_normalize didn't do its job
if (S_ISBLK(stat.mode) || S_ISCHR(stat.mode)) {
int type;
if (S_ISBLK(stat.mode))
type = DEV_BLOCK;
else
type = DEV_CHAR;
int major = dev_major(stat.rdev);
int minor = dev_minor(stat.rdev);
err = dev_open(major, minor, type, fd);
if (err < 0) {
fd_close(fd);
return ERR_PTR(err);
}
if (err < 0) {
fd_close(fd);
return ERR_PTR(err);
}
fd->type = stat.mode & S_IFMT;
fd->flags = flags;

assert(!S_ISLNK(fd->type)); // would mean path_normalize didn't do its job
if (S_ISBLK(fd->type) || S_ISCHR(fd->type)) {
int type;
if (S_ISBLK(fd->type))
type = DEV_BLOCK;
else
type = DEV_CHAR;
err = dev_open(dev_major(stat.rdev), dev_minor(stat.rdev), type, fd);
if (err < 0) {
fd_close(fd);
return ERR_PTR(err);
}
}
if (S_ISDIR(fd->type) && flags & (O_RDWR_ | O_WRONLY_)) {
fd_close(fd);
return ERR_PTR(_EISDIR);
}

return fd;
}

Expand Down Expand Up @@ -88,7 +96,7 @@ int generic_accessat(struct fd *dirfd, const char *path_raw, int UNUSED(mode)) {
return err;

struct mount *mount = find_mount_and_trim_path(path);
struct statbuf stat;
struct statbuf stat = {};
err = mount->fs->stat(mount, path, &stat, true);
mount_release(mount);
if (err < 0)
Expand Down Expand Up @@ -208,7 +216,9 @@ ssize_t generic_readlinkat(struct fd *at, const char *path_raw, char *buf, size_
if (err < 0)
return err;
struct mount *mount = find_mount_and_trim_path(path);
err = mount->fs->readlink(mount, path, buf, bufsize);
err = _EINVAL;
if (mount->fs->readlink)
err = mount->fs->readlink(mount, path, buf, bufsize);
mount_release(mount);
return err;
}
Expand Down
6 changes: 3 additions & 3 deletions fs/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ struct dev_ops *mem_devs[256] = {
};

// dispatch device for major device 1
static int mem_open(int major, int minor, int type, struct fd *fd) {
static int mem_open(int major, int minor, struct fd *fd) {
struct dev_ops *dev = mem_devs[minor];
if (dev == NULL) {
return _ENXIO;
}
fd->ops = &dev->fd;
if (!dev->open)
return 0;
return dev->open(major, minor, type, fd);
return dev->open(major, minor, fd);
}

struct dev_ops mem_dev = {
.open = mem_open,
};

// begin inline devices
static int null_open(int UNUSED(major), int UNUSED(minor), int UNUSED(type), struct fd *UNUSED(fd)) {
static int null_open(int UNUSED(major), int UNUSED(minor), struct fd *UNUSED(fd)) {
return 0;
}
static ssize_t null_read(struct fd *UNUSED(fd), void *UNUSED(buf), size_t UNUSED(bufsize)) {
Expand Down
1 change: 1 addition & 0 deletions fs/mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
const struct fs_ops *filesystems[] = {
&realfs,
&procfs,
&devptsfs,
};

struct mount *mount_find(char *path) {
Expand Down
4 changes: 3 additions & 1 deletion fs/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ int path_normalize(struct fd *at, const char *path, char *out, bool follow_links
strcpy(possible_symlink, out);
struct mount *mount = find_mount_and_trim_path(possible_symlink);
assert(path_is_normalized(possible_symlink));
int res = mount->fs->readlink(mount, possible_symlink, c, MAX_PATH - (c - out));
int res = _EINVAL;
if (mount->fs->readlink)
res = mount->fs->readlink(mount, possible_symlink, c, MAX_PATH - (c - out));
mount_release(mount);
if (res >= 0) {
// readlink does not null terminate
Expand Down
3 changes: 1 addition & 2 deletions fs/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
#include "debug.h"

static fd_t pipe_f_create(int pipe_fd, int flags) {
struct fd *fd = adhoc_fd_create();
struct fd *fd = adhoc_fd_create(&realfs_fdops);
if (fd == NULL)
return _ENOMEM;
fd->real_fd = pipe_fd;
fd->ops = &realfs_fdops;
return f_install(fd, flags);
}

Expand Down
Loading

0 comments on commit 088e7b7

Please sign in to comment.