-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
327 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
on: | ||
push: | ||
pull_request: | ||
workflow_dispatch: | ||
jobs: | ||
build: | ||
name: Build and package | ||
runs-on: ubuntu-20.04 | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Build package | ||
uses: toltec-dev/build-action@v1 | ||
- name: Save packages | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: packages | ||
path: dist/rm*/*.ipk | ||
- name: Save repo | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: rmall | ||
path: dist/rmall | ||
test: | ||
name: Test package | ||
runs-on: ubuntu-latest | ||
needs: [build] | ||
steps: | ||
- uses: actions/download-artifact@v3 | ||
id: download | ||
with: | ||
name: rmall | ||
- uses: Eeems-Org/run-in-remarkable-action@v1 | ||
with: | ||
setup: | | ||
set -ex | ||
echo "src/gz local-rmall file:///opt/tmp/src" > /opt/etc/opkg.conf.d/16-local.conf | ||
run: | | ||
set -ex | ||
echo Y | toltecctl generate-opkg-conf | ||
opkg update | ||
opkg install sysfs_preload | ||
# Add steps here to test app | ||
opkg remove sysfs_preload | ||
path: ${{ steps.download.outputs.download-path }} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,3 +52,6 @@ compile_commands.json | |
*creator.user* | ||
|
||
*_qmlcache.qrc | ||
|
||
build/ | ||
dist/ |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[![rm1](https://img.shields.io/badge/rM1-supported-green)](https://remarkable.com/store/remarkable) | ||
[![rm2](https://img.shields.io/badge/rM2-supported-green)](https://remarkable.com/store/remarkable-2) | ||
[![opkg](https://img.shields.io/badge/OPKG-sysfs_preload-blue)](https://toltec-dev.org/) | ||
[![Discord](https://img.shields.io/discord/385916768696139794.svg?label=reMarkable&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/ATqQGfu) | ||
|
||
Sysfs Preload | ||
============= | ||
|
||
A simple preload that forces any calls to /sys/power/state to use systemd instead. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
#include <QMutex> | ||
#include <QString> | ||
#include <QVariant> | ||
|
||
#include <thread> | ||
#include <chrono> | ||
#include <filesystem> | ||
#include <dlfcn.h> | ||
#include <unistd.h> | ||
#include <dirent.h> | ||
#include <linux/fcntl.h> | ||
#include <sys/socket.h> | ||
#include <systemd/sd-journal.h> | ||
|
||
static int(*func_open)(const char*, int, mode_t) = nullptr; | ||
static QMutex logMutex; | ||
static std::thread stateThread; | ||
std::atomic<bool> stateThreadRunning = false; | ||
static int stateFds[2] = {-1, -1}; | ||
static QMutex stateMutex; | ||
|
||
// Use this instead of Oxide::getAppName to avoid recursion when logging in open() | ||
QString appName(){ | ||
static QString name; | ||
if(!name.isEmpty()){ | ||
return name; | ||
} | ||
if(func_open == nullptr){ | ||
return "liboxide_sysfs_preload.so"; | ||
} | ||
int fd = func_open("/proc/self/comm", O_RDONLY, 0); | ||
if(fd != -1){ | ||
FILE* f = fdopen(fd, "r"); | ||
fseek(f, 0, SEEK_END); | ||
size_t size = ftell(f); | ||
char* where = new char[size]; | ||
rewind(f); | ||
fread(where, sizeof(char), size, f); | ||
name = QString::fromLatin1(where, size); | ||
delete[] where; | ||
} | ||
if(!name.isEmpty()){ | ||
return name; | ||
} | ||
name = QString::fromStdString(std::filesystem::canonical("/proc/self/exe").string()); | ||
if(name.isEmpty()){ | ||
return "liboxide_sysfs_preload.so"; | ||
} | ||
return name; | ||
} | ||
|
||
template<class... Args> | ||
void __printf(char const* file, unsigned int line, char const* func, int priority, Args... args){ | ||
if(!qEnvironmentVariableIsSet("OXIDE_PRELOAD_DEBUG")){ | ||
return; | ||
} | ||
QStringList list; | ||
([&]{ list << QVariant(args).toString(); }(), ...); | ||
auto msg = list.join(' '); | ||
sd_journal_send( | ||
"MESSAGE=%s", msg.toStdString().c_str(), | ||
"PRIORITY=%i", priority, | ||
"CODE_FILE=%s", file, | ||
"CODE_LINE=%i", line, | ||
"CODE_FUNC=%s", func, | ||
"SYSLOG_IDENTIFIER=%s", appName().toStdString().c_str(), | ||
"SYSLOG_FACILITY=%s", "LOG_DAEMON", | ||
NULL | ||
); | ||
if(!isatty(fileno(stdin)) || !isatty(fileno(stdout)) || !isatty(fileno(stderr))){ | ||
return; | ||
} | ||
QMutexLocker locker(&logMutex); | ||
Q_UNUSED(locker) | ||
std::string level; | ||
switch(priority){ | ||
case LOG_INFO: | ||
level = "Info"; | ||
break; | ||
case LOG_WARNING: | ||
level = "Warning"; | ||
break; | ||
case LOG_CRIT: | ||
level = "Critical"; | ||
break; | ||
default: | ||
level = "Debug"; | ||
} | ||
fprintf( | ||
stderr, | ||
"[%i:%i:%i %s] %s: %s (%s:%u, %s)\n", | ||
getpgrp(), | ||
getpid(), | ||
gettid(), | ||
appName().toStdString().c_str(), | ||
level.c_str(), | ||
msg.toStdString().c_str(), | ||
file, | ||
line, | ||
func | ||
); | ||
} | ||
#define _PRINTF(priority, ...) __printf("shared/preload-sysfs/main.cpp", __LINE__, __PRETTY_FUNCTION__, priority, __VA_ARGS__) | ||
#define _DEBUG(...) _PRINTF(LOG_DEBUG, __VA_ARGS__) | ||
#define _WARN(...) _PRINTF(LOG_WARNING, __VA_ARGS__) | ||
#define _INFO(...) _PRINTF(LOG_INFO, __VA_ARGS__) | ||
#define _CRIT(...) _PRINTF(LOG_CRIT, __VA_ARGS__) | ||
|
||
void __thread_run(int fd){ | ||
char line[PIPE_BUF]; | ||
forever{ | ||
int res = read(fd, line, PIPE_BUF); | ||
if(res == -1){ | ||
if(errno == EINTR){ | ||
continue; | ||
} | ||
if(errno == EAGAIN || errno == EIO){ | ||
std::this_thread::sleep_for(std::chrono::seconds(1)); | ||
continue; | ||
} | ||
_WARN("/sys/power/state pipe failed to read:", strerror(errno)); | ||
_DEBUG("/sys/power/state pip fd:", fd); | ||
break; | ||
} | ||
if(res == 0){ | ||
continue; | ||
} | ||
auto data = QString::fromStdString(std::string(line, res)).trimmed(); | ||
if((QStringList() << "mem" << "freeze" << "standby").contains(data)){ | ||
_INFO("Suspending system due to", data, "request"); | ||
system("systemctl suspend"); | ||
}else{ | ||
_WARN("Unknown power state call:", data); | ||
} | ||
} | ||
stateThreadRunning = false; | ||
} | ||
|
||
int __open(const char* pathname, int flags){ | ||
if(strcmp(pathname, "/sys/power/state") != 0){ | ||
return -2; | ||
} | ||
stateMutex.lock(); | ||
if(stateFds[0] != -1){ | ||
if(!stateThreadRunning){ | ||
stateThread.join(); | ||
stateThreadRunning = true; | ||
stateThread = std::thread(__thread_run, stateFds[1]); | ||
} | ||
stateMutex.unlock(); | ||
_INFO("Getting /sys/power/state pipe"); | ||
return stateFds[0]; | ||
} | ||
_INFO("Opening /sys/power/state pipe"); | ||
int socketFlags = SOCK_STREAM; | ||
if((flags & O_NONBLOCK) || (flags & O_NDELAY)){ | ||
socketFlags |= SOCK_NONBLOCK; | ||
} | ||
if(socketpair(AF_UNIX, socketFlags, 0, stateFds) == 0){ | ||
stateThreadRunning = true; | ||
stateThread = std::thread(__thread_run, stateFds[1]); | ||
_INFO("/sys/power/state pipe opened"); | ||
}else{ | ||
_WARN("Unable to open /sys/power/state pipe:", strerror(errno)); | ||
} | ||
stateMutex.unlock(); | ||
return stateFds[0]; | ||
} | ||
|
||
extern "C" { | ||
__attribute__((visibility("default"))) | ||
int open64(const char* pathname, int flags, mode_t mode = 0){ | ||
static const auto func_open64 = (int(*)(const char*, int, mode_t))dlsym(RTLD_NEXT, "open64"); | ||
int fd = __open(pathname, flags); | ||
if(fd == -2){ | ||
fd = func_open64(pathname, flags, mode); | ||
} | ||
return fd; | ||
} | ||
|
||
__attribute__((visibility("default"))) | ||
int openat(int dirfd, const char* pathname, int flags, mode_t mode = 0){ | ||
static const auto func_openat = (int(*)(int, const char*, int, mode_t))dlsym(RTLD_NEXT, "openat"); | ||
int fd = __open(pathname, flags); | ||
if(fd == -2){ | ||
DIR* save = opendir("."); | ||
fchdir(dirfd); | ||
char path[PATH_MAX+1]; | ||
getcwd(path, PATH_MAX); | ||
fchdir(::dirfd(save)); | ||
closedir(save); | ||
fd = __open(QString("%1/%2").arg(path, pathname).toStdString().c_str(), flags); | ||
} | ||
if(fd == -2){ | ||
fd = func_openat(dirfd, pathname, flags, mode); | ||
} | ||
return fd; | ||
} | ||
|
||
__attribute__((visibility("default"))) | ||
int open(const char* pathname, int flags, mode_t mode = 0){ | ||
int fd = __open(pathname, flags); | ||
if(fd == -2){ | ||
fd = func_open(pathname, flags, mode); | ||
} | ||
return fd; | ||
} | ||
|
||
void __attribute__ ((constructor)) init(void); | ||
void init(void){ | ||
func_open = (int(*)(const char*, int, mode_t))dlsym(RTLD_NEXT, "open"); | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
pkgnames=(sysfs_preload) | ||
pkgdesc="A simple preload that forces any calls to /sys/power/state to use systemd instead." | ||
url=https://github.com/Eeems-Org/sysfs_preload | ||
pkgver=1.0.0-1 | ||
timestamp=2024-01-06T02:43Z | ||
section=util | ||
maintainer="Eeems <[email protected]>" | ||
license=MIT | ||
|
||
image=qt:v3.1 | ||
source=( | ||
main.cpp | ||
sysfs_preload.pro | ||
sysfs_preload.env | ||
) | ||
sha256sums=( | ||
SKIP | ||
SKIP | ||
SKIP | ||
) | ||
|
||
build() { | ||
find . -name "*.pro" -type f -print0 \ | ||
| xargs -r -0 sed -i 's/linux-oe-g++/linux-arm-remarkable-g++/g' | ||
qmake | ||
make -j$(nproc) | ||
INSTALL_ROOT="dist" make install | ||
} | ||
|
||
package() { | ||
cp -ar "${srcdir}/dist/." "${pkgdir}" | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export LD_PRELOAD="$LD_PRELOAD:/opt/lib/libsysfs_preload.so" |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
TARGET = sysfs_preload | ||
TEMPLATE = lib | ||
|
||
QMAKE_RPATHDIR += /lib /usr/lib /opt/lib /opt/usr/lib | ||
VERSION = 1.0 | ||
|
||
CONFIG += hide_symbols | ||
CONFIG += c++17 | ||
|
||
QT = core | ||
QT += network | ||
|
||
SOURCES += main.cpp | ||
|
||
LIBS += -lrt -ldl -Wl,--exclude-libs,ALL | ||
LIBS += -lsystemd | ||
|
||
target.path += /opt/lib | ||
INSTALLS += target | ||
|
||
xochitl_env.files = sysfs_preload.env | ||
xochitl_env.path = /opt/etc/xochitl.env.d/ | ||
INSTALLS += xochitl_env | ||
|
||
DEFINES += QT_MESSAGELOGCONTEXT |