mirror of
https://github.com/ish-app/ish.git
synced 2026-05-28 21:10:35 +00:00
Add support for mounting folders from iOS
This commit is contained in:
committed by
Theodore Dubois
parent
c1ab200b20
commit
68340acd03
+7
-2
@@ -10,11 +10,13 @@
|
||||
#include <netdb.h>
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
#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;
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "TerminalViewController.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
extern TerminalViewController *currentTerminalViewController;
|
||||
|
||||
API_AVAILABLE(ios(13))
|
||||
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
|
||||
|
||||
|
||||
+15
-1
@@ -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
|
||||
|
||||
@@ -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;
|
||||
+449
@@ -0,0 +1,449 @@
|
||||
//
|
||||
// iOSFS.m
|
||||
// iSH
|
||||
//
|
||||
// Created by Noah Peeters on 26.10.19.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#include <sys/stat.h>
|
||||
#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 <UIDocumentPickerDelegate>
|
||||
|
||||
@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<NSURL *> *)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,
|
||||
};
|
||||
+4
-2
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 = "<group>"; };
|
||||
408A2639236440F8008A4E81 /* iOSFS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iOSFS.m; sourceTree = "<group>"; };
|
||||
408A263B23644102008A4E81 /* iOSFS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iOSFS.h; sourceTree = "<group>"; };
|
||||
650B335A22E9E46A00B4C03E /* mem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mem.c; sourceTree = "<group>"; tabWidth = 4; };
|
||||
650B335B22E9E46A00B4C03E /* mem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem.h; sourceTree = "<group>"; tabWidth = 4; };
|
||||
650B335D22E9EF9B00B4C03E /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = "<group>"; };
|
||||
@@ -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 */,
|
||||
);
|
||||
|
||||
+33
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user