From 68340acd03a1eb9bc87eec9504b082ca7badff7d Mon Sep 17 00:00:00 2001 From: NoahPeeters Date: Sat, 14 Dec 2019 13:54:59 +0200 Subject: [PATCH] Add support for mounting folders from iOS --- app/AppDelegate.m | 9 +- app/SceneDelegate.h | 3 + app/SceneDelegate.m | 16 +- app/iOSFS.h | 9 + app/iOSFS.m | 449 ++++++++++++++++++++++++++++++++++ fs/mount.c | 6 +- fs/real.c | 34 +-- iSH.xcodeproj/project.pbxproj | 9 + kernel/fs.h | 33 +++ 9 files changed, 548 insertions(+), 20 deletions(-) create mode 100644 app/iOSFS.h create mode 100644 app/iOSFS.m diff --git a/app/AppDelegate.m b/app/AppDelegate.m index 324158a5..273ba9f6 100644 --- a/app/AppDelegate.m +++ b/app/AppDelegate.m @@ -10,11 +10,13 @@ #include #import #import "AppDelegate.h" +#import "AppGroup.h" +#import "iOSFS.h" +#import "SceneDelegate.h" #import "PasteboardDevice.h" #import "LocationDevice.h" #import "TerminalViewController.h" #import "UserPreferences.h" -#import "AppGroup.h" #include "kernel/init.h" #include "kernel/calls.h" #include "fs/dyndev.h" @@ -137,7 +139,9 @@ static void ios_handle_die(const char *msg) { die_handler = ios_handle_die; NSString *sockTmp = [NSTemporaryDirectory() stringByAppendingString:@"ishsock"]; sock_tmp_prefix = strdup(sockTmp.UTF8String); - + + filesystems[IOS_FILESYSTEM_ID] = &iosfs; + filesystems[IOS_UNSAFE_FILESYSTEM_ID] = &iosfs_unsafe; tty_drivers[TTY_CONSOLE_MAJOR] = &ios_console_driver; set_console_device(TTY_CONSOLE_MAJOR, 1); err = create_stdio("/dev/console", TTY_CONSOLE_MAJOR, 1); @@ -237,6 +241,7 @@ void NetworkReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach if (self.window != nil) { // For iOS <13, where the app delegate owns the window instead of the scene TerminalViewController *vc = (TerminalViewController *) self.window.rootViewController; + currentTerminalViewController = vc; [vc startNewSession]; } return YES; diff --git a/app/SceneDelegate.h b/app/SceneDelegate.h index 5fcf546f..c4032a50 100644 --- a/app/SceneDelegate.h +++ b/app/SceneDelegate.h @@ -6,9 +6,12 @@ // #import +#import "TerminalViewController.h" NS_ASSUME_NONNULL_BEGIN +extern TerminalViewController *currentTerminalViewController; + API_AVAILABLE(ios(13)) @interface SceneDelegate : UIResponder diff --git a/app/SceneDelegate.m b/app/SceneDelegate.m index 4ed9a09b..bb9a526a 100644 --- a/app/SceneDelegate.m +++ b/app/SceneDelegate.m @@ -6,7 +6,8 @@ // #import "SceneDelegate.h" -#import "TerminalViewController.h" + +TerminalViewController *currentTerminalViewController = NULL; @interface SceneDelegate () @@ -40,4 +41,17 @@ static NSString *const TerminalUUID = @"TerminalUUID"; return activity; } +- (void)sceneDidBecomeActive:(UIScene *)scene { + TerminalViewController *terminalViewController = (TerminalViewController *) self.window.rootViewController;; + currentTerminalViewController = terminalViewController; +} + +- (void)sceneWillResignActive:(UIScene *)scene { + TerminalViewController *terminalViewController = (TerminalViewController *) self.window.rootViewController; + + if (currentTerminalViewController == terminalViewController) { + currentTerminalViewController = NULL; + } +} + @end diff --git a/app/iOSFS.h b/app/iOSFS.h new file mode 100644 index 00000000..fcfc01cf --- /dev/null +++ b/app/iOSFS.h @@ -0,0 +1,9 @@ +// +// iOSFS.h +// iSH +// +// Created by Noah Peeters on 26.10.19. +// + +extern const struct fs_ops iosfs; +extern const struct fs_ops iosfs_unsafe; diff --git a/app/iOSFS.m b/app/iOSFS.m new file mode 100644 index 00000000..36f1c130 --- /dev/null +++ b/app/iOSFS.m @@ -0,0 +1,449 @@ +// +// iOSFS.m +// iSH +// +// Created by Noah Peeters on 26.10.19. +// + +#import +#import +#include +#include "SceneDelegate.h" +#include "iOSFS.h" +#include "kernel/fs.h" +#include "kernel/errno.h" +#include "fs/path.h" + +const NSFileCoordinatorWritingOptions NSFileCoordinatorWritingForCreating = NSFileCoordinatorWritingForMerging; + +@interface DirectoryPickerDelegate : NSObject + +@property NSURL *url; +@property pthread_mutex_t *mutex; + +@end + +@implementation DirectoryPickerDelegate + +- (instancetype)initWithMutex:(pthread_mutex_t *)mutex { + if (self = [super init]) { + self.mutex = mutex; + self.url = nil; + pthread_mutex_lock(mutex); + } + return self; +} + +- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller { + pthread_mutex_unlock(self.mutex); +} + +- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray *)urls { + if (urls.count > 0) + self.url = urls[0]; + pthread_mutex_unlock(self.mutex); +} + +@end + +NSURL *url_for_mount(struct mount *mount) { + return (__bridge NSURL *) mount->data; +} + +NSURL *url_for_path_in_mount(struct mount *mount, const char *path) { + return [[url_for_mount(mount) URLByAppendingPathComponent:[NSString stringWithUTF8String:path]] URLByStandardizingPath]; +} + +const char *path_for_url_in_mount(struct mount *mount, NSURL *url, const char *fallback) { + NSString *mount_path = [[url_for_mount(mount) URLByStandardizingPath] path]; + NSString *url_path = [[url URLByStandardizingPath] path]; + + // The `/private` prefix is a special case as described in the documentation of `URLByStandardizingPath`. + if ([mount_path hasPrefix:@"/private/"]) mount_path = [mount_path substringFromIndex:8]; + if ([url_path hasPrefix:@"/private/"]) url_path = [url_path substringFromIndex:8]; + + if (![url_path hasPrefix:mount_path]) + return fallback; + + NSURL *new_url = [NSURL fileURLWithPath:[url_path substringFromIndex:[mount_path length]]]; + return [new_url ? [new_url path] : @"" cStringUsingEncoding:NSUTF8StringEncoding]; +} + +static int iosfs_stat(struct mount *mount, const char *path, struct statbuf *fake_stat); +const struct fd_ops iosfs_fdops; + +static int posixErrorFromNSError(NSError *error) { + if (error != nil) { + NSError *underlyingError = [error.userInfo objectForKey:NSUnderlyingErrorKey]; + if (underlyingError) { + return -(int)underlyingError.code + ; + } else { + return _EPERM; + } + } + + return 0; +} + +static int combine_error(NSError *coordinatorError, int err) { + int posix_error = posixErrorFromNSError(coordinatorError); + return posix_error ? posix_error : err; +} + +static struct fd *iosfs_open(struct mount *mount, const char *path, int flags, int mode) { + NSURL *url = url_for_path_in_mount(mount, path); + + struct statbuf stats; + int err = iosfs_stat(mount, path, &stats); + + if (!err && S_ISREG(stats.mode)) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + + __block pthread_mutex_t open_mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&open_mutex); + + __block NSError *error; + __block struct fd *openedFile; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ + void (^operation)(NSURL *url) = ^(NSURL *url) { + openedFile = realfs_open_with_fdops(mount, path_for_url_in_mount(mount, url, path), flags, mode, &iosfs_fdops); + + if (IS_ERR(openedFile)) { + pthread_mutex_unlock(&open_mutex); + } else { + pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&close_mutex); + openedFile->data = &close_mutex; + pthread_mutex_unlock(&open_mutex); + + pthread_mutex_lock(&close_mutex); + pthread_mutex_unlock(&close_mutex); + } + }; + + if (!(flags & O_WRONLY_) && !(flags & O_RDWR_)) { + [coordinator coordinateReadingItemAtURL:url options:NSFileCoordinatorReadingWithoutChanges error:&error byAccessor:operation]; + } else if (flags & O_CREAT_) { + [coordinator coordinateWritingItemAtURL:url options:NSFileCoordinatorWritingForCreating error:&error byAccessor:operation]; + } else { + [coordinator coordinateWritingItemAtURL:url options:NSFileCoordinatorWritingForMerging error:&error byAccessor:operation]; + } + }); + + pthread_mutex_lock(&open_mutex); + pthread_mutex_unlock(&open_mutex); + + int posix_error = posixErrorFromNSError(error); + return posix_error ? ERR_PTR(posix_error) : openedFile; + } else { + return realfs_open_with_fdops(mount, path, flags, mode, &iosfs_fdops); + } +} + +int iosfs_close(struct fd *fd) { + int err = realfs.close(fd); + + if (fd->data) { + pthread_mutex_t *mutex = (pthread_mutex_t *)fd->data; + pthread_mutex_unlock(mutex); + } + return err; +} + +static int iosfs_ask_for_url(NSURL **url) { + TerminalViewController *terminalViewController = currentTerminalViewController; + + if (!terminalViewController) + return _ENODEV; + + pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + DirectoryPickerDelegate *pickerDelegate = [[DirectoryPickerDelegate alloc] initWithMutex:&mutex]; + + dispatch_async(dispatch_get_main_queue(), ^(void) { + UIDocumentPickerViewController *picker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[ @"public.folder" ] inMode:UIDocumentPickerModeOpen]; + picker.delegate = pickerDelegate; + [terminalViewController presentViewController:picker animated:true completion:nil]; + }); + + pthread_mutex_lock(&mutex); + pthread_mutex_unlock(&mutex); + + if (pickerDelegate.url == nil) + return _ENODEV; + + *url = pickerDelegate.url; + return 0; +} + +static int iosfs_mount(struct mount *mount) { + NSURL *url; + + int err = iosfs_ask_for_url(&url); + if (err) + return err; + + // Overwrite url & base path + mount->data = (void *)CFBridgingRetain(url); + mount->source = strdup([[url path] UTF8String]); + + if ([url startAccessingSecurityScopedResource] == NO) { + CFBridgingRelease(mount->data); + return _EPERM; + } + + return realfs.mount(mount); +} + +static int iosfs_umount(struct mount *mount) { + NSURL *url = url_for_mount(mount); + [url stopAccessingSecurityScopedResource]; + CFBridgingRelease(mount->data); + + return 0; +} + +static int iosfs_rename(struct mount *mount, const char *src, const char *dst) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *src_url = url_for_path_in_mount(mount, src); + NSURL *dst_url = url_for_path_in_mount(mount, dst); + + NSError *error; + __block int err; + + [coordinator coordinateWritingItemAtURL:src_url options:NSFileCoordinatorWritingForMoving error:&error byAccessor:^(NSURL *url) { + [coordinator itemAtURL:url willMoveToURL:dst_url]; + err = realfs.rename(mount, path_for_url_in_mount(mount, url, src), dst); + [coordinator itemAtURL:url didMoveToURL:dst_url]; + }]; + + return combine_error(error, err); +} + +static int iosfs_symlink(struct mount *mount, const char *target, const char *link) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *dst_url = url_for_path_in_mount(mount, link); + + NSError *error; + __block int err; + + [coordinator coordinateWritingItemAtURL:dst_url options:NSFileCoordinatorWritingForCreating error:&error byAccessor:^(NSURL *url) { + err = realfs.symlink(mount, path_for_url_in_mount(mount, url, target), link); + }]; + + return combine_error(error, err); +} + +static int iosfs_mknod(struct mount *mount, const char *path, mode_t_ mode, dev_t_ dev) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *in_url = url_for_path_in_mount(mount, path); + + NSError *error; + __block int err; + + [coordinator coordinateWritingItemAtURL:in_url options:NSFileCoordinatorWritingForCreating error:&error byAccessor:^(NSURL *url) { + err = realfs.mknod(mount, path_for_url_in_mount(mount, url, path), mode, dev); + }]; + + return combine_error(error, err); +} + +static int iosfs_setattr(struct mount *mount, const char *path, struct attr attr) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *in_url = url_for_path_in_mount(mount, path); + + NSError *error; + __block int err; + + [coordinator coordinateWritingItemAtURL:in_url options:NSFileCoordinatorWritingContentIndependentMetadataOnly error:&error byAccessor:^(NSURL *url) { + err = realfs.setattr(mount, path_for_url_in_mount(mount, url, path), attr); + }]; + + return combine_error(error, err); +} + +static int iosfs_fsetattr(struct fd *fd, struct attr attr) { + return realfs.fsetattr(fd, attr); +} + +static ssize_t iosfs_readlink(struct mount *mount, const char *path, char *buf, size_t bufsize) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *in_url = url_for_path_in_mount(mount, path); + + NSError *error; + __block ssize_t size; + + [coordinator coordinateReadingItemAtURL:in_url options:NSFileCoordinatorReadingWithoutChanges error:&error byAccessor:^(NSURL *url) { + size = realfs.readlink(mount, path_for_url_in_mount(mount, url, path), buf, bufsize); + }]; + + int posix_error = posixErrorFromNSError(error); + return posix_error ? posix_error : size; +} + +static int iosfs_getpath(struct fd *fd, char *buf) { + return realfs.getpath(fd, buf); +} + +static int iosfs_link(struct mount *mount, const char *src, const char *dst) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *dst_url = url_for_path_in_mount(mount, dst); + + NSError *error; + __block int err; + + [coordinator coordinateWritingItemAtURL:dst_url options:NSFileCoordinatorWritingForCreating error:&error byAccessor:^(NSURL *url) { + err = realfs.link(mount, src, path_for_url_in_mount(mount, url, dst)); + }]; + + return combine_error(error, err); +} + +static int iosfs_unlink(struct mount *mount, const char *path) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *in_url = url_for_path_in_mount(mount, path); + + NSError *error; + __block int err; + + [coordinator coordinateWritingItemAtURL:in_url options:NSFileCoordinatorWritingForDeleting error:&error byAccessor:^(NSURL *url) { + err = realfs.unlink(mount, path_for_url_in_mount(mount, url, path)); + }]; + + return combine_error(error, err); +} + +static int iosfs_rmdir(struct mount *mount, const char *path) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *in_url = url_for_path_in_mount(mount, path); + + NSError *error; + __block int err; + + [coordinator coordinateWritingItemAtURL:in_url options:NSFileCoordinatorWritingForDeleting error:&error byAccessor:^(NSURL *url) { + err = realfs.rmdir(mount, path_for_url_in_mount(mount, url, path)); + }]; + + return combine_error(error, err); +} + +static int iosfs_stat(struct mount *mount, const char *path, struct statbuf *fake_stat) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *in_url = url_for_path_in_mount(mount, path); + + NSError *error; + __block int err; + + [coordinator coordinateReadingItemAtURL:in_url options:NSFileCoordinatorReadingWithoutChanges error:&error byAccessor:^(NSURL *url) { + err = realfs.stat(mount, path_for_url_in_mount(mount, url, path), fake_stat); + }]; + + return combine_error(error, err); +} + +static int iosfs_fstat(struct fd *fd, struct statbuf *fake_stat) { + int err = realfs.fstat(fd, fake_stat); + return err; +} + +static int iosfs_utime(struct mount *mount, const char *path, struct timespec atime, struct timespec mtime) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *in_url = url_for_path_in_mount(mount, path); + + NSError *error; + __block int err; + + [coordinator coordinateWritingItemAtURL:in_url options:NSFileCoordinatorWritingContentIndependentMetadataOnly error:&error byAccessor:^(NSURL *url) { + err = realfs.utime(mount, path_for_url_in_mount(mount, url, path), atime, mtime); + }]; + + return combine_error(error, err); +} + +static int iosfs_mkdir(struct mount *mount, const char *path, mode_t_ mode) { + NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *in_url = url_for_path_in_mount(mount, path); + + NSError *error; + __block int err; + + [coordinator coordinateWritingItemAtURL:in_url options:NSFileCoordinatorWritingForCreating error:&error byAccessor:^(NSURL *url) { + err = realfs.mkdir(mount, path_for_url_in_mount(mount, url, path), mode); + }]; + + return combine_error(error, err); +} + +static int iosfs_flock(struct fd *fd, int operation) { + return realfs.flock(fd, operation); +} + +const struct fs_ops iosfs = { + .name = "ios", .magic = 0x7265616d, + .mount = iosfs_mount, + .umount = iosfs_umount, + .statfs = realfs_statfs, + + .open = iosfs_open, + .readlink = iosfs_readlink, + .link = iosfs_link, + .unlink = iosfs_unlink, + .rmdir = iosfs_rmdir, + .rename = iosfs_rename, + .symlink = iosfs_symlink, + .mknod = iosfs_mknod, + + .close = iosfs_close, + .stat = iosfs_stat, + .fstat = iosfs_fstat, + .setattr = iosfs_setattr, + .fsetattr = iosfs_fsetattr, + .utime = iosfs_utime, + .getpath = iosfs_getpath, + .flock = iosfs_flock, + + .mkdir = iosfs_mkdir, +}; + +const struct fs_ops iosfs_unsafe = { + .name = "ios-unsafe", .magic = 0x7265616e, + .mount = iosfs_mount, + .umount = iosfs_umount, + .statfs = realfs_statfs, + + .open = realfs_open, + .readlink = realfs_readlink, + .link = realfs_link, + .unlink = realfs_unlink, + .rmdir = realfs_rmdir, + .rename = realfs_rename, + .symlink = realfs_symlink, + .mknod = realfs_mknod, + + .close = realfs_close, + .stat = realfs_stat, + .fstat = realfs_fstat, + .setattr = realfs_setattr, + .fsetattr = realfs_fsetattr, + .utime = realfs_utime, + .getpath = realfs_getpath, + .flock = realfs_flock, + + .mkdir = realfs_mkdir, +}; + +const struct fd_ops iosfs_fdops = { + .read = realfs_read, + .write = realfs_write, + .readdir = realfs_readdir, + .telldir = realfs_telldir, + .seekdir = realfs_seekdir, + .lseek = realfs_lseek, + .mmap = realfs_mmap, + .poll = realfs_poll, + .fsync = realfs_fsync, + .close = iosfs_close, + .getflags = realfs_getflags, + .setflags = realfs_setflags, +}; diff --git a/fs/mount.c b/fs/mount.c index 8a2abd46..f3c7be34 100644 --- a/fs/mount.c +++ b/fs/mount.c @@ -9,6 +9,8 @@ const struct fs_ops *filesystems[] = { &procfs, &devptsfs, &tmpfs, + [IOS_FILESYSTEM_ID] = NULL, + [IOS_UNSAFE_FILESYSTEM_ID] = NULL }; struct mount *mount_find(char *path) { @@ -17,7 +19,7 @@ struct mount *mount_find(char *path) { struct mount *mount = NULL; assert(!list_empty(&mounts)); // this would mean there's no root FS mounted list_for_each_entry(&mounts, mount, mounts) { - int n = strlen(mount->point); + size_t n = strlen(mount->point); if (strncmp(path, mount->point, n) == 0 && (path[n] == '/' || path[n] == '\0')) break; } @@ -120,7 +122,7 @@ dword_t sys_mount(addr_t source_addr, addr_t point_addr, addr_t type_addr, dword const struct fs_ops *fs = NULL; for (size_t i = 0; i < sizeof(filesystems)/sizeof(filesystems[0]); i++) { - if (strcmp(filesystems[i]->name, type) == 0) { + if (filesystems[i] && (strcmp(filesystems[i]->name, type) == 0)) { fs = filesystems[i]; break; } diff --git a/fs/real.c b/fs/real.c index a842f0e3..4b8dd744 100644 --- a/fs/real.c +++ b/fs/real.c @@ -74,17 +74,21 @@ static int open_flags_fake_from_real(int flags) { return fake_flags; } -static struct fd *realfs_open(struct mount *mount, const char *path, int flags, int mode) { +struct fd *realfs_open_with_fdops(struct mount *mount, const char *path, int flags, int mode, const struct fd_ops *fdops) { int real_flags = open_flags_real_from_fake(flags); int fd_no = openat(mount->root_fd, fix_path(path), real_flags, mode); if (fd_no < 0) return ERR_PTR(errno_map()); - struct fd *fd = fd_create(&realfs_fdops); + struct fd *fd = fd_create(fdops); fd->real_fd = fd_no; fd->dir = NULL; return fd; } +struct fd *realfs_open(struct mount *mount, const char *path, int flags, int mode) { + return realfs_open_with_fdops(mount, path, flags, mode, &realfs_fdops); +} + int realfs_close(struct fd *fd) { if (fd->dir != NULL) closedir(fd->dir); @@ -119,7 +123,7 @@ static void copy_stat(struct statbuf *fake_stat, struct stat *real_stat) { #undef TIMESPEC } -static int realfs_stat(struct mount *mount, const char *path, struct statbuf *fake_stat) { +int realfs_stat(struct mount *mount, const char *path, struct statbuf *fake_stat) { struct stat real_stat; if (fstatat(mount->root_fd, fix_path(path), &real_stat, AT_SYMLINK_NOFOLLOW) < 0) return errno_map(); @@ -127,7 +131,7 @@ static int realfs_stat(struct mount *mount, const char *path, struct statbuf *fa return 0; } -static int realfs_fstat(struct fd *fd, struct statbuf *fake_stat) { +int realfs_fstat(struct fd *fd, struct statbuf *fake_stat) { struct stat real_stat; if (fstat(fd->real_fd, &real_stat) < 0) return errno_map(); @@ -163,7 +167,7 @@ ssize_t realfs_pwrite(struct fd *fd, const void *buf, size_t bufsize, off_t off) return res; } -static void realfs_opendir(struct fd *fd) { +void realfs_opendir(struct fd *fd) { if (fd->dir == NULL) { int dirfd = dup(fd->real_fd); fd->dir = fdopendir(dirfd); @@ -265,7 +269,7 @@ int realfs_mmap(struct fd *fd, struct mem *mem, page_t start, pages_t pages, off return pt_map(mem, start, pages, memory, correction, prot); } -static ssize_t realfs_readlink(struct mount *mount, const char *path, char *buf, size_t bufsize) { +ssize_t realfs_readlink(struct mount *mount, const char *path, char *buf, size_t bufsize) { ssize_t size = readlinkat(mount->root_fd, fix_path(path), buf, bufsize); if (size < 0) return errno_map(); @@ -283,42 +287,42 @@ int realfs_getpath(struct fd *fd, char *buf) { return 0; } -static int realfs_link(struct mount *mount, const char *src, const char *dst) { +int realfs_link(struct mount *mount, const char *src, const char *dst) { int res = linkat(mount->root_fd, fix_path(src), mount->root_fd, fix_path(dst), 0); if (res < 0) return errno_map(); return res; } -static int realfs_unlink(struct mount *mount, const char *path) { +int realfs_unlink(struct mount *mount, const char *path) { int res = unlinkat(mount->root_fd, fix_path(path), 0); if (res < 0) return errno_map(); return res; } -static int realfs_rmdir(struct mount *mount, const char *path) { +int realfs_rmdir(struct mount *mount, const char *path) { int err = unlinkat(mount->root_fd, fix_path(path), AT_REMOVEDIR); if (err < 0) return errno_map(); return 0; } -static int realfs_rename(struct mount *mount, const char *src, const char *dst) { +int realfs_rename(struct mount *mount, const char *src, const char *dst) { int err = renameat(mount->root_fd, fix_path(src), mount->root_fd, fix_path(dst)); if (err < 0) return errno_map(); return err; } -static int realfs_symlink(struct mount *mount, const char *target, const char *link) { +int realfs_symlink(struct mount *mount, const char *target, const char *link) { int err = symlinkat(target, mount->root_fd, link); if (err < 0) return errno_map(); return err; } -static int realfs_mknod(struct mount *mount, const char *path, mode_t_ mode, dev_t_ UNUSED(dev)) { +int realfs_mknod(struct mount *mount, const char *path, mode_t_ mode, dev_t_ UNUSED(dev)) { int err; if (S_ISFIFO(mode)) { lock_fchdir(mount->root_fd); @@ -347,7 +351,7 @@ int realfs_truncate(struct mount *mount, const char *path, off_t_ size) { return err; } -static int realfs_setattr(struct mount *mount, const char *path, struct attr attr) { +int realfs_setattr(struct mount *mount, const char *path, struct attr attr) { path = fix_path(path); int root = mount->root_fd; int err; @@ -371,7 +375,7 @@ static int realfs_setattr(struct mount *mount, const char *path, struct attr att return err; } -static int realfs_fsetattr(struct fd *fd, struct attr attr) { +int realfs_fsetattr(struct fd *fd, struct attr attr) { int real_fd = fd->real_fd; int err; switch (attr.type) { @@ -401,7 +405,7 @@ int realfs_utime(struct mount *mount, const char *path, struct timespec atime, s return 0; } -static int realfs_mkdir(struct mount *mount, const char *path, mode_t_ mode) { +int realfs_mkdir(struct mount *mount, const char *path, mode_t_ mode) { int err = mkdirat(mount->root_fd, fix_path(path), mode); if (err < 0) return errno_map(); diff --git a/iSH.xcodeproj/project.pbxproj b/iSH.xcodeproj/project.pbxproj index 3ce80f43..67ea4cb8 100644 --- a/iSH.xcodeproj/project.pbxproj +++ b/iSH.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 40616E3C236642B6008CDF19 /* mount.c in Sources */ = {isa = PBXBuildFile; fileRef = 40616E3B236642B5008CDF19 /* mount.c */; }; + 408A263A236440F8008A4E81 /* iOSFS.m in Sources */ = {isa = PBXBuildFile; fileRef = 408A2639236440F8008A4E81 /* iOSFS.m */; }; 650B337422EA235C00B4C03E /* PasteboardDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 650B337322EA235C00B4C03E /* PasteboardDevice.m */; }; 8632A7BF219A59FB00F02325 /* UserPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 8632A7BE219A59FB00F02325 /* UserPreferences.m */; }; 9A28E4EA219A8B670073D200 /* AboutAppearanceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A28E4E9219A8B670073D200 /* AboutAppearanceViewController.m */; }; @@ -99,6 +101,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 40616E3B236642B5008CDF19 /* mount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mount.c; sourceTree = ""; }; + 408A2639236440F8008A4E81 /* iOSFS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iOSFS.m; sourceTree = ""; }; + 408A263B23644102008A4E81 /* iOSFS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iOSFS.h; sourceTree = ""; }; 650B335A22E9E46A00B4C03E /* mem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mem.c; sourceTree = ""; tabWidth = 4; }; 650B335B22E9E46A00B4C03E /* mem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem.h; sourceTree = ""; tabWidth = 4; }; 650B335D22E9EF9B00B4C03E /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = ""; }; @@ -440,6 +445,8 @@ BB792B561F96D90D00FFB7A4 /* TerminalViewController.h */, BB792B571F96D90D00FFB7A4 /* TerminalViewController.m */, BBBF7B5B2415CDBB00EC4C14 /* Settings.bundle */, + 408A263B23644102008A4E81 /* iOSFS.h */, + 408A2639236440F8008A4E81 /* iOSFS.m */, BBFB557D21587B2B00DFE6DE /* Bar */, BB78AB291FAD22440013E782 /* TerminalView.h */, BB78AB2A1FAD22440013E782 /* TerminalView.m */, @@ -989,6 +996,7 @@ 9A28E4EA219A8B670073D200 /* AboutAppearanceViewController.m in Sources */, BB1D9D93234A8FE100F364E8 /* AboutNavigationController.m in Sources */, BB235534235D488500139E00 /* LocationDevice.m in Sources */, + 40616E3C236642B6008CDF19 /* mount.c in Sources */, BB792B581F96D90D00FFB7A4 /* TerminalViewController.m in Sources */, BB78AB2B1FAD22440013E782 /* TerminalView.m in Sources */, BB23F58D231E1D1400585522 /* ScrollbarView.m in Sources */, @@ -1006,6 +1014,7 @@ BBFB5579215876CD00DFE6DE /* AboutViewController.m in Sources */, 650B337422EA235C00B4C03E /* PasteboardDevice.m in Sources */, BBFB557121586C4800DFE6DE /* UIViewController+Back.m in Sources */, + 408A263A236440F8008A4E81 /* iOSFS.m in Sources */, BBFB558021587B6800DFE6DE /* ArrowBarButton.m in Sources */, BB792B551F96D90D00FFB7A4 /* AppDelegate.m in Sources */, ); diff --git a/kernel/fs.h b/kernel/fs.h index 32bb2b11..525860bd 100644 --- a/kernel/fs.h +++ b/kernel/fs.h @@ -108,6 +108,7 @@ void mount_release(struct mount *mount); // must hold mounts_lock while calling these, or traversing mounts int do_mount(const struct fs_ops *fs, const char *source, const char *point, int flags); +int do_mount_with_data(const struct fs_ops *fs, const char *source, const char *point, int flags, void *data); int do_umount(const char *point); int mount_remove(struct mount *mount); extern struct list mounts; @@ -178,6 +179,25 @@ const char *fix_path(const char *path); // TODO reconsider // real fs extern const struct fd_ops realfs_fdops; +struct fd *realfs_open_with_fdops(struct mount *mount, const char *path, int flags, int mode, const struct fd_ops *fdops); +struct fd *realfs_open(struct mount *mount, const char *path, int flags, int mode); + +ssize_t realfs_readlink(struct mount *mount, const char *path, char *buf, size_t bufsize); +int realfs_link(struct mount *mount, const char *src, const char *dst); +int realfs_unlink(struct mount *mount, const char *path); +int realfs_rmdir(struct mount *mount, const char *path); +int realfs_rename(struct mount *mount, const char *src, const char *dst); +int realfs_symlink(struct mount *mount, const char *target, const char *link); +int realfs_mknod(struct mount *mount, const char *path, mode_t_ mode, dev_t_ UNUSED(dev)); + +int realfs_stat(struct mount *mount, const char *path, struct statbuf *fake_stat); +int realfs_statfs(struct mount *mount, struct statfsbuf *stat); +int realfs_fstat(struct fd *fd, struct statbuf *fake_stat); +int realfs_setattr(struct mount *mount, const char *path, struct attr attr); +int realfs_fsetattr(struct fd *fd, struct attr attr); + +int realfs_mkdir(struct mount *mount, const char *path, mode_t_ mode); + int realfs_truncate(struct mount *mount, const char *path, off_t_ size); int realfs_utime(struct mount *mount, const char *path, struct timespec atime, struct timespec mtime); @@ -186,7 +206,16 @@ int realfs_flock(struct fd *fd, int operation); int realfs_getpath(struct fd *fd, char *buf); ssize_t realfs_read(struct fd *fd, void *buf, size_t bufsize); ssize_t realfs_write(struct fd *fd, const void *buf, size_t bufsize); + +int realfs_readdir(struct fd *fd, struct dir_entry *entry); +unsigned long realfs_telldir(struct fd *fd); +void realfs_seekdir(struct fd *fd, unsigned long ptr); + +off_t realfs_lseek(struct fd *fd, off_t offset, int whence); + int realfs_poll(struct fd *fd); +int realfs_mmap(struct fd *fd, struct mem *mem, page_t start, pages_t pages, off_t offset, int prot, int flags); +int realfs_fsync(struct fd *fd); int realfs_getflags(struct fd *fd); int realfs_setflags(struct fd *fd, dword_t arg); ssize_t realfs_ioctl_size(int cmd); @@ -203,4 +232,8 @@ extern const struct fs_ops fakefs; extern const struct fs_ops devptsfs; extern const struct fs_ops tmpfs; +extern const struct fs_ops *filesystems[]; +#define IOS_FILESYSTEM_ID 3 +#define IOS_UNSAFE_FILESYSTEM_ID 4 + #endif