Commit 7c12bf7f authored by topjohnwu's avatar topjohnwu

Modernize code base

parent ca35a968
This diff is collapsed.
...@@ -82,7 +82,7 @@ static void *request_handler(void *args) { ...@@ -82,7 +82,7 @@ static void *request_handler(void *args) {
close(client); close(client);
break; break;
} }
return NULL; return nullptr;
} }
static void main_daemon() { static void main_daemon() {
......
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
#pragma once #pragma once
#include "CharArray.h"
int prop_exist(const char *name); int prop_exist(const char *name);
int setprop(const char *name, const char *value, const bool trigger = true); int setprop(const char *name, const char *value, const bool trigger = true);
char *getprop(const char *name, bool persist = false); CharArray getprop(const char *name, bool persist = false);
void getprop(void (*callback)(const char *, const char *, void *), void *cookie, 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 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, const bool trigger = true);
......
...@@ -40,8 +40,8 @@ cpio_entry::cpio_entry(int fd, cpio_newc_header &header) { ...@@ -40,8 +40,8 @@ cpio_entry::cpio_entry(int fd, cpio_newc_header &header) {
// rdevminor = x8u(header.rdevminor); // rdevminor = x8u(header.rdevminor);
uint32_t namesize = x8u(header.namesize); uint32_t namesize = x8u(header.namesize);
// check = x8u(header.check); // check = x8u(header.check);
filename = (char *) xmalloc(namesize); filename = CharArray(namesize);
xxread(fd, filename, namesize); xxread(fd, filename, filename.size());
parse_align(); parse_align();
if (filesize) { if (filesize) {
data = xmalloc(filesize); data = xmalloc(filesize);
...@@ -51,7 +51,6 @@ cpio_entry::cpio_entry(int fd, cpio_newc_header &header) { ...@@ -51,7 +51,6 @@ cpio_entry::cpio_entry(int fd, cpio_newc_header &header) {
} }
cpio_entry::~cpio_entry() { cpio_entry::~cpio_entry() {
free(filename);
free(data); free(data);
} }
...@@ -61,7 +60,7 @@ int(*Array<cpio_entry*>::_cmp)(cpio_entry*&, cpio_entry*&) = [](auto a, auto b) ...@@ -61,7 +60,7 @@ int(*Array<cpio_entry*>::_cmp)(cpio_entry*&, cpio_entry*&) = [](auto a, auto b)
if (a == b) return 0; if (a == b) return 0;
if (a == nullptr) return 1; if (a == nullptr) return 1;
if (b == nullptr) return -1; if (b == nullptr) return -1;
return strcmp(a->filename, b->filename); return a->filename.compare(b->filename);
}; };
...@@ -73,12 +72,11 @@ cpio::cpio(const char *filename) { ...@@ -73,12 +72,11 @@ cpio::cpio(const char *filename) {
cpio_entry *entry; cpio_entry *entry;
while(xxread(fd, &header, sizeof(cpio_newc_header)) != -1) { while(xxread(fd, &header, sizeof(cpio_newc_header)) != -1) {
entry = new cpio_entry(fd, header); entry = new cpio_entry(fd, header);
if (strcmp(entry->filename, ".") == 0 || strcmp(entry->filename, "..") == 0 || if (entry->filename == "." || entry->filename == ".." || entry->filename == "TRAILER!!!") {
strcmp(entry->filename, "TRAILER!!!") == 0) { bool trailer = entry->filename[0] == 'T';
delete entry; delete entry;
if (entry->filename[0] == 'T') if (trailer)
break; break;
continue;
} }
arr.push_back(entry); arr.push_back(entry);
} }
...@@ -110,11 +108,11 @@ void cpio::dump(const char *file) { ...@@ -110,11 +108,11 @@ void cpio::dump(const char *file) {
0, // e->devminor 0, // e->devminor
0, // e->rdevmajor 0, // e->rdevmajor
0, // e->rdevminor 0, // e->rdevminor
(uint32_t) strlen(e->filename) + 1, (uint32_t) e->filename.size(),
0 // e->check 0 // e->check
); );
xwrite(fd, header, 110); xwrite(fd, header, 110);
xwrite(fd, e->filename, strlen(e->filename) + 1); xwrite(fd, e->filename, e->filename.size());
dump_align(); dump_align();
if (e->filesize) { if (e->filesize) {
xwrite(fd, e->data, e->filesize); xwrite(fd, e->data, e->filesize);
...@@ -134,7 +132,7 @@ int cpio::find(const char *name) { ...@@ -134,7 +132,7 @@ int cpio::find(const char *name) {
for (int i = 0; i < arr.size(); ++i) { for (int i = 0; i < arr.size(); ++i) {
if (!arr[i]) if (!arr[i])
continue; continue;
if (strcmp(arr[i]->filename, name) == 0) if (arr[i]->filename == name)
return i; return i;
} }
return -1; return -1;
...@@ -143,12 +141,11 @@ int cpio::find(const char *name) { ...@@ -143,12 +141,11 @@ int cpio::find(const char *name) {
void cpio::insert(cpio_entry *e) { void cpio::insert(cpio_entry *e) {
int i = find(e->filename); int i = find(e->filename);
if (i >= 0) { if (i >= 0) {
// Replace, then all is done
delete arr[i]; delete arr[i];
arr[i] = e; arr[i] = e;
return; } else {
}
arr.push_back(e); arr.push_back(e);
}
} }
void cpio::insert(Array<cpio_entry *> &arr) { void cpio::insert(Array<cpio_entry *> &arr) {
...@@ -156,17 +153,17 @@ void cpio::insert(Array<cpio_entry *> &arr) { ...@@ -156,17 +153,17 @@ void cpio::insert(Array<cpio_entry *> &arr) {
insert(e); insert(e);
} }
void cpio::rm(int recur, const char *name) { void cpio::rm(const char *name, bool r) {
size_t len = strlen(name); size_t len = strlen(name);
for (auto &e : arr) { for (auto &e : arr) {
if (!e) if (!e)
continue; continue;
if (strncmp(e->filename, name, len) == 0 && if (e->filename.compare(name, len) == 0 &&
((recur && e->filename[len] == '/') || e->filename[len] == '\0')) { ((r && e->filename[len] == '/') || e->filename[len] == '\0')) {
fprintf(stderr, "Remove [%s]\n", e->filename); fprintf(stderr, "Remove [%s]\n", e->filename.c_str());
delete e; delete e;
e = nullptr; e = nullptr;
if (!recur) if (!r)
return; return;
} }
} }
...@@ -175,7 +172,7 @@ void cpio::rm(int recur, const char *name) { ...@@ -175,7 +172,7 @@ void cpio::rm(int recur, const char *name) {
void cpio::makedir(mode_t mode, const char *name) { void cpio::makedir(mode_t mode, const char *name) {
auto e = new cpio_entry(); auto e = new cpio_entry();
e->mode = S_IFDIR | mode; e->mode = S_IFDIR | mode;
e->filename = strdup(name); e->filename = name;
insert(e); insert(e);
fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode); fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode);
} }
...@@ -183,7 +180,7 @@ void cpio::makedir(mode_t mode, const char *name) { ...@@ -183,7 +180,7 @@ void cpio::makedir(mode_t mode, const char *name) {
void cpio::ln(const char *target, const char *name) { void cpio::ln(const char *target, const char *name) {
auto e = new cpio_entry(); auto e = new cpio_entry();
e->mode = S_IFLNK; e->mode = S_IFLNK;
e->filename = strdup(name); e->filename = name;
e->filesize = strlen(target); e->filesize = strlen(target);
e->data = strdup(target); e->data = strdup(target);
insert(e); insert(e);
...@@ -194,7 +191,7 @@ void cpio::add(mode_t mode, const char *name, const char *file) { ...@@ -194,7 +191,7 @@ void cpio::add(mode_t mode, const char *name, const char *file) {
int fd = xopen(file, O_RDONLY); int fd = xopen(file, O_RDONLY);
auto e = new cpio_entry(); auto e = new cpio_entry();
e->mode = S_IFREG | mode; e->mode = S_IFREG | mode;
e->filename = strdup(name); e->filename = name;
e->filesize = lseek(fd, 0, SEEK_END); e->filesize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
e->data = xmalloc(e->filesize); e->data = xmalloc(e->filesize);
...@@ -212,35 +209,38 @@ bool cpio::mv(const char *from, const char *to) { ...@@ -212,35 +209,38 @@ bool cpio::mv(const char *from, const char *to) {
arr[t] = nullptr; arr[t] = nullptr;
} }
fprintf(stderr, "Move [%s] -> [%s]\n", from, to); fprintf(stderr, "Move [%s] -> [%s]\n", from, to);
char * tmp = strdup(to); arr[f]->filename = to;
free(arr[f]->filename);
arr[f]->filename = tmp;
return true; return true;
} }
fprintf(stderr, "Cannot find entry %s\n", from); fprintf(stderr, "Cannot find entry %s\n", from);
return false; return false;
} }
void cpio::extract() { static void extract_entry(cpio_entry *e, const char *file) {
for (auto &e : arr) { fprintf(stderr, "Extract [%s] to [%s]\n", e->filename.c_str(), file);
if (!e) unlink(file);
continue; rmdir(file);
fprintf(stderr, "Extract [%s]\n", e->filename);
unlink(e->filename);
rmdir(e->filename);
if (S_ISDIR(e->mode)) { if (S_ISDIR(e->mode)) {
mkdir(e->filename, e->mode & 0777); mkdir(file, e->mode & 0777);
} else if (S_ISREG(e->mode)) { } else if (S_ISREG(e->mode)) {
int fd = creat(e->filename, e->mode & 0777); int fd = creat(file, e->mode & 0777);
xwrite(fd, e->data, e->filesize); xwrite(fd, e->data, e->filesize);
fchown(fd, e->uid, e->gid); fchown(fd, e->uid, e->gid);
close(fd); close(fd);
} else if (S_ISLNK(e->mode)) { } else if (S_ISLNK(e->mode)) {
char *target = new char[e->filesize + 1]; auto target = new char[e->filesize + 1];
memcpy(target, e->data, e->filesize); memcpy(target, e->data, e->filesize);
symlink(target, e->filename); target[e->filesize] = '\0';
symlink(target, file);
delete[] target; delete[] target;
} }
}
void cpio::extract() {
for (auto &e : arr) {
if (!e)
continue;
extract_entry(e, e->filename);
} }
} }
...@@ -248,18 +248,7 @@ bool cpio::extract(const char *name, const char *file) { ...@@ -248,18 +248,7 @@ bool cpio::extract(const char *name, const char *file) {
int i = find(name); int i = find(name);
if (i > 0) { if (i > 0) {
auto e = arr[i]; auto e = arr[i];
fprintf(stderr, "Extract [%s] to [%s]\n", name, file); extract_entry(e, file);
if (S_ISREG(e->mode)) {
int fd = creat(file, e->mode & 0777);
xwrite(fd, e->data, e->filesize);
fchown(fd, e->uid, e->gid);
close(fd);
} else if (S_ISLNK(e->mode)) {
char *target = new char[e->filesize + 1];
memcpy(target, e->data, e->filesize);
symlink(target, e->filename);
delete[] target;
}
return true; return true;
} }
fprintf(stderr, "Cannot find the file entry [%s]\n", name); fprintf(stderr, "Cannot find the file entry [%s]\n", name);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include "array.h" #include "array.h"
#include "CharArray.h"
struct cpio_newc_header { struct cpio_newc_header {
char magic[6]; char magic[6];
...@@ -36,7 +37,8 @@ struct cpio_entry { ...@@ -36,7 +37,8 @@ struct cpio_entry {
// uint32_t rdevminor; // uint32_t rdevminor;
// uint32_t namesize; // uint32_t namesize;
// uint32_t check; // uint32_t check;
char *filename = nullptr; // char *filename = nullptr;
CharArray filename;
void *data = nullptr; void *data = nullptr;
cpio_entry() {} cpio_entry() {}
...@@ -51,7 +53,7 @@ public: ...@@ -51,7 +53,7 @@ public:
void dump(const char *file); void dump(const char *file);
int find(const char *name); int find(const char *name);
void insert(cpio_entry *e); void insert(cpio_entry *e);
void rm(int recur, const char *name); void rm(const char *name, bool r = false);
void makedir(mode_t mode, const char *name); void makedir(mode_t mode, const char *name);
void ln(const char *target, const char *name); void ln(const char *target, const char *name);
void add(mode_t mode, const char *name, const char *file); void add(mode_t mode, const char *name, const char *file);
......
...@@ -23,10 +23,13 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) { ...@@ -23,10 +23,13 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) {
for (auto &e : arr) { for (auto &e : arr) {
if (!e) if (!e)
continue; continue;
bool fstab = (!keepverity || !keepforceencrypt) &&
!e->filename.starts_with(".backup") &&
e->filename.contains("fstab") && S_ISREG(e->mode);
if (!keepverity) { if (!keepverity) {
if (strncmp(e->filename, ".backup", 7) && strstr(e->filename, "fstab") && S_ISREG(e->mode)) { if (fstab) {
patch_verity(&e->data, &e->filesize, 1); patch_verity(&e->data, &e->filesize, 1);
} else if (strcmp(e->filename, "verity_key") == 0) { } else if (e->filename == "verity_key") {
fprintf(stderr, "Remove [verity_key]\n"); fprintf(stderr, "Remove [verity_key]\n");
delete e; delete e;
e = nullptr; e = nullptr;
...@@ -34,7 +37,7 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) { ...@@ -34,7 +37,7 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) {
} }
} }
if (!keepforceencrypt) { if (!keepforceencrypt) {
if (strstr(e->filename, "fstab") != NULL && S_ISREG(e->mode)) { if (fstab) {
patch_encryption(&e->data, &e->filesize); patch_encryption(&e->data, &e->filesize);
} }
} }
...@@ -47,27 +50,26 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) { ...@@ -47,27 +50,26 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) {
#define UNSUPPORT_PATCH 0x2 #define UNSUPPORT_PATCH 0x2
int magisk_cpio::test() { int magisk_cpio::test() {
static const char *UNSUPPORT_LIST[] = { "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc", static const char *UNSUPPORT_LIST[] = { "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc",
"boot/sbin/launch_daemonsu.sh", nullptr }; "boot/sbin/launch_daemonsu.sh" };
static const char *MAGISK_LIST[] = { ".backup/.magisk", "init.magisk.rc", static const char *MAGISK_LIST[] = { ".backup/.magisk", "init.magisk.rc",
"overlay/init.magisk.rc", nullptr }; "overlay/init.magisk.rc" };
for (int i = 0; UNSUPPORT_LIST[i]; ++i) for (auto file : UNSUPPORT_LIST)
if (find(UNSUPPORT_LIST[i]) >= 0) if (find(file) >= 0)
return UNSUPPORT_PATCH; return UNSUPPORT_PATCH;
for (int i = 0; MAGISK_LIST[i]; ++i) for (auto file : MAGISK_LIST)
if (find(MAGISK_LIST[i]) >= 0) if (find(file) >= 0)
return MAGISK_PATCH; return MAGISK_PATCH;
return STOCK_BOOT; return STOCK_BOOT;
} }
char * magisk_cpio::sha1() { char *magisk_cpio::sha1() {
char sha1[41]; char sha1[41];
for (auto &e : arr) { for (auto &e : arr) {
if (!e) continue; if (!e) continue;
if (strcmp(e->filename, "init.magisk.rc") == 0 if (e->filename == "init.magisk.rc" || e->filename == "overlay/init.magisk.rc") {
|| strcmp(e->filename, "overlay/init.magisk.rc") == 0) {
for (char *pos = (char *) e->data; pos < (char *) e->data + e->filesize; for (char *pos = (char *) e->data; pos < (char *) e->data + e->filesize;
pos = strchr(pos + 1, '\n') + 1) { pos = strchr(pos + 1, '\n') + 1) {
if (memcmp(pos, "# STOCKSHA1=", 12) == 0) { if (memcmp(pos, "# STOCKSHA1=", 12) == 0) {
...@@ -77,7 +79,7 @@ char * magisk_cpio::sha1() { ...@@ -77,7 +79,7 @@ char * magisk_cpio::sha1() {
return strdup(sha1); return strdup(sha1);
} }
} }
} else if (strcmp(e->filename, ".backup/.sha1") == 0) { } else if (e->filename == ".backup/.sha1") {
return (char *) e->data; return (char *) e->data;
} }
} }
...@@ -87,12 +89,12 @@ char * magisk_cpio::sha1() { ...@@ -87,12 +89,12 @@ char * magisk_cpio::sha1() {
void magisk_cpio::restore() { void magisk_cpio::restore() {
for (auto &e : arr) { for (auto &e : arr) {
if (!e) continue; if (!e) continue;
if (strncmp(e->filename, ".backup", 7) == 0) { if (e->filename.starts_with(".backup")) {
if (e->filename[7] == '\0') continue; if (e->filename[7] == '\0') continue;
if (e->filename[8] == '.') { if (e->filename[8] == '.') {
if (strcmp(e->filename + 8, ".rmlist") == 0) { if (strcmp(&e->filename[8], ".rmlist") == 0) {
for (int pos = 0; pos < e->filesize; pos += strlen((char *) e->data + pos) + 1) for (int pos = 0; pos < e->filesize; pos += strlen((char *) e->data + pos) + 1)
rm(false, (char *) e->data + pos); rm((char *) e->data + pos, false);
} }
} else { } else {
mv(e->filename, e->filename + 8); mv(e->filename, e->filename + 8);
...@@ -101,43 +103,41 @@ void magisk_cpio::restore() { ...@@ -101,43 +103,41 @@ void magisk_cpio::restore() {
} }
// Some known stuff we can remove // Some known stuff we can remove
rm(true, ".backup"); rm(".backup", true);
rm(true, "overlay"); rm("overlay", true);
rm(false, "sbin/magic_mask.sh"); rm("sbin/magic_mask.sh", false);
rm(false, "init.magisk.rc"); rm("init.magisk.rc", false);
rm(true, "magisk"); rm("magisk", true);
} }
void magisk_cpio::backup(Array<cpio_entry*> &bak, const char *orig, const char *sha1) { void magisk_cpio::backup(Array<cpio_entry*> &bak, const char *orig, const char *sha1) {
cpio_entry *m, *n, *rem, *cksm; cpio_entry *m, *n, *rem, *cksm;
char buf[PATH_MAX]; char buf[PATH_MAX];
int res;
bool backup;
m = new cpio_entry(); m = new cpio_entry();
m->filename = strdup(".backup"); m->filename = ".backup";
m->mode = S_IFDIR; m->mode = S_IFDIR;
bak.push_back(m); bak.push_back(m);
rem = new cpio_entry(); rem = new cpio_entry();
rem->filename = strdup(".backup/.rmlist"); rem->filename = ".backup/.rmlist";
rem->mode = S_IFREG; rem->mode = S_IFREG;
if (sha1) { if (sha1) {
fprintf(stderr, "Save SHA1: [%s] -> [.backup/.sha1]\n", sha1); fprintf(stderr, "Save SHA1: [%s] -> [.backup/.sha1]\n", sha1);
cksm = new cpio_entry(); cksm = new cpio_entry();
bak.push_back(cksm); cksm->filename = ".backup/.sha1";
cksm->filename = strdup(".backup/.sha1");
cksm->mode = S_IFREG; cksm->mode = S_IFREG;
cksm->data = strdup(sha1); cksm->data = strdup(sha1);
cksm->filesize = strlen(sha1) + 1; cksm->filesize = strlen(sha1) + 1;
bak.push_back(cksm);
} }
magisk_cpio o = magisk_cpio(orig); magisk_cpio o(orig);
// Remove possible backups in original ramdisk // Remove possible backups in original ramdisk
o.rm(true, ".backup"); o.rm(".backup", true);
rm(true, ".backup"); rm(".backup", true);
// Sort both CPIOs before comparing // Sort both CPIOs before comparing
o.sort(); o.sort();
...@@ -146,11 +146,12 @@ void magisk_cpio::backup(Array<cpio_entry*> &bak, const char *orig, const char * ...@@ -146,11 +146,12 @@ void magisk_cpio::backup(Array<cpio_entry*> &bak, const char *orig, const char *
// Start comparing // Start comparing
size_t i = 0, j = 0; size_t i = 0, j = 0;
while(i != o.arr.size() || j != arr.size()) { while(i != o.arr.size() || j != arr.size()) {
backup = false; int res;
bool backup = false;
if (i != o.arr.size() && j != arr.size()) { if (i != o.arr.size() && j != arr.size()) {
m = o.arr[i]; m = o.arr[i];
n = arr[j]; n = arr[j];
res = strcmp(m->filename, n->filename); res = m->filename.compare(n->filename);
} else if (i == o.arr.size()) { } else if (i == o.arr.size()) {
n = arr[j]; n = arr[j];
res = 1; res = 1;
...@@ -174,16 +175,15 @@ void magisk_cpio::backup(Array<cpio_entry*> &bak, const char *orig, const char * ...@@ -174,16 +175,15 @@ void magisk_cpio::backup(Array<cpio_entry*> &bak, const char *orig, const char *
} else { } else {
// Something new in ramdisk, record in rem // Something new in ramdisk, record in rem
++j; ++j;
rem->data = xrealloc(rem->data, rem->filesize + strlen(n->filename) + 1); rem->data = xrealloc(rem->data, rem->filesize + n->filename.size());
memcpy((char *) rem->data + rem->filesize, n->filename, strlen(n->filename) + 1); memcpy((char *) rem->data + rem->filesize, n->filename, n->filename.size());
rem->filesize += strlen(n->filename) + 1; rem->filesize += n->filename.size();
fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename); fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename.c_str());
} }
if (backup) { if (backup) {
sprintf(buf, ".backup/%s", m->filename); sprintf(buf, ".backup/%s", m->filename.c_str());
fprintf(stderr, "[%s] -> [%s]\n", m->filename, buf); fprintf(stderr, "[%s] -> [%s]\n", m->filename.c_str(), buf);
free(m->filename); m->filename = buf;
m->filename = strdup(buf);
bak.push_back(m); bak.push_back(m);
// NULL the original entry, so it won't be freed // NULL the original entry, so it won't be freed
o.arr[i - 1] = nullptr; o.arr[i - 1] = nullptr;
...@@ -202,7 +202,7 @@ int cpio_commands(int argc, char *argv[]) { ...@@ -202,7 +202,7 @@ int cpio_commands(int argc, char *argv[]) {
++argv; ++argv;
--argc; --argc;
magisk_cpio cpio = magisk_cpio(incpio); magisk_cpio cpio(incpio);
int cmdc; int cmdc;
char *cmdv[6]; char *cmdv[6];
...@@ -230,17 +230,17 @@ int cpio_commands(int argc, char *argv[]) { ...@@ -230,17 +230,17 @@ int cpio_commands(int argc, char *argv[]) {
free(sha1); free(sha1);
return 0; return 0;
} else if (cmdc >= 2 && strcmp(cmdv[0], "backup") == 0) { } else if (cmdc >= 2 && strcmp(cmdv[0], "backup") == 0) {
auto bak = Array<cpio_entry*>(); Array<cpio_entry*> bak;
cpio.backup(bak, cmdv[1], cmdv[2]); cpio.backup(bak, cmdv[1], cmdv[2]);
cpio.insert(bak); cpio.insert(bak);
} else if (cmdc >= 4 && strcmp(cmdv[0], "magisk") == 0) { } else if (cmdc >= 4 && strcmp(cmdv[0], "magisk") == 0) {
cpio.patch(strcmp(cmdv[2], "true") == 0, strcmp(cmdv[3], "true") == 0); cpio.patch(strcmp(cmdv[2], "true") == 0, strcmp(cmdv[3], "true") == 0);
auto bak = Array<cpio_entry*>(); Array<cpio_entry*> bak;
cpio.backup(bak, cmdv[1], cmdv[4]); cpio.backup(bak, cmdv[1], cmdv[4]);
auto e = new cpio_entry(); auto e = new cpio_entry();
e->filename = strdup(".backup/.magisk"); e->filename = ".backup/.magisk";
e->mode = S_IFREG; e->mode = S_IFREG;
e->data = xmalloc(50); e->data = xmalloc(50);
snprintf((char *) e->data, 50, "KEEPVERITY=%s\nKEEPFORCEENCRYPT=%s\n", cmdv[2], cmdv[3]); snprintf((char *) e->data, 50, "KEEPVERITY=%s\nKEEPFORCEENCRYPT=%s\n", cmdv[2], cmdv[3]);
...@@ -249,8 +249,8 @@ int cpio_commands(int argc, char *argv[]) { ...@@ -249,8 +249,8 @@ int cpio_commands(int argc, char *argv[]) {
cpio.insert(bak); cpio.insert(bak);
cpio.insert(e); cpio.insert(e);
} else if (cmdc >= 2 && strcmp(cmdv[0], "rm") == 0) { } else if (cmdc >= 2 && strcmp(cmdv[0], "rm") == 0) {
int recur = cmdc > 2 && strcmp(cmdv[1], "-r") == 0; bool r = cmdc > 2 && strcmp(cmdv[1], "-r") == 0;
cpio.rm(recur, cmdv[1 + recur]); cpio.rm(cmdv[1 + r], r);
} else if (cmdc == 3 && strcmp(cmdv[0], "mv") == 0) { } else if (cmdc == 3 && strcmp(cmdv[0], "mv") == 0) {
cpio.mv(cmdv[1], cmdv[2]); cpio.mv(cmdv[1], cmdv[2]);
} else if (cmdc == 3 && strcmp(cmdv[0], "patch") == 0) { } else if (cmdc == 3 && strcmp(cmdv[0], "patch") == 0) {
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include "daemon.h" #include "daemon.h"
#include "db.h" #include "db.h"
auto hide_list = Array<char *>(); Array<CharArray> hide_list;
static const char *prop_key[] = static const char *prop_key[] =
{ "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", { "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked",
...@@ -46,14 +46,10 @@ void hide_sensitive_props() { ...@@ -46,14 +46,10 @@ void hide_sensitive_props() {
LOGI("hide_utils: Hiding sensitive props\n"); LOGI("hide_utils: Hiding sensitive props\n");
// Hide all sensitive props // Hide all sensitive props
char *value;
for (int i = 0; prop_key[i]; ++i) { for (int i = 0; prop_key[i]; ++i) {
value = getprop(prop_key[i]); CharArray value = getprop(prop_key[i]);
if (value) { if (!value.empty() && value != prop_value[i])
if (strcmp(value, prop_value[i]) != 0)
setprop(prop_key[i], prop_value[i], false); setprop(prop_key[i], prop_value[i], false);
free(value);
}
} }
} }
...@@ -139,14 +135,12 @@ void clean_magisk_props() { ...@@ -139,14 +135,12 @@ void clean_magisk_props() {
}, nullptr, false); }, nullptr, false);
} }
static int add_list(sqlite3 *db, char *proc) { static int add_list(sqlite3 *db, const char *proc) {
for (auto &s : hide_list) { for (auto &s : hide_list) {
// They should be unique // They should be unique
if (strcmp(s, proc) == 0) { if (s == proc)
free(proc);
return HIDE_ITEM_EXIST; return HIDE_ITEM_EXIST;
} }
}
LOGI("hide_list add: [%s]\n", proc); LOGI("hide_list add: [%s]\n", proc);
kill_process(proc); kill_process(proc);
...@@ -164,7 +158,7 @@ static int add_list(sqlite3 *db, char *proc) { ...@@ -164,7 +158,7 @@ static int add_list(sqlite3 *db, char *proc) {
return DAEMON_SUCCESS; return DAEMON_SUCCESS;
} }
int add_list(char *proc) { int add_list(const char *proc) {
sqlite3 *db = get_magiskdb(); sqlite3 *db = get_magiskdb();
if (db) { if (db) {
int ret = add_list(db, proc); int ret = add_list(db, proc);
...@@ -175,20 +169,20 @@ int add_list(char *proc) { ...@@ -175,20 +169,20 @@ int add_list(char *proc) {
} }
int add_list(int client) { int add_list(int client) {
return add_list(read_string(client)); char *proc = read_string(client);
int ret = add_list(proc);
free(proc);
return ret;
} }
static int rm_list(char *proc) { static int rm_list(const char *proc) {
int ret = DAEMON_ERROR;
// Update list in critical region // Update list in critical region
bool do_rm = false; bool do_rm = false;
pthread_mutex_lock(&list_lock); pthread_mutex_lock(&list_lock);
for (auto it = hide_list.begin(); it != hide_list.end(); ++it) { for (auto it = hide_list.begin(); it != hide_list.end(); ++it) {
if (strcmp(*it, proc) == 0) { if (*it == proc) {
do_rm = true; do_rm = true;
LOGI("hide_list rm: [%s]\n", proc); LOGI("hide_list rm: [%s]\n", proc);
free(*it);
hide_list.erase(it); hide_list.erase(it);
break; break;
} }
...@@ -199,45 +193,44 @@ static int rm_list(char *proc) { ...@@ -199,45 +193,44 @@ static int rm_list(char *proc) {
kill_process(proc); kill_process(proc);
sqlite3 *db = get_magiskdb(); sqlite3 *db = get_magiskdb();
if (db == nullptr) if (db == nullptr)
goto error; return DAEMON_ERROR;
char sql[128]; char sql[128];
sprintf(sql, "DELETE FROM hidelist WHERE process='%s'", proc); sprintf(sql, "DELETE FROM hidelist WHERE process='%s'", proc);
sqlite3_exec(db, sql, nullptr, nullptr, nullptr); sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
sqlite3_close_v2(db); sqlite3_close_v2(db);
ret = DAEMON_SUCCESS; return DAEMON_SUCCESS;
} else { } else {
ret = HIDE_ITEM_NOT_EXIST; return HIDE_ITEM_NOT_EXIST;
} }
error:
free(proc);
return ret;
} }
int rm_list(int client) { int rm_list(int client) {
return rm_list(read_string(client)); char *proc = read_string(client);
int ret = rm_list(proc);
free(proc);
return ret;
} }
#define LEGACY_LIST MOUNTPOINT "/.core/hidelist" #define LEGACY_LIST MOUNTPOINT "/.core/hidelist"
int init_list() { bool init_list() {
LOGD("hide_list: initialize\n"); LOGD("hide_list: initialize\n");
sqlite3 *db = get_magiskdb(); sqlite3 *db = get_magiskdb();
if (db == nullptr) if (db == nullptr)
return 1; return false;
sqlite3_exec(db, "SELECT process FROM hidelist", sqlite3_exec(db, "SELECT process FROM hidelist",
[] (auto, auto, char **data, auto) -> int [] (auto, auto, char **data, auto) -> int
{ {
LOGI("hide_list: [%s]\n", data[0]); LOGI("hide_list: [%s]\n", data[0]);
hide_list.push_back(strdup(data[0])); hide_list.push_back(data[0]);
return 0; return 0;
}, nullptr, nullptr); }, nullptr, nullptr);
// Migrate old hide list into database // Migrate old hide list into database
if (access(LEGACY_LIST, R_OK) == 0) { if (access(LEGACY_LIST, R_OK) == 0) {
auto tmp = Array<char *>(); Array<CharArray> tmp;
file_to_array(LEGACY_LIST, tmp); file_to_array(LEGACY_LIST, tmp);
for (auto &s : tmp) for (auto &s : tmp)
add_list(db, s); add_list(db, s);
...@@ -245,14 +238,7 @@ int init_list() { ...@@ -245,14 +238,7 @@ int init_list() {
} }
sqlite3_close_v2(db); sqlite3_close_v2(db);
return 0; return true;
}
int destroy_list() {
for (auto &str : hide_list)
free(str);
hide_list.clear();
return 0;
} }
void ls_list(int client) { void ls_list(int client) {
......
...@@ -54,11 +54,11 @@ int launch_magiskhide() { ...@@ -54,11 +54,11 @@ int launch_magiskhide() {
pthread_mutex_init(&list_lock, nullptr); pthread_mutex_init(&list_lock, nullptr);
// Initialize the hide list // Initialize the hide list
if (init_list()) if (!init_list())
goto error; goto error;
// Add SafetyNet by default // Add SafetyNet by default
add_list(strdup("com.google.android.gms.unstable")); add_list("com.google.android.gms.unstable");
// Get thread reference // Get thread reference
proc_monitor_thread = pthread_self(); proc_monitor_thread = pthread_self();
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "daemon.h" #include "daemon.h"
#include "array.h" #include "array.h"
#include "CharArray.h"
#define TERM_THREAD SIGUSR1 #define TERM_THREAD SIGUSR1
...@@ -24,13 +25,12 @@ void hide_sensitive_props(); ...@@ -24,13 +25,12 @@ void hide_sensitive_props();
void clean_magisk_props(); void clean_magisk_props();
// List managements // List managements
int add_list(char *proc); int add_list(const char *proc);
int init_list(); bool init_list();
int destroy_list();
extern int hide_enabled; extern int hide_enabled;
extern pthread_mutex_t list_lock; extern pthread_mutex_t list_lock;
extern Array<char *> hide_list; extern Array<CharArray> hide_list;
enum { enum {
LAUNCH_MAGISKHIDE, LAUNCH_MAGISKHIDE,
......
...@@ -27,13 +27,13 @@ static int sockfd = -1; ...@@ -27,13 +27,13 @@ static int sockfd = -1;
// Workaround for the lack of pthread_cancel // Workaround for the lack of pthread_cancel
static void term_thread(int) { static void term_thread(int) {
LOGD("proc_monitor: running cleanup\n"); LOGD("proc_monitor: running cleanup\n");
destroy_list(); hide_list.clear(true);
hide_enabled = 0; hide_enabled = 0;
close(sockfd); close(sockfd);
sockfd = -1; sockfd = -1;
pthread_mutex_destroy(&list_lock); pthread_mutex_destroy(&list_lock);
LOGD("proc_monitor: terminating\n"); LOGD("proc_monitor: terminating\n");
pthread_exit(NULL); pthread_exit(nullptr);
} }
static int read_ns(const int pid, struct stat *st) { static int read_ns(const int pid, struct stat *st) {
...@@ -63,7 +63,7 @@ static void hide_daemon(int pid) { ...@@ -63,7 +63,7 @@ static void hide_daemon(int pid) {
LOGD("hide_daemon: start unmount for pid=[%d]\n", pid); LOGD("hide_daemon: start unmount for pid=[%d]\n", pid);
char buffer[PATH_MAX]; char buffer[PATH_MAX];
auto mounts = Array<char *>(); Array<CharArray> mounts;
manage_selinux(); manage_selinux();
clean_magisk_props(); clean_magisk_props();
...@@ -76,11 +76,10 @@ static void hide_daemon(int pid) { ...@@ -76,11 +76,10 @@ static void hide_daemon(int pid) {
// Unmount dummy skeletons and /sbin links // Unmount dummy skeletons and /sbin links
for (auto &s : mounts) { for (auto &s : mounts) {
if (strstr(s, "tmpfs /system/") || strstr(s, "tmpfs /vendor/") || strstr(s, "tmpfs /sbin")) { if (s.contains("tmpfs /system/") || s.contains("tmpfs /vendor/") || s.contains("tmpfs /sbin")) {
sscanf(s, "%*s %4096s", buffer); sscanf(s, "%*s %4096s", buffer);
lazy_unmount(buffer); lazy_unmount(buffer);
} }
free(s);
} }
mounts.clear(); mounts.clear();
...@@ -90,13 +89,11 @@ static void hide_daemon(int pid) { ...@@ -90,13 +89,11 @@ static void hide_daemon(int pid) {
// Unmount everything under /system, /vendor, and loop mounts // Unmount everything under /system, /vendor, and loop mounts
for (auto &s : mounts) { for (auto &s : mounts) {
if (strstr(s, "/dev/block/loop") || strstr(s, " /system/") || strstr(s, " /vendor/")) { if (s.contains("/dev/block/loop") || s.contains(" /system/") || s.contains(" /vendor/")) {
sscanf(s, "%*s %4096s", buffer); sscanf(s, "%*s %4096s", buffer);
lazy_unmount(buffer); lazy_unmount(buffer);
} }
free(s);
} }
mounts.clear();
exit: exit:
// Send resume signal // Send resume signal
...@@ -159,7 +156,7 @@ void proc_monitor() { ...@@ -159,7 +156,7 @@ void proc_monitor() {
bool hide = false; bool hide = false;
pthread_mutex_lock(&list_lock); pthread_mutex_lock(&list_lock);
for (auto &s : hide_list) { for (auto &s : hide_list) {
if (strcmp(proc, s) == 0) { if (s == proc) {
hide = true; hide = true;
break; break;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef MAGISK_PROPS_H #ifndef MAGISK_PROPS_H
#define MAGISK_PROPS_H #define MAGISK_PROPS_H
#include <CharArray.h>
#include "resetprop/private/system_properties.h" #include "resetprop/private/system_properties.h"
#include "logging.h" #include "logging.h"
...@@ -48,7 +49,7 @@ struct read_cb_t { ...@@ -48,7 +49,7 @@ struct read_cb_t {
extern bool use_pb; extern bool use_pb;
char *persist_getprop(const char *name); CharArray persist_getprop(const char *name);
void persist_getprop(read_cb_t *read_cb); void persist_getprop(read_cb_t *read_cb);
bool persist_deleteprop(const char *name); bool persist_deleteprop(const char *name);
void collect_props(const char *name, const char *value, void *v_plist); void collect_props(const char *name, const char *value, void *v_plist);
......
...@@ -190,21 +190,21 @@ void persist_getprop(read_cb_t *read_cb) { ...@@ -190,21 +190,21 @@ void persist_getprop(read_cb_t *read_cb) {
} }
} }
char *persist_getprop(const char *name) { CharArray persist_getprop(const char *name) {
prop_t prop(name); prop_t prop(name);
if (use_pb) { if (use_pb) {
read_cb_t read_cb(pb_getprop_cb, &prop); read_cb_t read_cb(pb_getprop_cb, &prop);
pb_getprop(&read_cb); pb_getprop(&read_cb);
if (prop.value[0]) if (prop.value[0])
return strdup(prop.value); return prop.value;
} else { } else {
// Try to read from file // Try to read from file
char value[PROP_VALUE_MAX]; char value[PROP_VALUE_MAX];
file_getprop(name, value); file_getprop(name, value);
if (value[0]) if (value[0])
return strdup(value); return value;
} }
return nullptr; return CharArray();
} }
bool persist_deleteprop(const char *name) { bool persist_deleteprop(const char *name) {
......
...@@ -130,18 +130,18 @@ int prop_exist(const char *name) { ...@@ -130,18 +130,18 @@ int prop_exist(const char *name) {
} }
// Get prop by name, return string (should free manually!) // Get prop by name, return string (should free manually!)
char *getprop(const char *name, bool persist) { CharArray getprop(const char *name, bool persist) {
if (!check_legal_property_name(name) || init_resetprop()) if (!check_legal_property_name(name) || init_resetprop())
return nullptr; return nullptr;
const prop_info *pi = __system_property_find(name); const prop_info *pi = __system_property_find(name);
if (pi == nullptr) { if (pi == nullptr) {
if (persist && strncmp(name, "persist.", 8) == 0) { if (persist && strncmp(name, "persist.", 8) == 0) {
char *value = persist_getprop(name); CharArray value = persist_getprop(name);
if (value) if (!value.empty())
return value; return value;
} }
LOGD("resetprop: prop [%s] does not exist\n", name); LOGD("resetprop: prop [%s] does not exist\n", name);
return nullptr; return CharArray();
} else { } else {
char value[PROP_VALUE_MAX]; char value[PROP_VALUE_MAX];
read_cb_t read_cb; read_cb_t read_cb;
...@@ -149,7 +149,7 @@ char *getprop(const char *name, bool persist) { ...@@ -149,7 +149,7 @@ char *getprop(const char *name, bool persist) {
read_cb.arg = value; read_cb.arg = value;
read_props(pi, &read_cb); read_props(pi, &read_cb);
LOGD("resetprop: getprop [%s]: [%s]\n", name, value); LOGD("resetprop: getprop [%s]: [%s]\n", name, value);
return strdup(value); return value;
} }
} }
...@@ -254,7 +254,8 @@ int resetprop_main(int argc, char *argv[]) { ...@@ -254,7 +254,8 @@ int resetprop_main(int argc, char *argv[]) {
log_cb.d = [](auto fmt, auto ap) -> int { return verbose ? vfprintf(stderr, fmt, ap) : 0; }; log_cb.d = [](auto fmt, auto ap) -> int { return verbose ? vfprintf(stderr, fmt, ap) : 0; };
bool trigger = true, persist = false; bool trigger = true, persist = false;
char *argv0 = argv[0], *prop; char *argv0 = argv[0];
CharArray prop;
--argc; --argc;
++argv; ++argv;
...@@ -297,10 +298,9 @@ int resetprop_main(int argc, char *argv[]) { ...@@ -297,10 +298,9 @@ int resetprop_main(int argc, char *argv[]) {
print_props(persist); print_props(persist);
return 0; return 0;
case 1: case 1:
prop = getprop(argv[0], persist); prop = utils::move(getprop(argv[0], persist));
if (prop == nullptr) return 1; if (!prop) return 1;
printf("%s\n", prop); printf("%s\n", prop.c_str());
free(prop);
return 0; return 0;
case 2: case 2:
return setprop(argv[0], argv[1], trigger); return setprop(argv[0], argv[1], trigger);
......
...@@ -9,6 +9,7 @@ LOCAL_SRC_FILES := \ ...@@ -9,6 +9,7 @@ LOCAL_SRC_FILES := \
selinux.cpp \ selinux.cpp \
logging.cpp \ logging.cpp \
xwrap.cpp \ xwrap.cpp \
CharArray.cpp \
vector.c vector.c
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
#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 strstr(_buf, s) != nullptr;
}
bool CharArray::starts_with(const char *s) const {
return compare(s, strlen(s)) == 0;
}
bool CharArray::empty() const {
return _buf == nullptr || _buf[0] == '\0';
}
...@@ -388,7 +388,7 @@ void write_zero(int fd, size_t size) { ...@@ -388,7 +388,7 @@ void write_zero(int fd, size_t size) {
lseek(fd, pos + size, SEEK_SET); lseek(fd, pos + size, SEEK_SET);
} }
int file_to_array(const char *filename, Array<char *> &arr) { int file_to_array(const char *filename, Array<CharArray> &arr) {
if (access(filename, R_OK) != 0) if (access(filename, R_OK) != 0)
return 1; return 1;
char *line = nullptr; char *line = nullptr;
...@@ -404,8 +404,8 @@ int file_to_array(const char *filename, Array<char *> &arr) { ...@@ -404,8 +404,8 @@ int file_to_array(const char *filename, Array<char *> &arr) {
if (line[read - 1] == '\n') if (line[read - 1] == '\n')
line[read - 1] = '\0'; line[read - 1] = '\0';
arr.push_back(line); arr.push_back(line);
line = nullptr;
} }
fclose(fp); fclose(fp);
free(line);
return 0; return 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;
};
#pragma once #pragma once
#include <stdlib.h> #include <stdlib.h>
#include "cpputils.h"
template <class T> template <class T>
class Array { class Array {
...@@ -72,7 +73,7 @@ public: ...@@ -72,7 +73,7 @@ public:
if (_capacity) { if (_capacity) {
_data = new T[_capacity]; _data = new T[_capacity];
for(int i = 0; i < _size; ++i) for(int i = 0; i < _size; ++i)
_data[i] = (T&&) a[i]; _data[i] = utils::move(a[i]);
} }
return *this; return *this;
} }
...@@ -101,7 +102,7 @@ public: ...@@ -101,7 +102,7 @@ public:
void push_back(T&& x) { void push_back(T&& x) {
if(_size == _capacity) if(_size == _capacity)
expand(); expand();
_data[_size] = (T&&) x; _data[_size] = utils::move(x);
++_size; ++_size;
} }
...@@ -114,7 +115,7 @@ public: ...@@ -114,7 +115,7 @@ public:
if (_size == 0 || d < _data || d >= _data + _size) if (_size == 0 || d < _data || d >= _data + _size)
return false; return false;
for (; d < _data + _size - 1; ++d) for (; d < _data + _size - 1; ++d)
*d = (T&&) *(d + 1); *d = utils::move(*(d + 1));
--_size; --_size;
return true; return true;
...@@ -130,9 +131,16 @@ public: ...@@ -130,9 +131,16 @@ public:
return false; return false;
} }
void clear() { _size = 0; } void clear(bool dealloc = false) {
_size = 0;
if (dealloc) {
_capacity = 0;
delete [] _data;
_data = nullptr;
}
}
void sort() const { void sort() {
qsort(_data, _size, sizeof(T), compare); qsort(_data, _size, sizeof(T), compare);
} }
...@@ -161,7 +169,7 @@ private: ...@@ -161,7 +169,7 @@ private:
T* temp = _data; T* temp = _data;
_data = new T[_capacity]; _data = new T[_capacity];
for(int i = 0; i < _size; ++i) for(int i = 0; i < _size; ++i)
_data[i] = (T&&) temp[i]; _data[i] = utils::move(temp[i]);
delete [] temp; delete [] temp;
} }
}; };
......
#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);
}
}
\ No newline at end of file
...@@ -12,9 +12,15 @@ ...@@ -12,9 +12,15 @@
#include <sys/stat.h> #include <sys/stat.h>
#ifdef __cplusplus #ifdef __cplusplus
// C++ only
#include "array.h" #include "array.h"
int file_to_array(const char* filename, Array<char *> &arr); #include "CharArray.h"
#include "cpputils.h"
int file_to_array(const char *filename, Array<CharArray> &arr);
char *strdup2(const char *s, size_t *size = nullptr);
extern "C" { extern "C" {
#endif #endif
......
...@@ -268,3 +268,11 @@ int exec_command(int err, int *fd, void (*cb)(void), const char *argv0, ...) { ...@@ -268,3 +268,11 @@ int exec_command(int err, int *fd, void (*cb)(void), const char *argv0, ...) {
va_end(argv); va_end(argv);
return pid; return pid;
} }
char *strdup2(const char *s, size_t *size) {
size_t l = strlen(s) + 1;
char *buf = new char[l];
memcpy(buf, s, l);
if (size) *size = l;
return buf;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment