Skip to content

Commit

Permalink
Implement read-only /dev/clipboard (fix ish-app#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
stek29 committed Aug 6, 2019
1 parent c7dc14a commit 9310c44
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 0 deletions.
11 changes: 11 additions & 0 deletions app/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
#include <arpa/inet.h>
#include <netdb.h>
#import "AppDelegate.h"
#import "Pasteboard.h"
#import "TerminalViewController.h"
#import "UserPreferences.h"
#include "kernel/init.h"
#include "kernel/calls.h"
#include "fs/path.h"
#include "fs/dyndev.h"

@interface AppDelegate ()

Expand Down Expand Up @@ -103,6 +105,15 @@ - (int)startThings {
generic_mknod("/dev/random", S_IFCHR|0666, dev_make(1, 8));
generic_mknod("/dev/urandom", S_IFCHR|0666, dev_make(1, 9));
generic_mkdirat(AT_PWD, "/dev/pts", 0755);

// Register clipboard device driver and create device node for it
int clipboard_dev_minor = dyn_dev_register(&clipboard_dev, CLIPBOARD_DEV_MINOR);
if (clipboard_dev_minor != CLIPBOARD_DEV_MINOR) {
return clipboard_dev_minor;
}
// XXX(stek29): mknod does nothing if device already exists, but has different major/minor number
// but dyn_dev doesn't guarantee fixed minor number. Consider dynamic minor selection.
generic_mknod("/dev/clipboard", S_IFCHR|0666, dev_make(DYN_DEV_MAJOR, clipboard_dev_minor));

do_mount(&procfs, "proc", "/proc", 0);
do_mount(&devptsfs, "devpts", "/dev/pts", 0);
Expand Down
5 changes: 5 additions & 0 deletions app/Pasteboard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Pasteboard is implementation of /dev/clipboard device

#define CLIPBOARD_DEV_MINOR 0

extern struct dev_ops clipboard_dev;
139 changes: 139 additions & 0 deletions app/Pasteboard.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include <string.h>
#import <UIKit/UIKit.h>
#include "fs/poll.h"
#include "fs/dyndev.h"
#include "kernel/errno.h"
#include "debug.h"

#if 0
#define CLIP_DEBUG_PRINTK(...) printk
#else
#define CLIP_DEBUG_PRINTK(...)
#endif

static void inline dump_clipboard_state(const char* tag, struct fd *fd) {
CLIP_DEBUG_PRINTK("%s offset=%d pb_gen=%d len=%lu\n", tag, fd->offset, fd->eventfd.val, UIPasteboard.generalPasteboard.string.length);
}

// Generation aka UIPasteboard changeCount is stored at fd->eventfd.val
//
// If pasteboard contents were changed since file was opened,
// all read operations on in return IO Error
static int check_read_generation(struct fd* fd, UIPasteboard *pb) {
uint64_t pb_gen = (uint64_t)pb.changeCount;
uint64_t fd_gen = fd->eventfd.val;

CLIP_DEBUG_PRINTK("%s(%p): pb_gen=%d fd_gen=%d offset=%d\n", __func__, fd, pb_gen, fd_gen, fd->offset);
// XXX: fd_gen modifications should be locked
if (fd_gen == 0 || fd->offset == 0) {
fd->eventfd.val = pb_gen;
} else if (fd_gen != pb_gen) {
return _EIO;
}

return 0;
}

static int clipboard_poll(struct fd *fd) {
CLIP_DEBUG_PRINTK("%s(%p)\n", fd, __func__);
int rv = 0;

UIPasteboard* pb = UIPasteboard.generalPasteboard;
if (check_read_generation(fd, pb) == 0) {
if (fd->offset < pb.string.length) {
rv |= POLL_READ;
}
}

return rv;
}

static ssize_t clipboard_read(struct fd *fd, void *buf, size_t bufsize) {
CLIP_DEBUG_PRINTK("%s(%p, buf, %zu)\n", __func__, fd, bufsize);
dump_clipboard_state("read pre", fd);
UIPasteboard* pb = UIPasteboard.generalPasteboard;

NSString *contents = pb.string;

int err = check_read_generation(fd, pb);
if (err != 0) {
return err;
}

size_t length = contents.length;

size_t remaining = length - fd->offset;
if ((size_t) fd->offset > length)
remaining = 0;
size_t n = bufsize;
if (n > remaining)
n = remaining;

if (n != 0) {
memcpy(buf, contents.UTF8String + fd->offset, n);
fd->offset += n;
}

dump_clipboard_state("read post", fd);
return n;
}

static off_t_ clipboard_lseek(struct fd *fd, off_t_ off, int whence) {
CLIP_DEBUG_PRINTK("%s(%p, off=%d, whence=%d)\n", __func__, fd, off, whence);
dump_clipboard_state("lseek pre", fd);
off_t_ old_off = fd->offset;
size_t length = 0;

if (whence != LSEEK_SET || off != 0) {
UIPasteboard *pb = UIPasteboard.generalPasteboard;
length = pb.string.length;

int err = check_read_generation(fd, pb);
if (err != 0) {
return err;
}
}

switch (whence) {
case LSEEK_SET:
fd->offset = off;
break;

case LSEEK_CUR:
fd->offset += off;
break;

case LSEEK_END:
fd->offset = length + off;
break;

default:
return _EINVAL;
}

if (fd->offset < 0) {
fd->offset = old_off;
return _EINVAL;
}

dump_clipboard_state("lseek post", fd);
return fd->offset;
}

static int clipboard_close(struct fd *fd) {
CLIP_DEBUG_PRINTK("%s(%p)\n", __func__, fd);
return 0;
}

static int clipboard_open(int major, int minor, struct fd *fd) {
CLIP_DEBUG_PRINTK("%s(%p)\n", __func__, fd);
return 0;
}

struct dev_ops clipboard_dev = {
.open = clipboard_open,
.fd.read = clipboard_read,
.fd.lseek = clipboard_lseek,
.fd.poll = clipboard_poll,
.fd.close = clipboard_close,
};
6 changes: 6 additions & 0 deletions iSH.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
650B336A22E9F0B500B4C03E /* entry.c in Sources */ = {isa = PBXBuildFile; fileRef = 650B336722E9F0B500B4C03E /* entry.c */; };
650B336B22E9F0B500B4C03E /* root.c in Sources */ = {isa = PBXBuildFile; fileRef = 650B336822E9F0B500B4C03E /* root.c */; };
650B336E22EA052500B4C03E /* dyndev.c in Sources */ = {isa = PBXBuildFile; fileRef = 650B336C22EA052400B4C03E /* dyndev.c */; };
650B337422EA235C00B4C03E /* Pasteboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 650B337322EA235C00B4C03E /* Pasteboard.m */; };
8632A7BF219A59FB00F02325 /* UserPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 8632A7BE219A59FB00F02325 /* UserPreferences.m */; };
9A28E4EA219A8B670073D200 /* AppearanceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A28E4E9219A8B670073D200 /* AppearanceViewController.m */; };
BB0FC5921F980A6C00803272 /* Terminal.m in Sources */ = {isa = PBXBuildFile; fileRef = BB0FC5911F980A6B00803272 /* Terminal.m */; };
Expand Down Expand Up @@ -100,6 +101,8 @@
650B336822E9F0B500B4C03E /* root.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = root.c; sourceTree = "<group>"; };
650B336C22EA052400B4C03E /* dyndev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dyndev.c; sourceTree = "<group>"; };
650B336D22EA052400B4C03E /* dyndev.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dyndev.h; sourceTree = "<group>"; };
650B337222EA235C00B4C03E /* Pasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pasteboard.h; sourceTree = "<group>"; };
650B337322EA235C00B4C03E /* Pasteboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Pasteboard.m; sourceTree = "<group>"; };
8632A7BD219A59FB00F02325 /* UserPreferences.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserPreferences.h; sourceTree = "<group>"; };
8632A7BE219A59FB00F02325 /* UserPreferences.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UserPreferences.m; sourceTree = "<group>"; };
9A28E4E8219A8B670073D200 /* AppearanceViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppearanceViewController.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -376,6 +379,8 @@
BB792B521F96D90D00FFB7A4 /* app */ = {
isa = PBXGroup;
children = (
650B337222EA235C00B4C03E /* Pasteboard.h */,
650B337322EA235C00B4C03E /* Pasteboard.m */,
BB792B531F96D90D00FFB7A4 /* AppDelegate.h */,
BB792B541F96D90D00FFB7A4 /* AppDelegate.m */,
BB792B561F96D90D00FFB7A4 /* TerminalViewController.h */,
Expand Down Expand Up @@ -934,6 +939,7 @@
BB60F55221573FCA003A4E52 /* BarButton.m in Sources */,
BBFB557C215878C600DFE6DE /* UIApplication+OpenURL.m in Sources */,
BBFB5579215876CD00DFE6DE /* AboutViewController.m in Sources */,
650B337422EA235C00B4C03E /* Pasteboard.m in Sources */,
BBFB557121586C4800DFE6DE /* UIViewController+Back.m in Sources */,
650B336E22EA052500B4C03E /* dyndev.c in Sources */,
650B336B22E9F0B500B4C03E /* root.c in Sources */,
Expand Down

0 comments on commit 9310c44

Please sign in to comment.