IPadOS: Creating files on SMB share

files.appipadsmb

A new issue has cropped up for me—possibly since iPadOS 14 was released (last week as of this writing), but I’m not sure it hasn’t been around longer since it’s been some weeks since I last tried doing this and it worked. The issue is specifically with creating files on an SMB share.

My iPad’s Files sidebar has an SMB share (boringly called Shared and located on the Linux machine at ~/Shared) exported by Samba from an Ubuntu Linux workstation on my home network, the same network my iPad’s on.

It works for fine for editing files—meaning, if I open a file from an app supporting Files selection, or use the Files app itself to invoke an app using a long-press on a file in Shared, I can modify it, and those changes propagate to my Linux machine’s storage with no problem.

It also works for deleting files using the Files app, by long-holding on the file in Shared and selecting Delete Now.

The problem arises only when I try to create a new file. If I copy a file into it by what I think of as the “classic Windows method”—finding its original location, long-pressing to Copy, navigating to Shared and doing Paste, I get:
A cropped screenshot showing an error panel reading, “The operation couldn’t be completed. Operation canceled // Operation canceled // OK”

which is an error panel reading,

The operation couldn’t be completed. Operation canceled
Operation canceled
OK

The same happens if I try to move a file there by dragging it in.

If I try to save a file into Shared directly from an app’s export sheet, I get the same:
A fullscreen screenshot from the Export panel of Vectornator showing an error panel reading, “The operation couldn’t be completed. Operation canceled // Operation canceled // OK”

I have tried restarting the Linux machine and ejecting and remounting the SMB share on the iPad.

One additional possible clue: I thought perhaps doing touch ~/Shared/two-boxes.svg on Linux prior to attempting the creation might work, since editing existing files works. I did this and then tried to paste the two-boxes.svg file, and got the box warning me of overwriting the empty file:

A “Replace Existing Items?” dialog

which reads,

Replace Existing Items
The file “two-boxes” already exists in this location. Do you want to replace it with the one you’re copying?
Replace
Keep Both
Stop

Interestingly, if I select Replace, I get the same “Operation canceled” error, but then no two-boxes.svg file at all is left behind. On the other hand, if I select Keep Both, I get no error, but also nothing happens—the old file remains and no new file is created.

One final possible clue: if I go into Shared in the Files app and try to create a new directory, the Files app itself crashes immediately (I’m sent to the home screen and when I restart Files, it reinitializes its state). But oddly, even though it crashes, it worked: the directory is created and visible on Linux!

Best Answer

In reply to a comment from Marian Rainer-Harbach, I wanted to suggest an answer than I’m not 100% firm about, but does reflect my greater familiarity with iPadOS gained over the last eight months. I believe the answer to my question is a firm “no”: iOS and iPadOS apps (including the Files app) cannot create files on an external share except in very circumscribed cases.¹

The issue here is with app sandboxing:

Generally, apps are restricted to accessing files inside their own sandbox, meaning the files and directories they were installed with. Aside from temporary cache files, this is the only way apps can address files simply by name.

This is something I’ve learned from using apps like the Blink ssh/mosh shell, Pythonista, iVim, Termius, and other apps that can provide Unix shell-like access or other ways of specifying files by pathname. I’ve supplemented this learning-by-experience a bit with some research in the Apple Developer docs, but I don’t claim expertise here as an app developer.²

So: iPadOS apps can access files contained in their sandbox directory, like /private/var/mobile/Containers/Data/Application/$appID, or its subdirectories, by name (in read-write mode if they so choose), but outside that directory (in superfolders or siblings), they only have by-name access to securely-shared componentized resources (nearly always only in read-only mode), and they generally have no visibility at all into other apps’ sandboxes.

Yet iPadOS apps can, obviously, access files elsewhere in at least two circumstances:

  1. An iCloud Documents directory created for the app; and
  2. Files shared with the app via a Share sheet.

The iCloud directory is created by the app developer’s using CloudKit, and has a specific naming convention: in the Blink shell, for instance, the files I can find in the Files app under iCloud Drive → Blink are available in the Blink shell under the symbolic link ~/iCloud.

If I read that symlink, I can find:

blink> ls -l iCloud
lrwxr-xr-x  1 mobile  mobile  91 Mar 17 14:53 iCloud -> \
/private/var/mobile/Library/Mobile Documents\
/iCloud~com~carloscabanero~blinkshell/Documents

Thus, apps using CloudKit can “break out of their sandbox”, but only to the extent of reaching what amounts to a second iCloud sandbox, limited to only their own iCloud Documents data.

This is why, since the introduction of iPadOS (iOS > v13) and the Files app, some iPad apps sport a file-opening screen that looks very like the Files app; via the UIDocumentBrowserViewController interface, they give the user the ability to use a Finder-like interface for managing an app’s files.

However, as similar as they look (so similar, in, fact, that you could be forgiven for thinking it was simply Files being used as a helper app), there’s a key difference between this UIDocumentBrowserViewController interface and the Files app: when you tap iCloud Drive in the Files app, you find a directory listing all the various CloudKit-compatible apps you have installed, each as subdirectories you can navigate to. But when you tap iCloud Drive in an app using the UIDocumentBrowserViewController interface, you’re immediately taken to the iCloud Documents subdirectory for that app; you can’t “escape” and look at other apps’ iCloud documents.

Share sheets are the other way apps can potentially get access to files outside their sandbox. However, this is user-initiated (via a Share operation), and the file-like object the app receives is not accessible simply by pathname. You won’t find an app that includes a “Recents” list with files shared via Share sheet, because once an app has lost reference to a file object given it by handoff from the Share sheet, it no longer has a way to access it again (unlike files in its own sandbox, which it can access at any time by name).

Usually, that means the app being Shared to has no ability to create a file—that would be mucking with another app’s sandbox by name and isn’t allowed.

(There’s an exception for “bundles”—objects in macOS/iOS/iPadOS like apps that appear to be files, but are actually directories—on macOS you can right-click on an app in the Finder and choose to “Open bundle” to see this. When bundles are shared with appropriate permissions, the shared-to app may be able to create files inside the bundle.)³

While not fully answering all my questions, I think this background at least explains the issue: except for Shared bundles, apps simply can’t create files anywhere except inside their own sandbox. While the Files app—as a system utility—has greater access than other iPadOS/iOS apps to browse the file tree (including mounts of network drives), it still doesn’t have the write to create files outside its own sandbox by name, which is what would be required to allow the functionality I was asking about.

While app sandboxing exists in macOS—for all apps installed from the Store, and many other apps too, as Apple has pushed developers to implement app sandboxing in their macOS apps—it’s an ever-present security measure in iOS and iPadOS that, unlike on macOS, can’t be ignored by ordinary developers, not even with the coöperation of users (assuming they haven’t jailbroken their devices).

The Finder is a macOS app that isn’t subject to sandboxing rules. iPadOS’s Files app looks like Finder, so at its first introduction it was perhaps reasonable for users to expect it to work like Finder, too. But as an iOS/iPadOS app, even though it does have special access, Files still has to play by the rules—meaning no file creation in random places in the filesystem hierarchy.


¹ This discussion doesn’t really pertain to Secure Enclave storage, which has its own, entirely separate, set of requirements. But it should probably be obvious that the concepts of “Secure Enclave storage” and “network storage” can’t overlap!

² This is why I am posting this answer to my own question, but I’m not accepting it—perhaps commenters will have corrections or suggestions.

³ There’s also an exception when an app shares a subdirectory of its own with another app; in the Blink shell, for instance, you can use the command open to give, say, an editor access to text files inside a Blink documents subdirectory. But even in this case, this just allows the other app to open and export to files in the foreign directory; it doesn’t get full read-write access.