Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for mounting folders from iOS #543

Closed
wants to merge 1 commit into from

Conversation

NoahPeeters
Copy link
Contributor

Adds a button to the bar to mount any folder from a FileProvider into ish as described in #230.

Not all FileProvider support giving read/write access to a folder. Those aren't available.

Working FileProviders:

  • On My iPad/iPhone
  • iCloud Drive
  • Working Copy
  • SMB servers

FileProviders which do not work

  • GoogleDrive
  • ish itself
  • OneDrive

@tbodt
Copy link
Member

tbodt commented Oct 26, 2019

Thanks! There are a few things missing, such as file coordination.

return fs;
}

const struct fs_ops *externalfs = nil;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you create this statically to avoid having to call something to create it?

NSURL *url = urlForMount(mount);
if ([url startAccessingSecurityScopedResource] == NO) {
CFBridgingRelease(mount->data);
return errno_map();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

startAccessingSecurityScopedResource doesn't set errno so this will return garbage

fs/mount.c Outdated
@@ -37,15 +37,15 @@ void mount_release(struct mount *mount) {
unlock(&mounts_lock);
}

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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're supposed to set mount->data after calling this, there shouldn't need to be a new function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My problem was (and still is) that do_mount calls fs->mount and at that point startAccessingSecurityScopedResource must be called. For that, I need the NSURL object.

[self presentViewController:picker animated:true completion:nil];
}

-(void)displayMountError {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should include some information on what the error is

@tbodt
Copy link
Member

tbodt commented Oct 26, 2019

Also I think a better idea for the UI is to open the UIDocumentPickerViewController code in the mount function. That way you type something like mount -t ios website /mnt/website and it pops up a file picker.

@NoahPeeters NoahPeeters force-pushed the mount_file_provider branch 2 times, most recently from 41e96e5 to 547e507 Compare October 27, 2019 23:25
@NoahPeeters
Copy link
Contributor Author

I've updated the pull request. Now, new directories can be mounted with the mount -t ... command.
I also included the NSFileCoordinator but it is currently not used for opening files as I ran into some problems. One simple example is creating a fifo with mkfifo. If one now tries to read it with cat and then pipe data into the fifo with echo, the echo command blocks because it requires write access and cat still has read access to the file.

@tbodt tbodt mentioned this pull request Oct 29, 2019
}

static int iosfs_mount_data(char source[MAX_PATH], char point[MAX_PATH], dword_t *flags, void **data) {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be moved into iosfs_mount? I think that would eliminate the need for a new do_mount_with_data.

@tbodt
Copy link
Member

tbodt commented Nov 3, 2019

File coordination was clearly not designed for fifos. I think it's reasonable to check what type the file is, and don't use file coordination on files where read/write can block.

@videoMonkey
Copy link

Would love to see this happen, is any progress being made? I wish my programming chops were at the level to be able to help.

@NoahPeeters
Copy link
Contributor Author

I had to do a lot for university lately. I will definitely continue working on this. Probably between Christmas and New Year or so. I already looked into it and it is not that hard to implement it.

@videoMonkey
Copy link

videoMonkey commented Dec 12, 2019 via email

@NoahPeeters NoahPeeters force-pushed the mount_file_provider branch 2 times, most recently from 8b178b3 to 52f30f8 Compare December 14, 2019 13:38
@NoahPeeters
Copy link
Contributor Author

I continued working on this. I added file coordination for regular files and removed the iosfs_mount_data function by calling the ui functions in iosfs_mount.

I did a lot of testing with git in a mounted folder from Working Copy. I noticed that git status can be quit slow even with mid-size repositories because git will check every file in the repository and each of the coordinator calls slows down the process. That's why I added a second filesystem: ios-unsafe. That one will simply make sure that the correct permissions for the security scope are requested but the filecoordinators are not used at all. In case of Working Copy, this works very well but there are probably apps which can have a problem with that (that's why I called in ios-UNSAFE).

Therefore, this pull request now adds the following two commands:

mount -t ios website /mnt/website
mount -t ios-unsafe website /mnt/website

Finally, someone with more experience in async programming in objective-c should have a look at the usage of mutexes in iosfs_open. It does work but I do not know if there is a better/more elegant way of doing this.

@tbodt
Copy link
Member

tbodt commented Dec 16, 2019

Nice! Will do a detailed review in a bit.

I'm torn on whether ios-unsafe is a good idea. For the specific case of Working Copy, it makes more sense to just do git operations directly in the Working Copy app.

@@ -548,6 +555,7 @@
650B335A22E9E46A00B4C03E /* mem.c */,
650B335B22E9E46A00B4C03E /* mem.h */,
BB101B512364EAF0000A93BC /* mount.c */,
40616E3B236642B5008CDF19 /* mount.c */,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be a duplicate

@@ -431,6 +436,8 @@
BBCC9D952365430800424C83 /* SceneDelegate.m */,
BB792B561F96D90D00FFB7A4 /* TerminalViewController.h */,
BB792B571F96D90D00FFB7A4 /* TerminalViewController.m */,
408A263B23644102008A4E81 /* iOSFS.h */,
408A2639236440F8008A4E81 /* iOSFS.m */,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you put these under Devices?

@@ -174,6 +175,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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point there should be a separate fs/real.h header.

@@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused, please remove

@@ -73,17 +73,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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a new function here, how about setting fd->ops after calling realfs_open?

}

const struct fs_ops iosfs = {
.name = "ios", .magic = 0x7265616d,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you choose more meaningful magic values? 0x7265616c is used for realfs because it's "real" in ascii hex, so this means "ream". :)

@@ -196,4 +225,8 @@ extern const struct fs_ops procfs;
extern const struct fs_ops fakefs;
extern const struct fs_ops devptsfs;

extern const struct fs_ops *filesystems[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a function filesystem_register that appends a filesystem to the array makes more sense than static filesystem ids.


NS_ASSUME_NONNULL_BEGIN

extern TerminalViewController *currentTerminalViewController;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like this way of getting the view controller. My other ideas are way more annoying to implement though.

@interface DirectoryPickerDelegate : NSObject <UIDocumentPickerDelegate>

@property NSURL *url;
@property pthread_mutex_t *mutex;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Locks aren't really intended for waiting for something to happen. Should use a condition variable. cond_t from util/sync.h is preferred because it allows the process to be interrupted by a signal, with e.g. ctrl-c.

return combine_error(error, err);
}

static int iosfs_symlink(struct mount *mount, const char *target, const char *link) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot of repeated code in these functions. How much can be factored out into a new function that takes a block?

@tbodt
Copy link
Member

tbodt commented Jan 1, 2020

@NoahPeeters Do you plan to work on this soon? If not, I'm willing to pick it up and get it merged.

@tbodt
Copy link
Member

tbodt commented Feb 10, 2020

@NoahPeeters Ping

@MrAlexWeber
Copy link

+1 for this feature, replying to bump and watch

@tbodt
Copy link
Member

tbodt commented Apr 12, 2020

Gonna take this over

@tbodt
Copy link
Member

tbodt commented Apr 12, 2020

Merged in dbd4100.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants