-
Notifications
You must be signed in to change notification settings - Fork 17
Description
Hello, in termux-pacman, which is a port of the package manager pacman to the distro Android, there is a pacutils package available from pacman -S pacutils, which on some Android devices works, but unfortunately on most Android devices does not work and crashes immediately when commands like pacfile are used.
After debugging the problem for some time, I have determined that the root cause is that this software attempts to use open("/", O_DIRECTORY), here:
pacutils/ext/globdir.c/globdir.c
Line 237 in d3998fe
| fd = open("/", O_DIRECTORY); |
which does not work and derails pacutils into lots of errors and crashes (beginning with a Segmentation fault and turning into other errors like "Permission denied" and "No such file or directory" if the undefined behavior is naively prevented), because most Android devices do not permit access to the actual / absolute path folder without root, but pacutils is currently designed only for distros where direct access to the actual / folder is permitted.
It is theoretically possible to remove the requirement for root access on Android from software which previously called open("/", O_RDONLY) or open("/", O_DIRECTORY), however, that can unfortunately be extremely difficult, because every software varies greatly in its behavior. For one example, this was done to the software capnproto, here:
However, unfortunately, just changing pacutils' instance of open(dir, O_DIRECTORY) to open(dir, O_PATH | O_DIRECTORY) in an attempt to mimic what was done to capnproto results in this error instead:
error: reading '/data/data/com.termux/files/usr/etc/pacman.conf' failed (Bad file descriptor)
error: could not parse '/data/data/com.termux/files/usr/etc/pacman.conf'
Also, unfortunately, just replacing all of the instances of sysroot = NULL; with sysroot = "/data/data/com.termux/files/usr"; in the source code of pacutils and setting SYSCONFDIR to /etc so that it is handled as a path relative to /data/data/com.termux/files/usr is not sufficient to completely resolve all problems, because if that is done, then pacutils starts parsing the /data/data/com.termux/files/usr/etc/pacman.conf, but as soon as it encounters the entry /data/data/com.termux/files/usr/etc/pacman.d/serverlist, it derails again because pacutils assumes that entries within the pacman.conf itself would also be relative to the sysroot, not absolute paths, so it looks for /data/data/com.termux/files/usr/data/data/com.termux/files/usr/etc/pacman.d/serverlist, which does not exist, and prints this sort of error:
error: reading '/data/data/com.termux/files/usr/etc/pacman.conf' failed (No such file or directory)
error: could not parse '/data/data/com.termux/files/usr/etc/pacman.conf'
This is what termux-pacman's /data/data/com.termux/files/usr/etc/pacman.conf file contents look like, which are all currently handled correctly by termux-pacman's build of pacman, so cannot be modified, and if pacutils is to work with termux-pacman, pacutils must unfortunately be adapted to handle this file as termux-pacman's pacman does.
#
# /data/data/com.termux/files/usr/etc/pacman.conf
#
# See the pacman.conf(5) manpage for option and repository directives
#
# GENERAL OPTIONS
#
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
#RootDir = /
#DBPath = /data/data/com.termux/files/usr/var/lib/pacman/
#CacheDir = /data/data/com.termux/files/usr/var/cache/pacman/pkg/
#LogFile = /data/data/com.termux/files/usr/var/log/pacman.log
#GPGDir = /data/data/com.termux/files/usr/etc/pacman.d/gnupg/
#HookDir = /data/data/com.termux/files/usr/etc/pacman.d/hooks/
HoldPkg = pacman
#XferCommand = /data/data/com.termux/files/usr/bin/curl -L -C - -f -o %o %u
#XferCommand = /data/data/com.termux/files/usr/bin/wget --passive-ftp -c -O %o %u
#CleanMethod = KeepInstalled
Architecture = aarch64
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg =
#IgnoreGroup =
#NoUpgrade =
#NoExtract =
# Misc options
#UseSyslog
Color
#NoProgressBar
CheckSpace
#VerbosePkgLists
ParallelDownloads = 5
#DownloadUser = alpm
#DisableSandbox
# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = DatabaseRequired
LocalFileSigLevel = Optional
#RemoteFileSigLevel = Required
#
# REPOSITORIES
# - can be defined here or included from another file
# - pacman will search repositories in the order defined here
# - local/custom mirrors can be added here or in separate files
# - repositories listed first will take precedence when packages
# have identical names, regardless of version number
# - URLs will have $repo replaced by the name of the current repo
# - URLs will have $arch replaced by the name of the architecture
#
# Repository entries are of the format:
# [repo-name]
# Server = ServerName
# Include = IncludePath
#
# The header [repo-name] is crucial - it must be present and
# uncommented to enable the repo.
#
[main]
Include = /data/data/com.termux/files/usr/etc/pacman.d/serverlist
[x11]
Include = /data/data/com.termux/files/usr/etc/pacman.d/serverlist
[root]
Include = /data/data/com.termux/files/usr/etc/pacman.d/serverlist
[tur]
Include = /data/data/com.termux/files/usr/etc/pacman.d/serverlist
[tur-continuous]
Include = /data/data/com.termux/files/usr/etc/pacman.d/serverlist
[tur-multilib]
Include = /data/data/com.termux/files/usr/etc/pacman.d/serverlist
[gpkg]
Include = /data/data/com.termux/files/usr/etc/pacman.d/serverlist
The highest absolute directory path that can be safely assumed to have read access in Android is /data/data/com.termux (where com.termux is the name of the app in which the software is running, which is a variable but can be safely hardcoded during testing and development because it is easy to dynamically replace at build-time)