ohmu
·
2026-10-15
1#include "common/android/package.h"
2#include "common/android/api.h"
3#include "common/debug.h"
4#include "common/strutil.h"
5
6#include <string.h>
7#include <unistd.h>
8
9// There is no way for a process to ask for its own package name: it is not in /proc/self/status, and
10// an app cannot list /data/data. The executable path carries it instead -- an app's binaries live
11// under /data/data/<package>/ or /data/user/<user>/<package>/, and /proc/self/exe resolves there.
12// Under Termux that is /data/data/com.termux/files/usr/bin/<binary>, whose third component is the
13// package.
14//
15// The memory cgroup carries the same information (4:memory:/apps/com.termux on the device this was
16// verified on), but the unified hierarchy spells it out as /apps/uid_10478/pid_26943 with no name
17// left in it, so the executable is the portable half of the two.
18bool ffAndroidGetOwnPackage(char* buffer, size_t capacity) {
19 char path[4096];
20 const ssize_t length = readlink("/proc/self/exe", path, sizeof(path) - 1);
21 if (length <= 0) {
22 FF_DEBUG("Cannot read /proc/self/exe, so the calling package cannot be derived");
23 return false;
24 }
25 path[length] = '\0';
26
27 const char* rest = nullptr;
28 const char* const dataPrefix = "/data/data/";
29 const char* const userPrefix = "/data/user/";
30 if (ffStrStartsWith(path, dataPrefix)) {
31 rest = path + strlen(dataPrefix);
32 } else if (ffStrStartsWith(path, userPrefix)) {
33 // /data/user/<user>/<package>/... -- the user number has to be stepped over before the
34 // package name starts, and only strchr() answers where that is.
35 rest = strchr(path + strlen(userPrefix), '/');
36 if (rest != nullptr) {
37 rest += 1;
38 }
39 }
40
41 if (rest == nullptr) {
42 const uint32_t uid = instance.state.platform.uid;
43 FF_DEBUG("The executable is not in an app data directory (\"%s\"), uid %u", path, uid);
44 if (uid != FF_ANDROID_PRIVILEGED_UID_SHELL) {
45 return false;
46 }
47 static const char shellPackage[] = FF_ANDROID_SHELL_PACKAGE;
48 if (sizeof(shellPackage) > capacity) {
49 return false;
50 }
51 memcpy(buffer, shellPackage, sizeof(shellPackage));
52 FF_DEBUG("The calling package is \"%s\" (the shell owns it)", buffer);
53 return true;
54 }
55
56 const char* end = strchr(rest, '/');
57 const size_t nameLength = end != nullptr ? (size_t) (end - rest) : strlen(rest);
58 if (nameLength == 0 || nameLength >= capacity) {
59 return false;
60 }
61 memcpy(buffer, rest, nameLength);
62 buffer[nameLength] = '\0';
63 FF_DEBUG("The calling package is \"%s\"", buffer);
64 return true;
65}