Migrate to STL

This commit is contained in:
topjohnwu 2019-01-19 23:59:37 -05:00
parent 03c39e692a
commit 3e4c12cf56
23 changed files with 226 additions and 548 deletions

View File

@ -13,6 +13,8 @@
#include <dirent.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <vector>
#include <string>
#include "magisk.h"
#include "db.h"
@ -23,8 +25,10 @@
#include "selinux.h"
#include "flags.h"
using namespace std;
static char buf[PATH_MAX], buf2[PATH_MAX];
static Vector<CharArray> module_list;
static vector<string> module_list;
static bool seperate_vendor;
char *system_block, *vendor_block, *magiskloop;
@ -42,9 +46,9 @@ extern void auto_start_magiskhide();
#define IS_SKEL 0x04 /* mount from skeleton */
#define IS_MODULE 0x08 /* mount from module */
#define IS_DIR(n) (n->type == DT_DIR)
#define IS_LNK(n) (n->type == DT_LNK)
#define IS_REG(n) (n->type == DT_REG)
#define IS_DIR(n) ((n)->type == DT_DIR)
#define IS_LNK(n) ((n)->type == DT_LNK)
#define IS_REG(n) ((n)->type == DT_REG)
class node_entry {
public:
@ -56,15 +60,15 @@ public:
private:
const char *module; /* Only used when status & IS_MODULE */
const CharArray name;
const string name;
uint8_t type;
uint8_t status;
node_entry *parent;
Vector<node_entry *> children;
vector<node_entry *> children;
node_entry(const char *, const char *, uint8_t type);
bool is_root();
CharArray get_path();
string get_path();
node_entry *insert(node_entry *);
void clone_skeleton();
int get_path(char *path);
@ -87,7 +91,7 @@ bool node_entry::is_root() {
return parent == nullptr;
}
CharArray node_entry::get_path() {
string node_entry::get_path() {
get_path(buf);
return buf;
}
@ -123,7 +127,7 @@ void node_entry::create_module_tree(const char *module) {
DIR *dir;
struct dirent *entry;
CharArray full_path = get_path();
auto full_path = get_path();
snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, full_path.c_str());
if (!(dir = xopendir(buf)))
@ -133,7 +137,7 @@ void node_entry::create_module_tree(const char *module) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
// Create new node
node_entry *node = new node_entry(module, entry->d_name, entry->d_type);
auto node = new node_entry(module, entry->d_name, entry->d_type);
snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), entry->d_name);
/*
@ -185,7 +189,7 @@ void node_entry::clone_skeleton() {
struct node_entry *dummy;
// Clone the structure
CharArray full_path = get_path();
auto full_path = get_path();
snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path.c_str());
if (!(dir = xopendir(buf)))
return;
@ -200,10 +204,10 @@ void node_entry::clone_skeleton() {
if (status & IS_SKEL) {
file_attr attr;
getattr(full_path, &attr);
getattr(full_path.c_str(), &attr);
LOGI("mnt_tmpfs : %s\n", full_path.c_str());
xmount("tmpfs", full_path, "tmpfs", 0, nullptr);
setattr(full_path, &attr);
xmount("tmpfs", full_path.c_str(), "tmpfs", 0, nullptr);
setattr(full_path.c_str(), &attr);
}
for (auto &child : children) {
@ -254,9 +258,9 @@ void node_entry::clone_skeleton() {
void node_entry::magic_mount() {
if (status & IS_MODULE) {
// Mount module item
CharArray real_path = get_path();
auto real_path = get_path();
snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, real_path.c_str());
bind_mount(buf, real_path);
bind_mount(buf, real_path.c_str());
} else if (status & IS_SKEL) {
// The node is labeled to be cloned with skeleton, lets do it
clone_skeleton();
@ -330,7 +334,8 @@ static void exec_common_script(const char* stage) {
}
static void exec_module_script(const char* stage) {
for (const char *module : module_list) {
for (const auto &m : module_list) {
const auto module = m.c_str();
snprintf(buf2, PATH_MAX, "%s/%s/%s.sh", MOUNTPOINT, module, stage);
if (access(buf2, F_OK) == -1)
continue;
@ -364,7 +369,7 @@ static void simple_mount(const char *path) {
if (access(buf2, F_OK) == -1)
continue;
if (entry->d_type == DT_DIR) {
simple_mount(CharArray(buf2));
simple_mount(string(buf2).c_str());
} else if (entry->d_type == DT_REG) {
// Actual file path
snprintf(buf, PATH_MAX, "%s%s", SIMPLEMOUNT, buf2);
@ -431,21 +436,20 @@ static bool magisk_env() {
xmkdir(SECURE_DIR "/post-fs-data.d", 0755);
xmkdir(SECURE_DIR "/service.d", 0755);
CharArray sdk_prop = getprop("ro.build.version.sdk");
int sdk = sdk_prop.empty() ? -1 : atoi(sdk_prop);
auto sdk_prop = getprop("ro.build.version.sdk");
int sdk = sdk_prop.empty() ? -1 : atoi(sdk_prop.c_str());
LOGI("* Mounting mirrors");
Vector<CharArray> mounts;
file_to_vector("/proc/mounts", mounts);
auto mounts = file_to_vector("/proc/mounts");
bool system_as_root = false;
for (auto &line : mounts) {
if (line.contains(" /system_root ")) {
if (line.find(" /system_root ") != string::npos) {
bind_mount("/system_root/system", MIRRDIR "/system");
sscanf(line, "%s", buf);
sscanf(line.c_str(), "%s", buf);
system_block = strdup2(buf);
system_as_root = true;
} else if (!system_as_root && line.contains(" /system ")) {
sscanf(line, "%s %*s %s", buf, buf2);
} else if (!system_as_root && line.find(" /system ") != string::npos) {
sscanf(line.c_str(), "%s %*s %s", buf, buf2);
system_block = strdup2(buf);
xmount(system_block, MIRRDIR "/system", buf2, MS_RDONLY, nullptr);
#ifdef MAGISK_DEBUG
@ -453,9 +457,9 @@ static bool magisk_env() {
#else
LOGI("mount: %s\n", MIRRDIR "/system");
#endif
} else if (line.contains(" /vendor ")) {
} else if (line.find(" /vendor ") != string::npos) {
seperate_vendor = true;
sscanf(line, "%s %*s %s", buf, buf2);
sscanf(line.c_str(), "%s %*s %s", buf, buf2);
vendor_block = strdup2(buf);
xmkdir(MIRRDIR "/vendor", 0755);
xmount(buf, MIRRDIR "/vendor", buf2, MS_RDONLY, nullptr);
@ -464,7 +468,9 @@ static bool magisk_env() {
#else
LOGI("mount: %s\n", MIRRDIR "/vendor");
#endif
} else if (sdk >= 24 && line.contains(" /proc ") && !line.contains("hidepid=2")) {
} else if (sdk >= 24 &&
line.find(" /proc ") != string::npos &&
line.find("hidepid=2") == string::npos) {
// Enforce hidepid
xmount(nullptr, "/proc", nullptr, MS_REMOUNT, "hidepid=2,gid=3009");
}
@ -508,7 +514,7 @@ static void collect_modules() {
}
unlink("update");
if (access("disable", F_OK))
module_list.push_back(entry->d_name);
module_list.emplace_back(entry->d_name);
chdir("..");
}
}
@ -559,7 +565,7 @@ static bool prepare_img() {
static void install_apk(const char *apk) {
setfilecon(apk, "u:object_r:" SEPOL_FILE_DOMAIN ":s0");
while (1) {
while (true) {
sleep(5);
LOGD("apk_install: attempting to install APK\n");
int fd = -1, pid;
@ -586,14 +592,14 @@ static void install_apk(const char *apk) {
static bool check_data() {
bool mnt = false;
bool data = false;
Vector<CharArray> mounts;
file_to_vector("/proc/mounts", mounts);
auto mounts = file_to_vector("/proc/mounts");
for (auto &line : mounts) {
if (line.contains(" /data ") && !line.contains("tmpfs"))
if (line.find(" /data ") != string::npos &&
line.find("tmpfs") == string::npos)
mnt = true;
}
if (mnt) {
CharArray crypto = getprop("ro.crypto.state");
auto crypto = getprop("ro.crypto.state");
if (!crypto.empty()) {
if (crypto == "unencrypted") {
// Unencrypted, we can directly access data
@ -811,11 +817,11 @@ void post_fs_data(int client) {
exec_module_script("post-fs-data");
// Recollect modules
module_list.clear(true);
module_list.clear();
collect_modules();
// Create the system root entry
node_entry *sys_root = new node_entry("system", IS_INTER);
auto sys_root = new node_entry("system", IS_INTER);
// Vendor root entry
node_entry *ven_root = nullptr;
@ -823,7 +829,8 @@ void post_fs_data(int client) {
bool has_modules = false;
LOGI("* Loading modules\n");
for (const char *module : module_list) {
for (const auto &m : module_list) {
const auto module = m.c_str();
// Read props
snprintf(buf, PATH_MAX, "%s/%s/system.prop", MOUNTPOINT, module);
if (access(buf, F_OK) == 0) {
@ -911,7 +918,7 @@ core_only:
}
// All boot stage done, cleanup
module_list.clear(true);
module_list.clear();
}
void boot_complete(int client) {

View File

@ -12,14 +12,17 @@
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <vector>
#include "magisk.h"
#include "utils.h"
#include "daemon.h"
#include "flags.h"
using namespace std;
bool log_daemon_started = false;
static Vector<const char *> log_cmd, clear_cmd;
static vector<const char *> log_cmd, clear_cmd;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
enum {
@ -68,7 +71,7 @@ static void *monitor_thread(void *) {
sleep(5);
int fd;
char b;
while (1) {
while (true) {
fd = connect_daemon();
write_int(fd, HANDSHAKE);
// This should hold unless the daemon is killed
@ -136,11 +139,7 @@ static void log_daemon() {
}
chmod("/dev/null", 0666);
clear_cmd = log_cmd;
log_cmd.push_back("-v");
log_cmd.push_back("threadtime");
log_cmd.push_back("-s");
log_cmd.push_back("am_proc_start");
log_cmd.push_back("Magisk");
log_cmd.insert(log_cmd.end(), { "-v", "threadtime", "-s", "am_proc_start", "Magisk" });
#ifdef MAGISK_DEBUG
log_cmd.push_back("*:F");
#endif
@ -163,7 +162,7 @@ static void log_daemon() {
if (xbind(sockfd, (struct sockaddr*) &sun, len))
exit(1);
xlisten(sockfd, 10);
while(1) {
while(true) {
int fd = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC);
switch(read_int(fd)) {
case HIDE_CONNECT:

View File

@ -3,12 +3,11 @@
#pragma once
#include "CharArray.h"
#include <string>
int prop_exist(const char *name);
int setprop(const char *name, const char *value, const bool trigger = true);
CharArray getprop(const char *name, bool persist = false);
int setprop(const char *name, const char *value, bool trigger = true);
std::string getprop(const char *name, bool persist = false);
void getprop(void (*callback)(const char *, const char *, void *), void *cookie, bool persist = false);
int deleteprop(const char *name, bool persist = false);
int load_prop_file(const char *filename, const bool trigger = true);
int load_prop_file(const char *filename, bool trigger = true);

View File

@ -2,11 +2,14 @@
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include "cpio.h"
#include "utils.h"
#include "logging.h"
using namespace std;
#define parse_align() lseek(fd, align(lseek(fd, 0, SEEK_CUR), 4), SEEK_SET)
static uint32_t x8u(char *hex) {
@ -40,8 +43,8 @@ cpio_entry::cpio_entry(int fd, cpio_newc_header &header) {
// rdevminor = x8u(header.rdevminor);
uint32_t namesize = x8u(header.namesize);
// check = x8u(header.check);
filename = CharArray(namesize);
xxread(fd, filename, filename.size());
filename.resize(namesize - 1);
xxread(fd, &filename[0], namesize);
parse_align();
if (filesize) {
data = xmalloc(filesize);
@ -54,22 +57,13 @@ cpio_entry::~cpio_entry() {
free(data);
}
// Define the way to sort cpio_entry
template<>
int(*Vector<cpio_entry*>::_cmp)(cpio_entry*&, cpio_entry*&) = [](auto a, auto b) -> int {
if (a == b) return 0;
if (a == nullptr) return 1;
if (b == nullptr) return -1;
return a->filename.compare(b->filename);
};
cpio::cpio(const char *filename) {
int fd = open(filename, O_RDONLY);
if (fd < 0) return;
fprintf(stderr, "Loading cpio: [%s]\n", filename);
cpio_newc_header header;
cpio_entry *entry;
int i = 0;
while(xxread(fd, &header, sizeof(cpio_newc_header)) != -1) {
entry = new cpio_entry(fd, header);
if (entry->filename == "." || entry->filename == ".." || entry->filename == "TRAILER!!!") {
@ -86,7 +80,7 @@ cpio::cpio(const char *filename) {
cpio::~cpio() {
for (auto &e : arr)
if (e) delete e;
delete e;
}
#define dump_align() write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR), 4))
@ -109,11 +103,11 @@ void cpio::dump(const char *file) {
0, // e->devminor
0, // e->rdevmajor
0, // e->rdevminor
(uint32_t) e->filename.size(),
(uint32_t) e->filename.size() + 1,
0 // e->check
);
xwrite(fd, header, 110);
xwrite(fd, e->filename, e->filename.size());
xwrite(fd, e->filename.c_str(), e->filename.size() + 1);
dump_align();
if (e->filesize) {
xwrite(fd, e->data, e->filesize);
@ -140,7 +134,7 @@ int cpio::find(const char *name) {
}
void cpio::insert(cpio_entry *e) {
int i = find(e->filename);
int i = find(e->filename.c_str());
if (i >= 0) {
delete arr[i];
arr[i] = e;
@ -149,17 +143,12 @@ void cpio::insert(cpio_entry *e) {
}
}
void cpio::insert(Vector<cpio_entry *> &arr) {
for (auto &e : arr)
insert(e);
}
void cpio::rm(const char *name, bool r) {
size_t len = strlen(name);
for (auto &e : arr) {
if (!e)
continue;
if (e->filename.compare(name, len) == 0 &&
if (e->filename.compare(0, len, name) == 0 &&
((r && e->filename[len] == '/') || e->filename[len] == '\0')) {
fprintf(stderr, "Remove [%s]\n", e->filename.c_str());
delete e;
@ -171,17 +160,15 @@ void cpio::rm(const char *name, bool r) {
}
void cpio::makedir(mode_t mode, const char *name) {
auto e = new cpio_entry();
auto e = new cpio_entry(name);
e->mode = S_IFDIR | mode;
e->filename = name;
insert(e);
fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode);
}
void cpio::ln(const char *target, const char *name) {
auto e = new cpio_entry();
auto e = new cpio_entry(name);
e->mode = S_IFLNK;
e->filename = name;
e->filesize = strlen(target);
e->data = strdup(target);
insert(e);
@ -190,9 +177,8 @@ void cpio::ln(const char *target, const char *name) {
void cpio::add(mode_t mode, const char *name, const char *file) {
int fd = xopen(file, O_RDONLY);
auto e = new cpio_entry();
auto e = new cpio_entry(name);
e->mode = S_IFREG | mode;
e->filename = name;
e->filesize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
e->data = xmalloc(e->filesize);
@ -239,17 +225,15 @@ static void extract_entry(cpio_entry *e, const char *file) {
void cpio::extract() {
for (auto &e : arr) {
if (!e)
continue;
extract_entry(e, e->filename);
if (!e) continue;
extract_entry(e, e->filename.c_str());
}
}
bool cpio::extract(const char *name, const char *file) {
int i = find(name);
if (i > 0) {
auto e = arr[i];
extract_entry(e, file);
extract_entry(arr[i], file);
return true;
}
fprintf(stderr, "Cannot find the file entry [%s]\n", name);
@ -257,7 +241,13 @@ bool cpio::extract(const char *name, const char *file) {
}
void cpio::sort() {
arr.sort();
std::sort(arr.begin(), arr.end(), [] (auto a, auto b) -> bool {
if (a == b || a == nullptr)
return false;
if (b == nullptr)
return true;
return a->filename.compare(b->filename) < 0;
});
while (arr.back() == nullptr)
arr.pop_back();
}

View File

@ -2,9 +2,8 @@
#define _CPIO_H_
#include <stdint.h>
#include "Vector.h"
#include "CharArray.h"
#include <vector>
#include <string>
struct cpio_newc_header {
char magic[6];
@ -38,17 +37,18 @@ struct cpio_entry {
// uint32_t namesize;
// uint32_t check;
// char *filename = nullptr;
CharArray filename;
std::string filename;
void *data = nullptr;
cpio_entry() {}
cpio_entry() = default;
explicit cpio_entry(const char *name) : filename(name) {}
cpio_entry(int fd, cpio_newc_header &header);
~cpio_entry();
};
class cpio {
public:
cpio(const char *filename);
explicit cpio(const char *filename);
~cpio();
void dump(const char *file);
int find(const char *name);
@ -57,14 +57,13 @@ public:
void makedir(mode_t mode, const char *name);
void ln(const char *target, const char *name);
void add(mode_t mode, const char *name, const char *file);
void insert(Vector<cpio_entry *> &arr);
bool mv(const char *from, const char *to);
void extract();
bool extract(const char *name, const char *file);
void sort();
protected:
Vector<cpio_entry *> arr;
std::vector<cpio_entry *> arr;
};
#endif

View File

@ -6,9 +6,11 @@
#include "cpio.h"
#include "utils.h"
using namespace std;
class magisk_cpio : public cpio {
public:
magisk_cpio(const char *filename) : cpio(filename) {}
explicit magisk_cpio(const char *filename) : cpio(filename) {}
void patch(bool keepverity, bool keepforceencrypt);
int test();
char * sha1();
@ -23,8 +25,8 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) {
if (!e)
continue;
bool fstab = (!keepverity || !keepforceencrypt) &&
!e->filename.starts_with(".backup") &&
e->filename.contains("fstab") && S_ISREG(e->mode);
!str_starts(e->filename, ".backup") &&
str_contains(e->filename, "fstab") && S_ISREG(e->mode);
if (!keepverity) {
if (fstab) {
patch_verity(&e->data, &e->filesize, 1);
@ -98,7 +100,7 @@ char *magisk_cpio::sha1() {
void magisk_cpio::restore() {
for (auto &e : arr) {
if (!e) continue;
if (e->filename.starts_with(".backup")) {
if (str_starts(e->filename, ".backup")) {
if (e->filename[7] == '\0') continue;
if (e->filename[8] == '.') {
if (strcmp(&e->filename[8], ".rmlist") == 0) {
@ -106,7 +108,7 @@ void magisk_cpio::restore() {
rm((char *) e->data + pos, false);
}
} else {
mv(e->filename, e->filename + 8);
mv(e->filename.c_str(), &e->filename[8]);
}
}
}
@ -120,17 +122,15 @@ void magisk_cpio::restore() {
}
void magisk_cpio::backup(const char *orig) {
Vector<cpio_entry*> bak;
vector<cpio_entry*> bak;
cpio_entry *m, *n, *rem;
char buf[PATH_MAX];
m = new cpio_entry();
m->filename = ".backup";
m = new cpio_entry(".backup");
m->mode = S_IFDIR;
bak.push_back(m);
rem = new cpio_entry();
rem->filename = ".backup/.rmlist";
rem = new cpio_entry(".backup/.rmlist");
rem->mode = S_IFREG;
magisk_cpio o(orig);
@ -176,7 +176,7 @@ void magisk_cpio::backup(const char *orig) {
// Something new in ramdisk, record in rem
++j;
rem->data = xrealloc(rem->data, rem->filesize + n->filename.size());
memcpy((char *) rem->data + rem->filesize, n->filename, n->filename.size());
memcpy((char *) rem->data + rem->filesize, n->filename.c_str(), n->filename.size());
rem->filesize += n->filename.size();
fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename.c_str());
}
@ -196,7 +196,8 @@ void magisk_cpio::backup(const char *orig) {
delete rem;
if (bak.size() > 1)
insert(bak);
for (auto item : bak)
insert(item);
}
@ -249,11 +250,11 @@ int cpio_commands(int argc, char *argv[]) {
return 0;
}
} else if (cmdc == 3 && strcmp(cmdv[0], "mkdir") == 0) {
cpio.makedir(strtoul(cmdv[1], NULL, 8), cmdv[2]);
cpio.makedir(strtoul(cmdv[1], nullptr, 8), cmdv[2]);
} else if (cmdc == 3 && strcmp(cmdv[0], "ln") == 0) {
cpio.ln(cmdv[1], cmdv[2]);
} else if (cmdc == 4 && strcmp(cmdv[0], "add") == 0) {
cpio.add(strtoul(cmdv[1], NULL, 8), cmdv[2], cmdv[3]);
cpio.add(strtoul(cmdv[1], nullptr, 8), cmdv[2], cmdv[3]);
} else {
return 1;
}

View File

@ -15,10 +15,12 @@
#include "daemon.h"
#include "db.h"
using namespace std;
#define SAFETYNET_COMPONENT "com.google.android.gms/.droidguard.DroidGuardService"
#define SAFETYNET_PROCESS "com.google.android.gms.unstable"
Vector<CharArray> hide_list;
vector<string> hide_list;
pthread_mutex_t list_lock;
static pthread_t proc_monitor_thread;
@ -55,7 +57,7 @@ void hide_sensitive_props() {
// Hide all sensitive props
for (int i = 0; prop_key[i]; ++i) {
CharArray value = getprop(prop_key[i]);
auto value = getprop(prop_key[i]);
if (!value.empty() && value != prop_value[i])
setprop(prop_key[i], prop_value[i], false);
}
@ -118,7 +120,7 @@ static bool proc_name_match(int pid, const char *name) {
}
static void kill_proc_cb(int pid, void *v) {
ps_arg *args = static_cast<ps_arg *>(v);
auto args = static_cast<ps_arg *>(v);
if (proc_name_match(pid, args->name))
kill(pid, SIGTERM);
else if (args->uid > 0) {
@ -183,7 +185,7 @@ int add_list(const char *proc) {
// Critical region
pthread_mutex_lock(&list_lock);
hide_list.push_back(proc);
hide_list.emplace_back(proc);
kill_process(proc);
pthread_mutex_unlock(&list_lock);
@ -247,10 +249,9 @@ bool init_list() {
// Migrate old hide list into database
if (access(LEGACY_LIST, R_OK) == 0) {
Vector<CharArray> tmp;
file_to_vector(LEGACY_LIST, tmp);
auto tmp = file_to_vector(LEGACY_LIST);
for (auto &s : tmp)
add_list(s);
add_list(s.c_str());
unlink(LEGACY_LIST);
}
@ -307,7 +308,7 @@ int launch_magiskhide(int client) {
// Start monitoring
proc_monitor();
error:
error:
hide_enabled = false;
return DAEMON_ERROR;
}

View File

@ -2,10 +2,10 @@
#define MAGISK_HIDE_H
#include <pthread.h>
#include <vector>
#include <string>
#include "daemon.h"
#include "Vector.h"
#include "CharArray.h"
#define TERM_THREAD SIGUSR1
@ -30,7 +30,7 @@ bool init_list();
extern bool hide_enabled;
extern pthread_mutex_t list_lock;
extern Vector<CharArray> hide_list;
extern std::vector<std::string> hide_list;
enum {
LAUNCH_MAGISKHIDE,

View File

@ -15,19 +15,23 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <vector>
#include <string>
#include "magisk.h"
#include "daemon.h"
#include "utils.h"
#include "magiskhide.h"
using namespace std;
static int sockfd = -1;
extern char *system_block, *vendor_block, *magiskloop;
// Workaround for the lack of pthread_cancel
static void term_thread(int) {
LOGD("proc_monitor: running cleanup\n");
hide_list.clear(true);
hide_list.clear();
hide_enabled = false;
close(sockfd);
sockfd = -1;
@ -64,7 +68,7 @@ static void hide_daemon(int pid) {
LOGD("hide_daemon: handling pid=[%d]\n", pid);
char buffer[4096];
Vector<CharArray> mounts;
vector<string> mounts;
manage_selinux();
clean_magisk_props();
@ -75,24 +79,24 @@ static void hide_daemon(int pid) {
snprintf(buffer, sizeof(buffer), "/proc/%d", pid);
chdir(buffer);
file_to_vector("mounts", mounts);
mounts = file_to_vector("mounts");
// Unmount dummy skeletons and /sbin links
for (auto &s : mounts) {
if (s.contains("tmpfs /system/") || s.contains("tmpfs /vendor/") || s.contains("tmpfs /sbin")) {
sscanf(s, "%*s %4096s", buffer);
if (str_contains(s, "tmpfs /system/") || str_contains(s, "tmpfs /vendor/") ||
str_contains(s, "tmpfs /sbin")) {
sscanf(s.c_str(), "%*s %4096s", buffer);
lazy_unmount(buffer);
}
}
mounts.clear();
// Re-read mount infos
file_to_vector("mounts", mounts);
mounts = file_to_vector("mounts");
// Unmount everything under /system, /vendor, and loop mounts
for (auto &s : mounts) {
if ((s.contains(" /system/") || s.contains(" /vendor/")) &&
(s.contains(system_block) || s.contains(vendor_block) || s.contains(magiskloop))) {
sscanf(s, "%*s %4096s", buffer);
if ((str_contains(s, " /system/") || str_contains(s, " /vendor/")) &&
(str_contains(s, system_block) || str_contains(s, vendor_block) || str_contains(s, magiskloop))) {
sscanf(s.c_str(), "%*s %4096s", buffer);
lazy_unmount(buffer);
}
}
@ -108,13 +112,12 @@ void proc_monitor() {
sigset_t block_set;
sigemptyset(&block_set);
sigaddset(&block_set, TERM_THREAD);
pthread_sigmask(SIG_UNBLOCK, &block_set, NULL);
pthread_sigmask(SIG_UNBLOCK, &block_set, nullptr);
// Register the cancel signal
struct sigaction act;
memset(&act, 0, sizeof(act));
struct sigaction act{};
act.sa_handler = term_thread;
sigaction(TERM_THREAD, &act, NULL);
sigaction(TERM_THREAD, &act, nullptr);
if (access("/proc/1/ns/mnt", F_OK) != 0) {
LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n");
@ -155,7 +158,7 @@ void proc_monitor() {
bool hide = false;
pthread_mutex_lock(&list_lock);
for (auto &s : hide_list) {
if (strncmp(cpnt, s, s.size() - 1) == 0) {
if (strncmp(cpnt, s.c_str(), s.size() - 1) == 0) {
hide = true;
break;
}

View File

@ -5,6 +5,8 @@
#include <stdio.h>
#include <limits.h>
#include <vector>
#include <string>
#include "sepolicy.h"
#include "magiskpolicy.h"
@ -12,6 +14,8 @@
#include "utils.h"
#include "flags.h"
using namespace std;
static const char *type_msg_1 =
"Type 1:\n"
"\"<rule_name> source_type target_type class perm_set\"\n"
@ -101,7 +105,7 @@ static const char *type_msg_6 =
exit(1);
}
static int parse_bracket(char *tok, char *&stmt, Vector<const char *> *vec) {
static int parse_bracket(char *tok, char *&stmt, vector<const char *> *vec) {
if (tok == nullptr || tok[0] != '{') {
// Not in a bracket
vec->push_back(tok);
@ -143,10 +147,10 @@ static int parse_pattern_1(int action, const char *action_str, char *stmt) {
int state = 0;
char *cur, *cls;
Vector<const char*> source, target, permission;
vector<const char*> source, target, permission;
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
if (cur[0] == '*') cur = ALL;
Vector<const char *> *vec;
vector<const char *> *vec;
switch (state) {
case 0:
vec = &source;
@ -200,10 +204,10 @@ static int parse_pattern_2(int action, const char *action_str, char *stmt) {
int state = 0;
char *cur, *range;
Vector<const char *> source, target, classes;
vector<const char *> source, target, classes;
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
if (cur[0] == '*') cur = ALL;
Vector<const char *> *vec;
vector<const char *> *vec;
switch (state) {
case 0:
vec = &source;
@ -216,7 +220,7 @@ static int parse_pattern_2(int action, const char *action_str, char *stmt) {
break;
case 3:
// Currently only support ioctl
if (strcmp(cur, "ioctl"))
if (strcmp(cur, "ioctl") != 0)
return 1;
vec = nullptr;
break;
@ -262,7 +266,7 @@ static int parse_pattern_3(int action, const char *action_str, char* stmt) {
}
char *cur;
Vector<const char *> domains;
vector<const char *> domains;
while ((cur = strtok_r(nullptr, " {}", &stmt)) != nullptr) {
if (cur[0] == '*') cur = ALL;
domains.push_back(cur);
@ -291,10 +295,10 @@ static int parse_pattern_4(int action, const char *action_str, char *stmt) {
int state = 0;
char *cur;
Vector<const char *> classes, attribute;
vector<const char *> classes, attribute;
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
if (cur[0] == '*') cur = ALL;
Vector<const char *> *vec;
vector<const char *> *vec;
switch (state) {
case 0:
vec = &classes;
@ -409,7 +413,7 @@ static void parse_statement(char *statement) {
char *action, *remain;
// strtok will modify the origin string, duplicate the statement for error messages
CharArray orig(statement);
string orig(statement);
action = strtok_r(statement, " ", &remain);
if (remain == nullptr) remain = &action[strlen(action)];

View File

@ -5,15 +5,15 @@
#ifndef MAGISK_PROPS_H
#define MAGISK_PROPS_H
#include <CharArray.h>
#include <string>
#include "resetprop/private/system_properties.h"
#include "logging.h"
struct prop_t {
char *name;
char value[PROP_VALUE_MAX];
prop_t() = default;
prop_t(const char *name) {
prop_t() : name(nullptr) {}
explicit prop_t(const char *name) {
this->name = strdup(name);
value[0] = '\0';
}
@ -21,7 +21,13 @@ struct prop_t {
this->name = strdup(name);
strcpy(this->value, value);
}
prop_t& operator= (prop_t&& prop) {
prop_t(prop_t &&prop): name(nullptr) {
operator=(std::move(prop));
}
bool operator<(const prop_t &prop) const {
return strcmp(name, prop.name) < 0;
}
prop_t& operator= (prop_t &&prop) {
if (this != &prop) {
free(name);
name = prop.name;
@ -38,7 +44,7 @@ struct prop_t {
struct read_cb_t {
void (*cb)(const char *, const char *, void *);
void *arg;
read_cb_t(void (*cb)(const char *, const char *, void *) = nullptr, void *arg = nullptr)
explicit read_cb_t(void (*cb)(const char *, const char *, void *) = nullptr, void *arg = nullptr)
: cb(cb), arg(arg) {}
void exec(const char *name, const char *value) {
cb(name, value, arg);
@ -49,7 +55,7 @@ struct read_cb_t {
extern bool use_pb;
CharArray persist_getprop(const char *name);
std::string persist_getprop(const char *name);
void persist_getprop(read_cb_t *read_cb);
bool persist_deleteprop(const char *name);
void collect_props(const char *name, const char *value, void *v_plist);

View File

@ -5,6 +5,8 @@
#include <unistd.h>
#include <sys/mman.h>
#include <vector>
#include <pb.h>
#include <pb_decode.h>
#include <pb_encode.h>
@ -12,6 +14,8 @@
#include "_resetprop.h"
#include "utils.h"
using namespace std;
/* ***********************************************************************
* Auto generated header and constant definitions compiled from
* android/platform/system/core/master/init/persistent_properties.proto
@ -113,7 +117,7 @@ static bool prop_encode(pb_ostream_t *stream, const pb_field_t *field, void * co
PersistentProperties_PersistentPropertyRecord prop = {};
prop.name.funcs.encode = name_encode;
prop.has_value = true;
Vector<prop_t> &prop_list = *(Vector<prop_t> *) *arg;
auto &prop_list = *(vector<prop_t> *) *arg;
for (auto &p : prop_list) {
if (!pb_encode_tag_for_field(stream, field))
return false;
@ -160,16 +164,16 @@ static void pb_getprop(read_cb_t *read_cb) {
munmap(buf, size);
}
static void file_getprop(const char *name, char *value) {
value[0] = '\0';
static bool file_getprop(const char *name, char *value) {
char path[PATH_MAX];
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0)
return;
return false;
LOGD("resetprop: read prop from [%s]\n", path);
value[read(fd, value, sizeof(PROP_VALUE_MAX))] = '\0'; // Null terminate the read value
value[read(fd, value, PROP_VALUE_MAX)] = '\0'; // Null terminate the read value
close(fd);
return value[0] != '\0';
}
void persist_getprop(read_cb_t *read_cb) {
@ -182,14 +186,13 @@ void persist_getprop(read_cb_t *read_cb) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 )
continue;
char value[PROP_VALUE_MAX];
file_getprop(entry->d_name, value);
if (value[0])
if (file_getprop(entry->d_name, value))
read_cb->exec(entry->d_name, value);
}
}
}
CharArray persist_getprop(const char *name) {
string persist_getprop(const char *name) {
prop_t prop(name);
if (use_pb) {
read_cb_t read_cb(pb_getprop_cb, &prop);
@ -199,21 +202,20 @@ CharArray persist_getprop(const char *name) {
} else {
// Try to read from file
char value[PROP_VALUE_MAX];
file_getprop(name, value);
if (value[0])
if (file_getprop(name, value))
return value;
}
return CharArray();
return string();
}
bool persist_deleteprop(const char *name) {
if (use_pb) {
Vector<prop_t> prop_list;
vector<prop_t> prop_list;
read_cb_t read_cb(collect_props, &prop_list);
persist_getprop(&read_cb);
for (auto it = prop_list.begin(); it != prop_list.end(); ++it) {
if (strcmp((*it).name, name) == 0) {
if (strcmp(it->name, name) == 0) {
prop_list.erase(it);
// Dump the props back
PersistentProperties props = PersistentProperties_init_zero;

View File

@ -6,6 +6,8 @@
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <vector>
#include <algorithm>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include "private/_system_properties.h"
@ -17,6 +19,8 @@
#include "utils.h"
#include "flags.h"
using namespace std;
bool use_pb = false;
static bool verbose = false;
@ -74,12 +78,6 @@ illegal:
exit(1);
}
// Define the way to sort prop_t
template<>
int(*Vector<prop_t>::_cmp)(prop_t&, prop_t&) = [](auto a, auto b) -> int {
return strcmp(a.name, b.name);
};
static void read_props(const prop_info *pi, void *read_cb) {
__system_property_read_callback(
pi, [](auto cb, auto name, auto value, auto) -> void
@ -89,12 +87,12 @@ static void read_props(const prop_info *pi, void *read_cb) {
}
void collect_props(const char *name, const char *value, void *v_plist) {
Vector<prop_t> &prop_list = *static_cast<Vector<prop_t> *>(v_plist);
prop_list.push_back(prop_t(name, value));
auto &prop_list = *static_cast<vector<prop_t> *>(v_plist);
prop_list.emplace_back(name, value);
}
static void collect_unique_props(const char *name, const char *value, void *v_plist) {
Vector<prop_t> &prop_list = *static_cast<Vector<prop_t> *>(v_plist);
auto &prop_list = *static_cast<vector<prop_t> *>(v_plist);
for (auto &prop : prop_list) {
if (strcmp(name, prop.name) == 0)
return;
@ -112,9 +110,9 @@ static int init_resetprop() {
}
static void print_props(bool persist) {
Vector<prop_t> prop_list;
vector<prop_t> prop_list;
getprop(collect_props, &prop_list, persist);
prop_list.sort();
sort(prop_list.begin(), prop_list.end());
for (auto &prop : prop_list)
printf("[%s]: [%s]\n", prop.name, prop.value);
}
@ -128,19 +126,19 @@ int prop_exist(const char *name) {
return __system_property_find(name) != nullptr;
}
// Get prop by name, return string (should free manually!)
CharArray getprop(const char *name, bool persist) {
// Get prop by name, return string
string getprop(const char *name, bool persist) {
if (!check_legal_property_name(name) || init_resetprop())
return nullptr;
const prop_info *pi = __system_property_find(name);
if (pi == nullptr) {
if (persist && strncmp(name, "persist.", 8) == 0) {
CharArray value = persist_getprop(name);
if (!value.empty())
return value;
auto value = persist_getprop(name);
if (value.empty())
LOGD("resetprop: prop [%s] does not exist\n", name);
return value;
}
LOGD("resetprop: prop [%s] does not exist\n", name);
return CharArray();
return string();
} else {
char value[PROP_VALUE_MAX];
read_cb_t read_cb;
@ -162,7 +160,7 @@ void getprop(void (*callback)(const char *, const char *, void *), void *cookie,
}
}
int setprop(const char *name, const char *value, const bool trigger) {
int setprop(const char *name, const char *value, bool trigger) {
if (!check_legal_property_name(name))
return 1;
if (init_resetprop())
@ -170,7 +168,7 @@ int setprop(const char *name, const char *value, const bool trigger) {
int ret;
prop_info *pi = (prop_info*) __system_property_find(name);
auto pi = (prop_info*) __system_property_find(name);
if (pi != nullptr) {
if (trigger) {
if (strncmp(name, "ro.", 3) == 0) deleteprop(name);
@ -208,7 +206,7 @@ int deleteprop(const char *name, bool persist) {
return __system_property_del(name) && !(persist && strncmp(name, "persist.", 8) == 0);
}
int load_prop_file(const char *filename, const bool trigger) {
int load_prop_file(const char *filename, bool trigger) {
if (init_resetprop()) return -1;
LOGD("resetprop: Load prop file [%s]\n", filename);
FILE *fp = xfopen(filename, "re");
@ -254,14 +252,14 @@ int resetprop_main(int argc, char *argv[]) {
bool trigger = true, persist = false;
char *argv0 = argv[0];
CharArray prop;
string prop;
--argc;
++argv;
// Parse flags and -- options
while (argc && argv[0][0] == '-') {
for (int idx = 1; 1; ++idx) {
for (int idx = 1; true; ++idx) {
switch (argv[0][idx]) {
case '-':
if (strcmp(argv[0], "--file") == 0 && argc == 2) {
@ -275,10 +273,10 @@ int resetprop_main(int argc, char *argv[]) {
verbose = true;
continue;
case 'p':
persist = 1;
persist = true;
continue;
case 'n':
trigger = 0;
trigger = false;
continue;
case '\0':
break;
@ -297,8 +295,8 @@ int resetprop_main(int argc, char *argv[]) {
print_props(persist);
return 0;
case 1:
prop = utils::move(getprop(argv[0], persist));
if (!prop) return 1;
prop = getprop(argv[0], persist);
if (prop.empty()) return 1;
printf("%s\n", prop.c_str());
return 0;
case 2:

View File

@ -9,7 +9,6 @@ LOCAL_SRC_FILES := \
misc.cpp \
selinux.cpp \
logging.cpp \
xwrap.cpp \
CharArray.cpp
xwrap.cpp
include $(BUILD_STATIC_LIBRARY)

View File

@ -1,99 +0,0 @@
#include "CharArray.h"
#include "utils.h"
CharArray::CharArray() : _buf(nullptr), _size(0){}
CharArray::CharArray(const char *s) : CharArray() {
this->operator=(s);
}
CharArray::CharArray(const CharArray &s) : CharArray() {
this->operator=(s);
}
CharArray::CharArray(size_t i) {
_size = i;
_buf = new char[i](); /* Zero initialize */
}
CharArray::~CharArray() {
delete[] _buf;
}
CharArray::operator char *() {
return _buf;
}
CharArray::operator const char *() const {
return _buf;
}
const char *CharArray::c_str() const {
return _buf;
}
size_t CharArray::length() const {
return strlen(_buf);
}
size_t CharArray::size() const {
return _size;
}
CharArray &CharArray::operator=(const CharArray &s) {
delete[] _buf;
_size = s._size;
_buf = new char[_size];
memcpy(_buf, s._buf, _size);
return *this;
}
CharArray &CharArray::operator=(const char *s) {
delete[] _buf;
_buf = strdup2(s, &_size);
return *this;
}
CharArray &CharArray::operator=(CharArray &&s) {
delete[] _buf;
_size = s._size;
_buf = s._buf;
s._buf = nullptr;
s._size = 0;
return *this;
}
bool CharArray::operator==(const char *s) const {
if (_buf == nullptr || s == nullptr)
return false;
return strcmp(_buf, s) == 0;
}
bool CharArray::operator==(char *s) const {
return *this == (const char *) s;
}
bool CharArray::operator!=(const char *s) const {
return !(*this == s);
}
int CharArray::compare(const char *s) const {
return strcmp(_buf, s);
}
int CharArray::compare(const char *s, size_t len) const {
return strncmp(_buf, s, len);
}
bool CharArray::contains(const char *s) const {
return s == nullptr ? false : strstr(_buf, s) != nullptr;
}
bool CharArray::starts_with(const char *s) const {
return s == nullptr ? false : compare(s, strlen(s)) == 0;
}
bool CharArray::empty() const {
return _buf == nullptr || _buf[0] == '\0';
}

View File

@ -15,6 +15,8 @@
#include "utils.h"
#include "selinux.h"
using namespace std;
const char **excl_list = nullptr;
static int is_excl(const char *name) {
@ -307,7 +309,7 @@ void clone_attr(const char *source, const char *target) {
setattr(target, &a);
}
void fclone_attr(const int sourcefd, const int targetfd) {
void fclone_attr(int sourcefd, int targetfd) {
struct file_attr a;
fgetattr(sourcefd, &a);
fsetattr(targetfd, &a);
@ -388,24 +390,25 @@ void write_zero(int fd, size_t size) {
lseek(fd, pos + size, SEEK_SET);
}
int file_to_vector(const char *filename, Vector<CharArray> &arr) {
vector<string> file_to_vector(const char *filename) {
auto arr = vector<string>();
if (access(filename, R_OK) != 0)
return 1;
return arr;
char *line = nullptr;
size_t len = 0;
ssize_t read;
FILE *fp = xfopen(filename, "re");
if (fp == nullptr)
return 1;
return arr;
while ((read = getline(&line, &len, fp)) != -1) {
// Remove end newline
if (line[read - 1] == '\n')
line[read - 1] = '\0';
arr.push_back(line);
arr.emplace_back(line);
}
fclose(fp);
free(line);
return 0;
return arr;
}

View File

@ -1,39 +0,0 @@
#pragma once
#include <string.h>
/* A wrapper around char array */
class CharArray {
public:
CharArray();
CharArray(const char *s);
CharArray(const CharArray &s);
CharArray(size_t i);
~CharArray();
CharArray &operator=(const CharArray &s);
CharArray &operator=(CharArray &&s);
CharArray &operator=(const char *s);
operator char *();
operator const char *() const;
bool operator==(char *s) const;
bool operator==(const char *s) const;
bool operator!=(const char *s) const;
int compare(const char *s) const;
int compare(const char *s, size_t len) const;
bool starts_with(const char *s) const;
bool contains(const char *s) const;
bool empty() const;
const char *c_str() const;
size_t length() const;
size_t size() const;
/* These 2 ops are incompatible with implicit char* conversion */
// char &operator[](size_t i);
// const char &operator[](size_t i) const;
private:
char *_buf;
size_t _size;
};

View File

@ -1,191 +0,0 @@
#pragma once
#include <stdlib.h>
#include "cpputils.h"
template <class T>
class Vector {
public:
Vector() : _data(0), _size(0), _capacity(0) {}
~Vector() { delete []_data; }
class iterator {
friend class Vector;
public:
iterator(T* n= 0): _node(n) {}
iterator(const iterator& i): _node(i._node) {}
~iterator() {} // Should NOT delete _node
const T& operator * () const { return (*_node); }
T& operator * () { return (*_node); }
iterator& operator ++ () {
++_node;
return (*this);
}
iterator operator ++ (int) {
iterator temp = *this;
++_node;
return temp;
}
iterator& operator -- () {
--_node;
return (*this);
}
iterator operator -- (int) {
iterator temp = *this;
--_node;
return temp;
}
iterator operator + (int i) const {
iterator temp = *this;
temp += i;
return temp;
}
iterator& operator += (int i) {
_node += i;
return (*this);
}
iterator& operator = (const iterator& i) {
_node = i._node;
return (*this);
}
bool operator != (const iterator& i) const {
return _node != i._node;
}
bool operator == (const iterator& i) const { return !(*this != i); }
private:
T* _node;
};
Vector &operator=(const Vector& a) {
delete [] _data;
_data = nullptr;
_size = a._size;
_capacity = a._capacity;
if (_capacity) {
_data = new T[_capacity];
for(int i = 0; i < _size; ++i)
_data[i] = a[i];
}
return *this;
}
Vector &operator=(Vector&& a) {
delete [] _data;
_size = a._size;
_capacity = a._capacity;
_data = a._data;
a._size = 0;
a._capacity = 0;
a._data = nullptr;
return *this;
}
iterator begin() const { return iterator(_data); }
iterator end() const { return iterator(_data + _size); }
bool empty() const { return !_size; }
size_t size() const { return _size; }
T& operator [] (size_t i) { return _data[i]; }
const T& operator [] (size_t i) const { return _data[i]; }
const T& back() const { return _data[_size - 1]; }
void push_back(const T& x) {
if(_size == _capacity)
expand();
_data[_size] = x;
++_size;
}
void push_back(T&& x) {
if(_size == _capacity)
expand();
_data[_size] = utils::move(x);
++_size;
}
void pop_front() { erase(begin()); }
void pop_back() { if(_size) --_size; }
bool erase(iterator pos) {
T* d = pos._node;
if (_size == 0 || d < _data || d >= _data + _size)
return false;
for (; d < _data + _size - 1; ++d)
*d = utils::move(*(d + 1));
--_size;
return true;
}
bool erase(const T& x) {
for (T* i = _data; i < _data + _size; ++i) {
if(*i == x) {
erase(iterator(i));
return true;
}
}
return false;
}
void clear(bool dealloc = false) {
_size = 0;
if (dealloc) {
_capacity = 0;
delete [] _data;
_data = nullptr;
}
}
void sort() {
qsort(_data, _size, sizeof(T), compare);
}
T* data() { return _data; }
const T* data() const { return _data; }
// void reserve(size_t n) { ... }
// void resize(size_t n) { ... }
private:
T* _data;
size_t _size; // number of valid elements
size_t _capacity; // max number of elements
static int(*_cmp)(T&, T&);
static int compare(const void *a, const void *b) {
return _cmp ? _cmp(*((T*) a), *((T*) b)) : 0;
}
void expand() {
if (_capacity == 0)
_capacity = 1;
else
_capacity *= 2;
T* temp = _data;
_data = new T[_capacity];
for(int i = 0; i < _size; ++i)
_data[i] = utils::move(temp[i]);
delete [] temp;
}
};
template<class T>
int(* Vector<T>::_cmp)(T&, T&) = nullptr;

View File

@ -1,12 +0,0 @@
#pragma once
namespace utils {
template< class T > struct remove_reference {typedef T type;};
template< class T > struct remove_reference<T&> {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};
template< class T >
constexpr typename remove_reference<T>::type&& move( T&& t ) noexcept {
return static_cast<typename remove_reference<T>::type&&>(t);
}
}

View File

@ -13,15 +13,17 @@
#ifdef __cplusplus
#include "Vector.h"
#include "CharArray.h"
#include "cpputils.h"
#include <string>
#include <vector>
int file_to_vector(const char *filename, Vector<CharArray> &arr);
#define str_contains(s, ss) ((s).find(ss) != string::npos)
#define str_starts(s, ss) ((s).compare(0, strlen(ss), ss) == 0)
std::vector<std::string> file_to_vector(const char *filename);
char *strdup2(const char *s, size_t *size = nullptr);
int exec_array(bool err, int *fd, void (*pre_exec)(void), const char **argv);
int exec_command(bool err, int *fd, void (*cb)(void), const char *argv0, ...);
int exec_array(bool err, int *fd, void (*pre_exec)(), const char **argv);
int exec_command(bool err, int *fd, void (*cb)(), const char *argv0, ...);
extern "C" {
#endif
@ -134,7 +136,7 @@ int fgetattr(int fd, struct file_attr *a);
int setattr(const char *path, struct file_attr *a);
int setattrat(int dirfd, const char *pathname, struct file_attr *a);
int fsetattr(int fd, struct file_attr *a);
void fclone_attr(const int sourcefd, const int targetfd);
void fclone_attr(int sourcefd, int targetfd);
void clone_attr(const char *source, const char *target);
void mmap_ro(const char *filename, void **buf, size_t *size);
void mmap_rw(const char *filename, void **buf, size_t *size);

View File

@ -11,10 +11,13 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sysmacros.h>
#include <vector>
#include "logging.h"
#include "utils.h"
using namespace std;
unsigned get_shell_uid() {
struct passwd* ppwd = getpwnam("shell");
if (nullptr == ppwd)
@ -199,7 +202,7 @@ int exec_array(bool err, int *fd, void (*pre_exec)(void), const char **argv) {
static int v_exec_command(bool err, int *fd, void (*cb)(void), const char *argv0, va_list argv) {
// Collect va_list into vector
Vector<const char *> args;
vector<const char *> args;
args.push_back(argv0);
for (const char *arg = va_arg(argv, char*); arg; arg = va_arg(argv, char*))
args.push_back(arg);

View File

@ -1,6 +1,9 @@
#include <new>
#include <stdlib.h>
/* Override libc++ new implementation
* to optimize final build size */
void* operator new(std::size_t s) { return malloc(s); }
void* operator new[](std::size_t s) { return malloc(s); }
void operator delete(void *p) { free(p); }

View File

@ -86,7 +86,7 @@ ssize_t xread(int fd, void *buf, size_t count) {
ssize_t xxread(int fd, void *buf, size_t count) {
int ret = read(fd, buf, count);
if (count != ret) {
PLOGE("read");
PLOGE("read (%d != %d)", count, ret);
}
return ret;
}