mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 19:41:10 +00:00
Fast path: hold every bind, so added games start in their own folder (#343)
* Fast path: hold every bind, so added games start in their own folder
libblfastpath kept the first 64 binds and dropped the rest without a word. A session has 87 (two
Games folders are the last two), so /root/Games/<folder>/... was mapped into the rootfs - the
empty mount point - instead of the bound storage. Wine resolves a new process's working directory
by those paths, found no drive for it and started every added game in C:\windows ("could not
find DOS drive for current working directory"): DiRT 3 did not mind, FEZ looks for
Content\Essentials.pak there and quits.
The library now holds 256, and turns itself off for the process when a bind does not fit or the
list runs past that, leaving the call to proot, which never maps it wrong. The app keeps the fast
path off for a session with more binds than that.
Verified on an AYANEO Pocket FIT: FEZ (added game) reaches its title screen; the warning is gone.
* Fast path: say in the session log when it stays off
---------
Co-authored-by: The412Banner <the412banner@users.noreply.github.com>
This commit is contained in:
1 parent
9fe5f29f64
commit
dba632ea14
4 files changed
+39
-4
No files matched your search
@@ -21,13 +21,15 @@ import java.security.MessageDigest
|
||||
*/
|
||||
object ProotFastPath {
|
||||
const val LIBRARY = "/usr/local/lib/libblfastpath.so"
|
||||
/** MAX_BINDS in fastpath.c: past it the library turns itself off, so the session keeps it off. */
|
||||
const val MAX_BINDS = 256
|
||||
|
||||
fun enabled(context: Context): Boolean =
|
||||
SessionPrefs.prootFastPath(context) && !SessionPrefs.prootNoSeccomp(context)
|
||||
|
||||
/** The key for this rootfs and these binds, or null when the library cannot be told them. */
|
||||
fun key(root: File, binds: List<String>): String? {
|
||||
if (binds.any { it.contains('|') } || root.path.contains('|')) return null
|
||||
if (binds.size > MAX_BINDS || binds.any { it.contains('|') } || root.path.contains('|')) return null
|
||||
val digest = MessageDigest.getInstance("SHA-256")
|
||||
.digest((root.path + "\n" + binds.joinToString("\n")).toByteArray())
|
||||
return digest.take(12).joinToString("") { "%02x".format(it) }
|
||||
|
||||
@@ -416,6 +416,9 @@ class SessionService : Service() {
|
||||
guest.addAll(fastPathAt, env)
|
||||
shellGuest.addAll(fastPathAt, env)
|
||||
Log.i(TAG, "proot: fast path on (${prootBinds.size} binds)")
|
||||
} ?: run {
|
||||
Log.w(TAG, "proot: fast path off - ${prootBinds.size} binds (it holds ${ProotFastPath.MAX_BINDS}) or a path it cannot be told")
|
||||
null
|
||||
}
|
||||
} else null
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.droiddeck.launcher.runtime
|
||||
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
class ProotFastPathTest {
|
||||
private val root = File("/data/data/com.droiddeck.launcher/files/linuxfs")
|
||||
|
||||
@Test fun aSessionsUsualBindsGetAKey() {
|
||||
// 87 on a device with two Games folders: past the old limit of 64, which dropped them.
|
||||
val binds = (1..87).map { "/host/$it:/guest/$it" }
|
||||
assertNotNull(ProotFastPath.key(root, binds))
|
||||
}
|
||||
|
||||
@Test fun moreBindsThanTheLibraryHoldsLeaveItOff() {
|
||||
val binds = (1..ProotFastPath.MAX_BINDS + 1).map { "/host/$it:/guest/$it" }
|
||||
assertNull(ProotFastPath.key(root, binds))
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,10 @@
|
||||
|
||||
#define FP_STUB_ADDR 0xffff00000UL /* must match FASTPATH_STUB_ADDR in proot's seccomp.c */
|
||||
#define FP_STUB_SIZE 4096UL
|
||||
#define MAX_BINDS 64
|
||||
/* A session binds 80-odd paths (devices, the Steam libraries, each Games folder...). More than fit,
|
||||
* or one that cannot be held, turns the fast path off: a bind it did not know would map that
|
||||
* guest path into the rootfs instead (an empty mount point), which proot never does. */
|
||||
#define MAX_BINDS 256
|
||||
#define FP_SLOW (-100000L)
|
||||
|
||||
typedef long (*stub_fn)(long nr, long a, long b, long c, long d, long e, long f);
|
||||
@@ -162,7 +165,9 @@ static void fp_init(void) {
|
||||
snprintf(root, sizeof root, "%s", r);
|
||||
canonical(root, sizeof root);
|
||||
rootlen = strlen(root);
|
||||
for (const char *s = b; s && *s && nbinds < MAX_BINDS;) {
|
||||
const char *s = b;
|
||||
int unheld = 0;
|
||||
for (; s && *s && nbinds < MAX_BINDS;) {
|
||||
const char *end = strchr(s, '|');
|
||||
size_t len = end ? (size_t)(end - s) : strlen(s);
|
||||
char spec[2 * PATH_MAX];
|
||||
@@ -176,7 +181,7 @@ static void fp_init(void) {
|
||||
* Static storage: malloc here would grow the heap with brk(2), which proot traps. */
|
||||
static char hosts[MAX_BINDS][PATH_MAX], guests[MAX_BINDS][512];
|
||||
const char *g = colon ? colon + 1 : spec;
|
||||
if (strlen(g) >= sizeof guests[0]) { s = end ? end + 1 : NULL; continue; }
|
||||
if (strlen(g) >= sizeof guests[0]) { unheld = 1; break; }
|
||||
bd->host = hosts[nbinds];
|
||||
bd->guest = guests[nbinds];
|
||||
snprintf(bd->guest, sizeof guests[0], "%s", g);
|
||||
@@ -184,9 +189,13 @@ static void fp_init(void) {
|
||||
bd->hlen = strlen(bd->host);
|
||||
bd->glen = strlen(bd->guest);
|
||||
if (bd->guest[0] == '/' && bd->glen > 1 && bd->hlen > 0) nbinds++;
|
||||
} else if (len > 0) {
|
||||
unheld = 1;
|
||||
break;
|
||||
}
|
||||
s = end ? end + 1 : NULL;
|
||||
}
|
||||
if (unheld || (s && *s)) { fp_sys = NULL; return; }
|
||||
pthread_atfork(NULL, NULL, after_fork); /* registered once per exec */
|
||||
fp_on = 1;
|
||||
if (getenv("PROOT_FP_STATS")) atexit(stats);
|
||||
|
||||
Reference in new issue
Block a user