Android: add support for content:// directory traversal#15691
Open
crudelios wants to merge 5 commits into
Open
Android: add support for content:// directory traversal#15691crudelios wants to merge 5 commits into
content:// directory traversal#15691crudelios wants to merge 5 commits into
Conversation
Contributor
Author
|
Regarding the cache, here's the approximate result of a full recursive directory traversal (with
So it's quite a big difference. Edit: Some more numbers: The "Before caching" above wasn't entirely correct, as some retrievals were being cached during the initial enumeration. Here are the most recent results:
The difference is even more dramatic than I expected. |
- Cached custom URI fetches are about ~35% faster - About ~40% less memory usage for cache - about 600KB on the example above - Cached real URI's - I feel the speedup difference (more than 100x) is too dramatic to ignore - Improve `openFileDescriptor` support to better comply with SDL's `mode` parameter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds support for traversal of
content://directories on Android, as well as gettingSDL_PathInfooncontent://files.Description
In order to allow proper traversal of directories and keeping platform compatibility, I had to come up with some changes for the way SDL handles URI's obtained from the "folder select dialog" on Android,
The problem
A normal use case for file access on games is for users to set a base path (such as the install path), then get subfolders and files from that path.
So, if the basepath is something like:
The library user tends to append the subfile to that. Example: appending
/mysubfolder/myfile.txtto the base path ofC:\Programs\MyGame, which results inC:\Programs\MyGame/mysubfolder/myfile.txt.This works fine on most platforms, but not on Android with
content://URIs.Android
content://URIs are part of the Storage Access Framework (or SAF), and may reference a tree (a root path), a document within a tree or an individual document. Either way, due to the way the directory is structured, simply appending/mysubfolder/myfile.txtto acontent://URI will not work. Worse yet, it will appear to work but will point to a completely unrelated document, such as the root directory of the tree (i.e. the folder selected from the dialog).An example of a tree URI (user selected
<external storage>/folder/subfolderfrom the "folder select" dialog).Appending
/mysubfolder/myfile.txtto this URI results in:Such an URI will actually still point to the
<external storage>/folder/subfolderdirectory and not to the selected file!To get the file, the user would either need to:
For reference, a proper document URI for the
musubfolder/myfile.txtusing the above tree URI would be:This is very error-prone and Android-specific, demanding
#ifdefsfor Android in the user code. Worse yet, the URI syntax may change in the future, rendering the user's code unusable.My solution
I wanted to create a solution that was:
content://URIs.What I came up with was to change the URI provided by
SDL_ShowOpenFolderDialogon Android.WIth this PR, SDL appends a fragment separator (an
#) to the end of the provided URI. This will be ignored by Android (so the user can directly use the provided URI) but will be picked up by SDL's functions. Similarly,content://URI's without#are still compatible with SDL - as long as they point to a valid file.Whathever comes after the
#on the URI will be treated by SDL as the subpath inside the directory provided by the tree URI.So in our example above, if the user wanted to access
mysubfolder/myfile.txt, he really would only need to append that to the URI, as such:SDL will properly navigate the provided path tree and find the file requested by the user, obtaining the correct URIs that are provided by the SAF API.
Additionally, since SAF traversal is slow, the provided results are cached in memory so subsequent accesses are much faster.
In order to allow proper original
content://directory enumerations, I've also added functions that convert tree URI's to document URI's, ending with a proper path separator (a%2F), in order to comply with thedirnamespecification of theSDL_EnumerateDirectoryCallback- in other words, even with originalcontent://URI's, chances are that if you appendfnametodirnamewhen enumerating acontent://directory and request info about the file, it will still work.While I've decided to cache the SDL specific URI's, I've decided against that on originalcontent://URI's. The reason being that if the user is providing a cleancontent://URI, he likely knows what he's doing and doesn't need SDL in the way.Edit: I've decided to cache real URI's as well. I feel the performance difference is too high to just ignore. Due to the different way real URI's are cached, cached fetches for URI's are about 3x slower than for SDL provided URI's - however, they're still orders of magnitude faster than direct SAF lookups.
Conclusion
I'm sorry for the very long PR description, but I felt the need to explain the underlying issue and my solution.
I've tested most of the code and couldn't find any more bugs, but there still may be some bugs lurking. Hopefully there aren't though.
Also, if this ends up being merged, I plan to add support to
SDL_CopyFile,SDL_CreateDirectory,SDL_RemovePathandSDL_RenamePath.Existing Issue(s)
Fixes #15541.