Convert indentation to spaces

The tab war is lost
This commit is contained in:
topjohnwu
2020-12-30 22:11:24 -08:00
parent 947a7d6a2f
commit f9bde347bc
78 changed files with 10945 additions and 10945 deletions

View File

@@ -5,13 +5,13 @@ LOCAL_MODULE:= libutils
LOCAL_C_INCLUDES := jni/include $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SRC_FILES := \
missing.cpp \
new.cpp \
files.cpp \
misc.cpp \
selinux.cpp \
logging.cpp \
xwrap.cpp \
stream.cpp
missing.cpp \
new.cpp \
files.cpp \
misc.cpp \
selinux.cpp \
logging.cpp \
xwrap.cpp \
stream.cpp
include $(BUILD_STATIC_LIBRARY)

View File

@@ -10,264 +10,264 @@
using namespace std;
struct cpio_newc_header {
char magic[6];
char ino[8];
char mode[8];
char uid[8];
char gid[8];
char nlink[8];
char mtime[8];
char filesize[8];
char devmajor[8];
char devminor[8];
char rdevmajor[8];
char rdevminor[8];
char namesize[8];
char check[8];
char magic[6];
char ino[8];
char mode[8];
char uid[8];
char gid[8];
char nlink[8];
char mtime[8];
char filesize[8];
char devmajor[8];
char devminor[8];
char rdevmajor[8];
char rdevminor[8];
char namesize[8];
char check[8];
} __attribute__((packed));
static uint32_t x8u(const char *hex) {
uint32_t val, inpos = 8, outpos;
char pattern[6];
uint32_t val, inpos = 8, outpos;
char pattern[6];
while (*hex == '0') {
hex++;
if (!--inpos) return 0;
}
// Because scanf gratuitously treats %*X differently than printf does.
sprintf(pattern, "%%%dx%%n", inpos);
sscanf(hex, pattern, &val, &outpos);
if (inpos != outpos)
LOGE("bad cpio header\n");
while (*hex == '0') {
hex++;
if (!--inpos) return 0;
}
// Because scanf gratuitously treats %*X differently than printf does.
sprintf(pattern, "%%%dx%%n", inpos);
sscanf(hex, pattern, &val, &outpos);
if (inpos != outpos)
LOGE("bad cpio header\n");
return val;
return val;
}
cpio_entry_base::cpio_entry_base(const cpio_newc_header *h)
: mode(x8u(h->mode)), uid(x8u(h->uid)), gid(x8u(h->gid)), filesize(x8u(h->filesize)) {};
void cpio::dump(const char *file) {
fprintf(stderr, "Dump cpio: [%s]\n", file);
dump(xfopen(file, "we"));
fprintf(stderr, "Dump cpio: [%s]\n", file);
dump(xfopen(file, "we"));
}
void cpio::rm(entry_map::iterator &it) {
fprintf(stderr, "Remove [%s]\n", it->first.data());
entries.erase(it);
fprintf(stderr, "Remove [%s]\n", it->first.data());
entries.erase(it);
}
void cpio::rm(const char *name, bool r) {
size_t len = strlen(name);
for (auto it = entries.begin(); it != entries.end();) {
if (it->first.compare(0, len, name) == 0 &&
((r && it->first[len] == '/') || it->first[len] == '\0')) {
auto tmp = it;
++it;
rm(tmp);
if (!r) return;
} else {
++it;
}
}
size_t len = strlen(name);
for (auto it = entries.begin(); it != entries.end();) {
if (it->first.compare(0, len, name) == 0 &&
((r && it->first[len] == '/') || it->first[len] == '\0')) {
auto tmp = it;
++it;
rm(tmp);
if (!r) return;
} else {
++it;
}
}
}
static void extract_entry(const entry_map::value_type &e, const char *file) {
fprintf(stderr, "Extract [%s] to [%s]\n", e.first.data(), file);
unlink(file);
rmdir(file);
if (S_ISDIR(e.second->mode)) {
mkdir(file, e.second->mode & 0777);
} else if (S_ISREG(e.second->mode)) {
int fd = creat(file, e.second->mode & 0777);
xwrite(fd, e.second->data, e.second->filesize);
fchown(fd, e.second->uid, e.second->gid);
close(fd);
} else if (S_ISLNK(e.second->mode)) {
auto target = strndup((char *) e.second->data, e.second->filesize);
symlink(target, file);
free(target);
}
fprintf(stderr, "Extract [%s] to [%s]\n", e.first.data(), file);
unlink(file);
rmdir(file);
if (S_ISDIR(e.second->mode)) {
mkdir(file, e.second->mode & 0777);
} else if (S_ISREG(e.second->mode)) {
int fd = creat(file, e.second->mode & 0777);
xwrite(fd, e.second->data, e.second->filesize);
fchown(fd, e.second->uid, e.second->gid);
close(fd);
} else if (S_ISLNK(e.second->mode)) {
auto target = strndup((char *) e.second->data, e.second->filesize);
symlink(target, file);
free(target);
}
}
void cpio::extract() {
for (auto &e : entries)
extract_entry(e, e.first.data());
for (auto &e : entries)
extract_entry(e, e.first.data());
}
bool cpio::extract(const char *name, const char *file) {
auto it = entries.find(name);
if (it != entries.end()) {
extract_entry(*it, file);
return true;
}
fprintf(stderr, "Cannot find the file entry [%s]\n", name);
return false;
auto it = entries.find(name);
if (it != entries.end()) {
extract_entry(*it, file);
return true;
}
fprintf(stderr, "Cannot find the file entry [%s]\n", name);
return false;
}
bool cpio::exists(const char *name) {
return entries.count(name) != 0;
return entries.count(name) != 0;
}
#define do_out(buf, len) pos += fwrite(buf, 1, len, out);
#define out_align() do_out(zeros, align_off(pos, 4))
void cpio::dump(FILE *out) {
size_t pos = 0;
unsigned inode = 300000;
char header[111];
char zeros[4] = {0};
for (auto &e : entries) {
sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
inode++, // e->ino
e.second->mode,
e.second->uid,
e.second->gid,
1, // e->nlink
0, // e->mtime
e.second->filesize,
0, // e->devmajor
0, // e->devminor
0, // e->rdevmajor
0, // e->rdevminor
(uint32_t) e.first.size() + 1,
0 // e->check
);
do_out(header, 110);
do_out(e.first.data(), e.first.size() + 1);
out_align();
if (e.second->filesize) {
do_out(e.second->data, e.second->filesize);
out_align();
}
}
// Write trailer
sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
inode++, 0755, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 0);
do_out(header, 110);
do_out("TRAILER!!!\0", 11);
out_align();
fclose(out);
size_t pos = 0;
unsigned inode = 300000;
char header[111];
char zeros[4] = {0};
for (auto &e : entries) {
sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
inode++, // e->ino
e.second->mode,
e.second->uid,
e.second->gid,
1, // e->nlink
0, // e->mtime
e.second->filesize,
0, // e->devmajor
0, // e->devminor
0, // e->rdevmajor
0, // e->rdevminor
(uint32_t) e.first.size() + 1,
0 // e->check
);
do_out(header, 110);
do_out(e.first.data(), e.first.size() + 1);
out_align();
if (e.second->filesize) {
do_out(e.second->data, e.second->filesize);
out_align();
}
}
// Write trailer
sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
inode++, 0755, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 0);
do_out(header, 110);
do_out("TRAILER!!!\0", 11);
out_align();
fclose(out);
}
cpio_rw::cpio_rw(const char *file) {
load_cpio(file);
load_cpio(file);
}
void cpio_rw::load_cpio(const char *file) {
char *buf;
size_t sz;
mmap_ro(file, buf, sz);
fprintf(stderr, "Loading cpio: [%s]\n", file);
load_cpio(buf, sz);
munmap(buf, sz);
char *buf;
size_t sz;
mmap_ro(file, buf, sz);
fprintf(stderr, "Loading cpio: [%s]\n", file);
load_cpio(buf, sz);
munmap(buf, sz);
}
void cpio_rw::insert(cpio_entry *e) {
auto ex = entries.extract(e->filename);
if (!ex) {
entries[e->filename].reset(e);
} else {
ex.key() = e->filename;
ex.mapped().reset(e);
entries.insert(std::move(ex));
}
auto ex = entries.extract(e->filename);
if (!ex) {
entries[e->filename].reset(e);
} else {
ex.key() = e->filename;
ex.mapped().reset(e);
entries.insert(std::move(ex));
}
}
void cpio_rw::add(mode_t mode, const char *name, const char *file) {
void *buf;
size_t sz;
mmap_ro(file, buf, sz);
auto e = new cpio_entry(name, S_IFREG | mode);
e->filesize = sz;
e->data = xmalloc(sz);
memcpy(e->data, buf, sz);
munmap(buf, sz);
insert(e);
fprintf(stderr, "Add entry [%s] (%04o)\n", name, mode);
void *buf;
size_t sz;
mmap_ro(file, buf, sz);
auto e = new cpio_entry(name, S_IFREG | mode);
e->filesize = sz;
e->data = xmalloc(sz);
memcpy(e->data, buf, sz);
munmap(buf, sz);
insert(e);
fprintf(stderr, "Add entry [%s] (%04o)\n", name, mode);
}
void cpio_rw::mkdir(mode_t mode, const char *name) {
insert(new cpio_entry(name, S_IFDIR | mode));
fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode);
insert(new cpio_entry(name, S_IFDIR | mode));
fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode);
}
void cpio_rw::ln(const char *target, const char *name) {
auto e = new cpio_entry(name, S_IFLNK);
e->filesize = strlen(target);
e->data = strdup(target);
insert(e);
fprintf(stderr, "Create symlink [%s] -> [%s]\n", name, target);
auto e = new cpio_entry(name, S_IFLNK);
e->filesize = strlen(target);
e->data = strdup(target);
insert(e);
fprintf(stderr, "Create symlink [%s] -> [%s]\n", name, target);
}
void cpio_rw::mv(entry_map::iterator &it, const char *to) {
fprintf(stderr, "Move [%s] -> [%s]\n", it->first.data(), to);
auto ex = entries.extract(it);
auto &name = static_cast<cpio_entry*>(ex.mapped().get())->filename;
name = to;
ex.key() = name;
entries.erase(name);
entries.insert(std::move(ex));
fprintf(stderr, "Move [%s] -> [%s]\n", it->first.data(), to);
auto ex = entries.extract(it);
auto &name = static_cast<cpio_entry*>(ex.mapped().get())->filename;
name = to;
ex.key() = name;
entries.erase(name);
entries.insert(std::move(ex));
}
bool cpio_rw::mv(const char *from, const char *to) {
auto it = entries.find(from);
if (it != entries.end()) {
mv(it, to);
return true;
}
fprintf(stderr, "Cannot find entry %s\n", from);
return false;
auto it = entries.find(from);
if (it != entries.end()) {
mv(it, to);
return true;
}
fprintf(stderr, "Cannot find entry %s\n", from);
return false;
}
#define pos_align(p) p = do_align(p, 4)
void cpio_rw::load_cpio(const char *buf, size_t sz) {
size_t pos = 0;
const cpio_newc_header *header;
unique_ptr<cpio_entry> entry;
while (pos < sz) {
header = reinterpret_cast<const cpio_newc_header *>(buf + pos);
entry = make_unique<cpio_entry>(header);
pos += sizeof(*header);
string_view name_view(buf + pos);
pos += x8u(header->namesize);
pos_align(pos);
if (name_view == "." || name_view == "..")
continue;
if (name_view == "TRAILER!!!")
break;
entry->filename = name_view;
entry->data = xmalloc(entry->filesize);
memcpy(entry->data, buf + pos, entry->filesize);
pos += entry->filesize;
entries[entry->filename] = std::move(entry);
pos_align(pos);
}
size_t pos = 0;
const cpio_newc_header *header;
unique_ptr<cpio_entry> entry;
while (pos < sz) {
header = reinterpret_cast<const cpio_newc_header *>(buf + pos);
entry = make_unique<cpio_entry>(header);
pos += sizeof(*header);
string_view name_view(buf + pos);
pos += x8u(header->namesize);
pos_align(pos);
if (name_view == "." || name_view == "..")
continue;
if (name_view == "TRAILER!!!")
break;
entry->filename = name_view;
entry->data = xmalloc(entry->filesize);
memcpy(entry->data, buf + pos, entry->filesize);
pos += entry->filesize;
entries[entry->filename] = std::move(entry);
pos_align(pos);
}
}
cpio_mmap::cpio_mmap(const char *file) {
mmap_ro(file, buf, sz);
fprintf(stderr, "Loading cpio: [%s]\n", file);
size_t pos = 0;
cpio_newc_header *header;
unique_ptr<cpio_entry_base> entry;
while (pos < sz) {
header = (cpio_newc_header *)(buf + pos);
entry = make_unique<cpio_entry_base>(header);
pos += sizeof(*header);
string_view name_view(buf + pos);
pos += x8u(header->namesize);
pos_align(pos);
if (name_view == "." || name_view == "..")
continue;
if (name_view == "TRAILER!!!")
break;
entry->data = buf + pos;
pos += entry->filesize;
entries[name_view] = std::move(entry);
pos_align(pos);
}
mmap_ro(file, buf, sz);
fprintf(stderr, "Loading cpio: [%s]\n", file);
size_t pos = 0;
cpio_newc_header *header;
unique_ptr<cpio_entry_base> entry;
while (pos < sz) {
header = (cpio_newc_header *)(buf + pos);
entry = make_unique<cpio_entry_base>(header);
pos += sizeof(*header);
string_view name_view(buf + pos);
pos += x8u(header->namesize);
pos_align(pos);
if (name_view == "." || name_view == "..")
continue;
if (name_view == "TRAILER!!!")
break;
entry->data = buf + pos;
pos += entry->filesize;
entries[name_view] = std::move(entry);
pos_align(pos);
}
}
cpio_mmap::~cpio_mmap() {
munmap(buf, sz);
munmap(buf, sz);
}

View File

@@ -13,427 +13,427 @@
using namespace std;
ssize_t fd_path(int fd, char *path, size_t size) {
snprintf(path, size, "/proc/self/fd/%d", fd);
return xreadlink(path, path, size);
snprintf(path, size, "/proc/self/fd/%d", fd);
return xreadlink(path, path, size);
}
int fd_pathat(int dirfd, const char *name, char *path, size_t size) {
if (fd_path(dirfd, path, size) < 0)
return -1;
auto len = strlen(path);
path[len] = '/';
strlcpy(path + len + 1, name, size - len - 1);
return 0;
if (fd_path(dirfd, path, size) < 0)
return -1;
auto len = strlen(path);
path[len] = '/';
strlcpy(path + len + 1, name, size - len - 1);
return 0;
}
int mkdirs(string path, mode_t mode) {
errno = 0;
for (char *p = path.data() + 1; *p; ++p) {
if (*p == '/') {
*p = '\0';
if (mkdir(path.data(), mode) == -1) {
if (errno != EEXIST)
return -1;
}
*p = '/';
}
}
if (mkdir(path.data(), mode) == -1) {
if (errno != EEXIST)
return -1;
}
return 0;
errno = 0;
for (char *p = path.data() + 1; *p; ++p) {
if (*p == '/') {
*p = '\0';
if (mkdir(path.data(), mode) == -1) {
if (errno != EEXIST)
return -1;
}
*p = '/';
}
}
if (mkdir(path.data(), mode) == -1) {
if (errno != EEXIST)
return -1;
}
return 0;
}
template <typename Func>
static void post_order_walk(int dirfd, const Func &fn) {
auto dir = xopen_dir(dirfd);
if (!dir) return;
auto dir = xopen_dir(dirfd);
if (!dir) return;
for (dirent *entry; (entry = xreaddir(dir.get()));) {
if (entry->d_type == DT_DIR)
post_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), fn);
fn(dirfd, entry);
}
for (dirent *entry; (entry = xreaddir(dir.get()));) {
if (entry->d_type == DT_DIR)
post_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), fn);
fn(dirfd, entry);
}
}
template <typename Func>
static void pre_order_walk(int dirfd, const Func &fn) {
auto dir = xopen_dir(dirfd);
if (!dir) return;
auto dir = xopen_dir(dirfd);
if (!dir) return;
for (dirent *entry; (entry = xreaddir(dir.get()));) {
if (!fn(dirfd, entry))
continue;
if (entry->d_type == DT_DIR)
pre_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), fn);
}
for (dirent *entry; (entry = xreaddir(dir.get()));) {
if (!fn(dirfd, entry))
continue;
if (entry->d_type == DT_DIR)
pre_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), fn);
}
}
static void remove_at(int dirfd, struct dirent *entry) {
unlinkat(dirfd, entry->d_name, entry->d_type == DT_DIR ? AT_REMOVEDIR : 0);
unlinkat(dirfd, entry->d_name, entry->d_type == DT_DIR ? AT_REMOVEDIR : 0);
}
void rm_rf(const char *path) {
struct stat st;
if (lstat(path, &st) < 0)
return;
if (S_ISDIR(st.st_mode))
frm_rf(xopen(path, O_RDONLY | O_CLOEXEC));
remove(path);
struct stat st;
if (lstat(path, &st) < 0)
return;
if (S_ISDIR(st.st_mode))
frm_rf(xopen(path, O_RDONLY | O_CLOEXEC));
remove(path);
}
void frm_rf(int dirfd) {
post_order_walk(dirfd, remove_at);
post_order_walk(dirfd, remove_at);
}
void mv_path(const char *src, const char *dest) {
file_attr attr;
getattr(src, &attr);
if (S_ISDIR(attr.st.st_mode)) {
if (access(dest, F_OK) != 0) {
xmkdirs(dest, 0);
setattr(dest, &attr);
}
mv_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC));
} else{
xrename(src, dest);
}
rmdir(src);
file_attr attr;
getattr(src, &attr);
if (S_ISDIR(attr.st.st_mode)) {
if (access(dest, F_OK) != 0) {
xmkdirs(dest, 0);
setattr(dest, &attr);
}
mv_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC));
} else{
xrename(src, dest);
}
rmdir(src);
}
void mv_dir(int src, int dest) {
auto dir = xopen_dir(src);
run_finally f([=]{ close(dest); });
for (dirent *entry; (entry = xreaddir(dir.get()));) {
switch (entry->d_type) {
case DT_DIR:
if (faccessat(dest, entry->d_name, F_OK, 0) == 0) {
// Destination folder exists, needs recursive move
int newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
int newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
mv_dir(newsrc, newdest);
unlinkat(src, entry->d_name, AT_REMOVEDIR);
break;
}
// Else fall through
case DT_LNK:
case DT_REG:
renameat(src, entry->d_name, dest, entry->d_name);
break;
}
}
auto dir = xopen_dir(src);
run_finally f([=]{ close(dest); });
for (dirent *entry; (entry = xreaddir(dir.get()));) {
switch (entry->d_type) {
case DT_DIR:
if (faccessat(dest, entry->d_name, F_OK, 0) == 0) {
// Destination folder exists, needs recursive move
int newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
int newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
mv_dir(newsrc, newdest);
unlinkat(src, entry->d_name, AT_REMOVEDIR);
break;
}
// Else fall through
case DT_LNK:
case DT_REG:
renameat(src, entry->d_name, dest, entry->d_name);
break;
}
}
}
void cp_afc(const char *src, const char *dest) {
file_attr a;
getattr(src, &a);
file_attr a;
getattr(src, &a);
if (S_ISDIR(a.st.st_mode)) {
xmkdirs(dest, 0);
clone_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC));
} else{
unlink(dest);
if (S_ISREG(a.st.st_mode)) {
int sfd = xopen(src, O_RDONLY | O_CLOEXEC);
int dfd = xopen(dest, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0);
xsendfile(dfd, sfd, nullptr, a.st.st_size);
close(sfd);
close(dfd);
} else if (S_ISLNK(a.st.st_mode)) {
char buf[4096];
xreadlink(src, buf, sizeof(buf));
xsymlink(buf, dest);
}
}
setattr(dest, &a);
if (S_ISDIR(a.st.st_mode)) {
xmkdirs(dest, 0);
clone_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC));
} else{
unlink(dest);
if (S_ISREG(a.st.st_mode)) {
int sfd = xopen(src, O_RDONLY | O_CLOEXEC);
int dfd = xopen(dest, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0);
xsendfile(dfd, sfd, nullptr, a.st.st_size);
close(sfd);
close(dfd);
} else if (S_ISLNK(a.st.st_mode)) {
char buf[4096];
xreadlink(src, buf, sizeof(buf));
xsymlink(buf, dest);
}
}
setattr(dest, &a);
}
void clone_dir(int src, int dest) {
auto dir = xopen_dir(src);
run_finally f([&]{ close(dest); });
for (dirent *entry; (entry = xreaddir(dir.get()));) {
file_attr a;
getattrat(src, entry->d_name, &a);
switch (entry->d_type) {
case DT_DIR: {
xmkdirat(dest, entry->d_name, 0);
setattrat(dest, entry->d_name, &a);
int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
int dst = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
clone_dir(sfd, dst);
break;
}
case DT_REG: {
int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
int dfd = xopenat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0);
xsendfile(dfd, sfd, nullptr, a.st.st_size);
fsetattr(dfd, &a);
close(dfd);
close(sfd);
break;
}
case DT_LNK: {
char buf[4096];
xreadlinkat(src, entry->d_name, buf, sizeof(buf));
xsymlinkat(buf, dest, entry->d_name);
setattrat(dest, entry->d_name, &a);
break;
}
}
}
auto dir = xopen_dir(src);
run_finally f([&]{ close(dest); });
for (dirent *entry; (entry = xreaddir(dir.get()));) {
file_attr a;
getattrat(src, entry->d_name, &a);
switch (entry->d_type) {
case DT_DIR: {
xmkdirat(dest, entry->d_name, 0);
setattrat(dest, entry->d_name, &a);
int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
int dst = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
clone_dir(sfd, dst);
break;
}
case DT_REG: {
int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
int dfd = xopenat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0);
xsendfile(dfd, sfd, nullptr, a.st.st_size);
fsetattr(dfd, &a);
close(dfd);
close(sfd);
break;
}
case DT_LNK: {
char buf[4096];
xreadlinkat(src, entry->d_name, buf, sizeof(buf));
xsymlinkat(buf, dest, entry->d_name);
setattrat(dest, entry->d_name, &a);
break;
}
}
}
}
void link_path(const char *src, const char *dest) {
link_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC));
link_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC));
}
void link_dir(int src, int dest) {
auto dir = xopen_dir(src);
run_finally f([&]{ close(dest); });
for (dirent *entry; (entry = xreaddir(dir.get()));) {
if (entry->d_type == DT_DIR) {
file_attr a;
getattrat(src, entry->d_name, &a);
xmkdirat(dest, entry->d_name, 0);
setattrat(dest, entry->d_name, &a);
int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
int dfd = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
link_dir(sfd, dfd);
} else {
xlinkat(src, entry->d_name, dest, entry->d_name, 0);
}
}
auto dir = xopen_dir(src);
run_finally f([&]{ close(dest); });
for (dirent *entry; (entry = xreaddir(dir.get()));) {
if (entry->d_type == DT_DIR) {
file_attr a;
getattrat(src, entry->d_name, &a);
xmkdirat(dest, entry->d_name, 0);
setattrat(dest, entry->d_name, &a);
int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
int dfd = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
link_dir(sfd, dfd);
} else {
xlinkat(src, entry->d_name, dest, entry->d_name, 0);
}
}
}
int getattr(const char *path, file_attr *a) {
if (xlstat(path, &a->st) == -1)
return -1;
char *con;
if (lgetfilecon(path, &con) == -1)
return -1;
strcpy(a->con, con);
freecon(con);
return 0;
if (xlstat(path, &a->st) == -1)
return -1;
char *con;
if (lgetfilecon(path, &con) == -1)
return -1;
strcpy(a->con, con);
freecon(con);
return 0;
}
int getattrat(int dirfd, const char *name, file_attr *a) {
char path[4096];
fd_pathat(dirfd, name, path, sizeof(path));
return getattr(path, a);
char path[4096];
fd_pathat(dirfd, name, path, sizeof(path));
return getattr(path, a);
}
int fgetattr(int fd, file_attr *a) {
if (xfstat(fd, &a->st) < 0)
return -1;
char *con;
if (fgetfilecon(fd, &con) < 0)
return -1;
strcpy(a->con, con);
freecon(con);
return 0;
if (xfstat(fd, &a->st) < 0)
return -1;
char *con;
if (fgetfilecon(fd, &con) < 0)
return -1;
strcpy(a->con, con);
freecon(con);
return 0;
}
int setattr(const char *path, file_attr *a) {
if (chmod(path, a->st.st_mode & 0777) < 0)
return -1;
if (chown(path, a->st.st_uid, a->st.st_gid) < 0)
return -1;
if (a->con[0] && lsetfilecon(path, a->con) < 0)
return -1;
return 0;
if (chmod(path, a->st.st_mode & 0777) < 0)
return -1;
if (chown(path, a->st.st_uid, a->st.st_gid) < 0)
return -1;
if (a->con[0] && lsetfilecon(path, a->con) < 0)
return -1;
return 0;
}
int setattrat(int dirfd, const char *name, file_attr *a) {
char path[4096];
fd_pathat(dirfd, name, path, sizeof(path));
return setattr(path, a);
char path[4096];
fd_pathat(dirfd, name, path, sizeof(path));
return setattr(path, a);
}
int fsetattr(int fd, file_attr *a) {
if (fchmod(fd, a->st.st_mode & 0777) < 0)
return -1;
if (fchown(fd, a->st.st_uid, a->st.st_gid) < 0)
return -1;
if (a->con[0] && fsetfilecon(fd, a->con) < 0)
return -1;
return 0;
if (fchmod(fd, a->st.st_mode & 0777) < 0)
return -1;
if (fchown(fd, a->st.st_uid, a->st.st_gid) < 0)
return -1;
if (a->con[0] && fsetfilecon(fd, a->con) < 0)
return -1;
return 0;
}
void clone_attr(const char *src, const char *dest) {
file_attr a;
getattr(src, &a);
setattr(dest, &a);
file_attr a;
getattr(src, &a);
setattr(dest, &a);
}
void fclone_attr(int src, int dest) {
file_attr a;
fgetattr(src, &a);
fsetattr(dest, &a);
file_attr a;
fgetattr(src, &a);
fsetattr(dest, &a);
}
void *__mmap(const char *filename, size_t *size, bool rw) {
int fd = xopen(filename, (rw ? O_RDWR : O_RDONLY) | O_CLOEXEC);
if (fd < 0) {
*size = 0;
return nullptr;
}
struct stat st;
void *buf;
if (fstat(fd, &st)) {
*size = 0;
return nullptr;
}
if (S_ISBLK(st.st_mode))
ioctl(fd, BLKGETSIZE64, size);
else
*size = st.st_size;
buf = *size > 0 ? xmmap(nullptr, *size, PROT_READ | (rw ? PROT_WRITE : 0), MAP_SHARED, fd, 0) : nullptr;
close(fd);
return buf;
int fd = xopen(filename, (rw ? O_RDWR : O_RDONLY) | O_CLOEXEC);
if (fd < 0) {
*size = 0;
return nullptr;
}
struct stat st;
void *buf;
if (fstat(fd, &st)) {
*size = 0;
return nullptr;
}
if (S_ISBLK(st.st_mode))
ioctl(fd, BLKGETSIZE64, size);
else
*size = st.st_size;
buf = *size > 0 ? xmmap(nullptr, *size, PROT_READ | (rw ? PROT_WRITE : 0), MAP_SHARED, fd, 0) : nullptr;
close(fd);
return buf;
}
void fd_full_read(int fd, void **buf, size_t *size) {
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = xmalloc(*size + 1);
xxread(fd, *buf, *size);
((char *) *buf)[*size] = '\0';
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = xmalloc(*size + 1);
xxread(fd, *buf, *size);
((char *) *buf)[*size] = '\0';
}
void full_read(const char *filename, void **buf, size_t *size) {
int fd = xopen(filename, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
*buf = nullptr;
*size = 0;
return;
}
fd_full_read(fd, buf, size);
close(fd);
int fd = xopen(filename, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
*buf = nullptr;
*size = 0;
return;
}
fd_full_read(fd, buf, size);
close(fd);
}
string fd_full_read(int fd) {
char buf[4096];
string str;
for (ssize_t len; (len = xread(fd, buf, sizeof(buf))) > 0;)
str.insert(str.end(), buf, buf + len);
return str;
char buf[4096];
string str;
for (ssize_t len; (len = xread(fd, buf, sizeof(buf))) > 0;)
str.insert(str.end(), buf, buf + len);
return str;
}
string full_read(const char *filename) {
int fd = xopen(filename, O_RDONLY | O_CLOEXEC);
run_finally f([=]{ close(fd); });
return fd < 0 ? "" : fd_full_read(fd);
int fd = xopen(filename, O_RDONLY | O_CLOEXEC);
run_finally f([=]{ close(fd); });
return fd < 0 ? "" : fd_full_read(fd);
}
void write_zero(int fd, size_t size) {
char buf[4096] = {0};
size_t len;
while (size > 0) {
len = sizeof(buf) > size ? size : sizeof(buf);
write(fd, buf, len);
size -= len;
}
char buf[4096] = {0};
size_t len;
while (size > 0) {
len = sizeof(buf) > size ? size : sizeof(buf);
write(fd, buf, len);
size -= len;
}
}
void file_readline(bool trim, const char *file, const function<bool(string_view)> &fn) {
FILE *fp = xfopen(file, "re");
if (fp == nullptr)
return;
size_t len = 1024;
char *buf = (char *) malloc(len);
char *start;
ssize_t read;
while ((read = getline(&buf, &len, fp)) >= 0) {
start = buf;
if (trim) {
while (read && "\n\r "sv.find(buf[read - 1]) != string::npos)
--read;
buf[read] = '\0';
while (*start == ' ')
++start;
}
if (!fn(start))
break;
}
fclose(fp);
free(buf);
FILE *fp = xfopen(file, "re");
if (fp == nullptr)
return;
size_t len = 1024;
char *buf = (char *) malloc(len);
char *start;
ssize_t read;
while ((read = getline(&buf, &len, fp)) >= 0) {
start = buf;
if (trim) {
while (read && "\n\r "sv.find(buf[read - 1]) != string::npos)
--read;
buf[read] = '\0';
while (*start == ' ')
++start;
}
if (!fn(start))
break;
}
fclose(fp);
free(buf);
}
void parse_prop_file(const char *file, const function<bool(string_view, string_view)> &fn) {
file_readline(true, file, [&](string_view line_view) -> bool {
char *line = (char *) line_view.data();
if (line[0] == '#')
return true;
char *eql = strchr(line, '=');
if (eql == nullptr || eql == line)
return true;
*eql = '\0';
return fn(line, eql + 1);
});
file_readline(true, file, [&](string_view line_view) -> bool {
char *line = (char *) line_view.data();
if (line[0] == '#')
return true;
char *eql = strchr(line, '=');
if (eql == nullptr || eql == line)
return true;
*eql = '\0';
return fn(line, eql + 1);
});
}
void parse_mnt(const char *file, const function<bool(mntent*)> &fn) {
auto fp = sFILE(setmntent(file, "re"), endmntent);
if (fp) {
mntent mentry{};
char buf[4096];
while (getmntent_r(fp.get(), &mentry, buf, sizeof(buf))) {
if (!fn(&mentry))
break;
}
}
auto fp = sFILE(setmntent(file, "re"), endmntent);
if (fp) {
mntent mentry{};
char buf[4096];
while (getmntent_r(fp.get(), &mentry, buf, sizeof(buf))) {
if (!fn(&mentry))
break;
}
}
}
void backup_folder(const char *dir, vector<raw_file> &files) {
char path[4096];
xrealpath(dir, path);
int len = strlen(path);
pre_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> bool {
int fd = xopenat(dfd, entry->d_name, O_RDONLY);
if (fd < 0)
return false;
run_finally f([&]{ close(fd); });
if (fd_path(fd, path, sizeof(path)) < 0)
return false;
raw_file file;
file.path = path + len + 1;
if (fgetattr(fd, &file.attr) < 0)
return false;
if (entry->d_type == DT_REG) {
fd_full_read(fd, file.buf, file.sz);
} else if (entry->d_type == DT_LNK) {
xreadlinkat(dfd, entry->d_name, path, sizeof(path));
file.sz = strlen(path) + 1;
file.buf = (uint8_t *) xmalloc(file.sz);
memcpy(file.buf, path, file.sz);
}
files.emplace_back(std::move(file));
return true;
});
char path[4096];
xrealpath(dir, path);
int len = strlen(path);
pre_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> bool {
int fd = xopenat(dfd, entry->d_name, O_RDONLY);
if (fd < 0)
return false;
run_finally f([&]{ close(fd); });
if (fd_path(fd, path, sizeof(path)) < 0)
return false;
raw_file file;
file.path = path + len + 1;
if (fgetattr(fd, &file.attr) < 0)
return false;
if (entry->d_type == DT_REG) {
fd_full_read(fd, file.buf, file.sz);
} else if (entry->d_type == DT_LNK) {
xreadlinkat(dfd, entry->d_name, path, sizeof(path));
file.sz = strlen(path) + 1;
file.buf = (uint8_t *) xmalloc(file.sz);
memcpy(file.buf, path, file.sz);
}
files.emplace_back(std::move(file));
return true;
});
}
void restore_folder(const char *dir, vector<raw_file> &files) {
string base(dir);
// Pre-order means folders will always be first
for (raw_file &file : files) {
string path = base + "/" + file.path;
if (S_ISDIR(file.attr.st.st_mode)) {
mkdirs(path.data(), 0);
} else if (S_ISREG(file.attr.st.st_mode)) {
auto fp = xopen_file(path.data(), "we");
fwrite(file.buf, 1, file.sz, fp.get());
} else if (S_ISLNK(file.attr.st.st_mode)) {
symlink((char *)file.buf, path.data());
}
setattr(path.data(), &file.attr);
}
string base(dir);
// Pre-order means folders will always be first
for (raw_file &file : files) {
string path = base + "/" + file.path;
if (S_ISDIR(file.attr.st.st_mode)) {
mkdirs(path.data(), 0);
} else if (S_ISREG(file.attr.st.st_mode)) {
auto fp = xopen_file(path.data(), "we");
fwrite(file.buf, 1, file.sz, fp.get());
} else if (S_ISLNK(file.attr.st.st_mode)) {
symlink((char *)file.buf, path.data());
}
setattr(path.data(), &file.attr);
}
}
sDIR make_dir(DIR *dp) {
return sDIR(dp, [](DIR *dp){ return dp ? closedir(dp) : 1; });
return sDIR(dp, [](DIR *dp){ return dp ? closedir(dp) : 1; });
}
sFILE make_file(FILE *fp) {
return sFILE(fp, [](FILE *fp){ return fp ? fclose(fp) : 1; });
return sFILE(fp, [](FILE *fp){ return fp ? fclose(fp) : 1; });
}

View File

@@ -14,29 +14,29 @@
#define align_off(p, a) (do_align(p, a) - (p))
struct file_attr {
struct stat st;
char con[128];
struct stat st;
char con[128];
};
struct raw_file {
std::string path;
file_attr attr;
uint8_t *buf = nullptr;
size_t sz = 0;
std::string path;
file_attr attr;
uint8_t *buf = nullptr;
size_t sz = 0;
raw_file() = default;
raw_file(const raw_file&) = delete;
raw_file(raw_file &&d) {
path = std::move(d.path);
attr = d.attr;
buf = d.buf;
sz = d.sz;
d.buf = nullptr;
d.sz = 0;
}
~raw_file() {
free(buf);
}
raw_file() = default;
raw_file(const raw_file&) = delete;
raw_file(raw_file &&d) {
path = std::move(d.path);
attr = d.attr;
buf = d.buf;
sz = d.sz;
d.buf = nullptr;
d.sz = 0;
}
~raw_file() {
free(buf);
}
};
ssize_t fd_path(int fd, char *path, size_t size);
@@ -63,11 +63,11 @@ std::string full_read(const char *filename);
void write_zero(int fd, size_t size);
void file_readline(bool trim, const char *file, const std::function<bool(std::string_view)> &fn);
static inline void file_readline(const char *file,
const std::function<bool(std::string_view)> &fn) {
file_readline(false, file, fn);
const std::function<bool(std::string_view)> &fn) {
file_readline(false, file, fn);
}
void parse_prop_file(const char *file,
const std::function<bool(std::string_view, std::string_view)> &fn);
const std::function<bool(std::string_view, std::string_view)> &fn);
void *__mmap(const char *filename, size_t *size, bool rw);
void frm_rf(int dirfd);
void clone_dir(int src, int dest);
@@ -77,38 +77,38 @@ void restore_folder(const char *dir, std::vector<raw_file> &files);
template <typename T>
void full_read(const char *filename, T &buf, size_t &size) {
static_assert(std::is_pointer<T>::value);
full_read(filename, reinterpret_cast<void**>(&buf), &size);
static_assert(std::is_pointer<T>::value);
full_read(filename, reinterpret_cast<void**>(&buf), &size);
}
template <typename T>
void fd_full_read(int fd, T &buf, size_t &size) {
static_assert(std::is_pointer<T>::value);
fd_full_read(fd, reinterpret_cast<void**>(&buf), &size);
static_assert(std::is_pointer<T>::value);
fd_full_read(fd, reinterpret_cast<void**>(&buf), &size);
}
template <typename B>
void mmap_ro(const char *filename, B &buf, size_t &sz) {
buf = (B) __mmap(filename, &sz, false);
buf = (B) __mmap(filename, &sz, false);
}
template <typename B, typename L>
void mmap_ro(const char *filename, B &buf, L &sz) {
size_t __sz;
buf = (B) __mmap(filename, &__sz, false);
sz = __sz;
size_t __sz;
buf = (B) __mmap(filename, &__sz, false);
sz = __sz;
}
template <typename B>
void mmap_rw(const char *filename, B &buf, size_t &sz) {
buf = (B) __mmap(filename, &sz, true);
buf = (B) __mmap(filename, &sz, true);
}
template <typename B, typename L>
void mmap_rw(const char *filename, B &buf, L &sz) {
size_t __sz;
buf = (B) __mmap(filename, &__sz, true);
sz = __sz;
size_t __sz;
buf = (B) __mmap(filename, &__sz, true);
sz = __sz;
}
using sFILE = std::unique_ptr<FILE, decltype(&fclose)>;
@@ -117,25 +117,25 @@ sDIR make_dir(DIR *dp);
sFILE make_file(FILE *fp);
static inline sDIR open_dir(const char *path) {
return make_dir(opendir(path));
return make_dir(opendir(path));
}
static inline sDIR xopen_dir(const char *path) {
return make_dir(xopendir(path));
return make_dir(xopendir(path));
}
static inline sDIR xopen_dir(int dirfd) {
return make_dir(xfdopendir(dirfd));
return make_dir(xfdopendir(dirfd));
}
static inline sFILE open_file(const char *path, const char *mode) {
return make_file(fopen(path, mode));
return make_file(fopen(path, mode));
}
static inline sFILE xopen_file(const char *path, const char *mode) {
return make_file(xfopen(path, mode));
return make_file(xfopen(path, mode));
}
static inline sFILE xopen_file(int fd, const char *mode) {
return make_file(xfdopen(fd, mode));
return make_file(xfdopen(fd, mode));
}

View File

@@ -11,67 +11,67 @@
struct cpio_newc_header;
struct cpio_entry_base {
uint32_t mode = 0;
uint32_t uid = 0;
uint32_t gid = 0;
uint32_t filesize = 0;
uint32_t mode = 0;
uint32_t uid = 0;
uint32_t gid = 0;
uint32_t filesize = 0;
void *data = nullptr;
void *data = nullptr;
cpio_entry_base() : mode(0), uid(0), gid(0), filesize(0) {};
explicit cpio_entry_base(const cpio_newc_header *h);
virtual ~cpio_entry_base() = default;
cpio_entry_base() : mode(0), uid(0), gid(0), filesize(0) {};
explicit cpio_entry_base(const cpio_newc_header *h);
virtual ~cpio_entry_base() = default;
};
struct cpio_entry : public cpio_entry_base {
std::string filename;
std::string filename;
cpio_entry() = default;
explicit cpio_entry(const char *name, uint32_t mode) : filename(name) {
this->mode = mode;
}
explicit cpio_entry(const cpio_newc_header *h) : cpio_entry_base(h) {}
cpio_entry() = default;
explicit cpio_entry(const char *name, uint32_t mode) : filename(name) {
this->mode = mode;
}
explicit cpio_entry(const cpio_newc_header *h) : cpio_entry_base(h) {}
~cpio_entry() override { free(data); };
~cpio_entry() override { free(data); };
};
typedef std::map<std::string_view, std::unique_ptr<cpio_entry_base>> entry_map;
class cpio {
public:
void dump(const char *file);
void rm(const char *name, bool r = false);
void extract();
bool extract(const char *name, const char *file);
bool exists(const char *name);
void dump(const char *file);
void rm(const char *name, bool r = false);
void extract();
bool extract(const char *name, const char *file);
bool exists(const char *name);
protected:
entry_map entries;
void rm(entry_map::iterator &it);
void dump(FILE *out);
entry_map entries;
void rm(entry_map::iterator &it);
void dump(FILE *out);
};
class cpio_rw : public cpio {
public:
cpio_rw() = default;
explicit cpio_rw(const char *file);
void load_cpio(const char *file);
void add(mode_t mode, const char *name, const char *file);
void mkdir(mode_t mode, const char *name);
void ln(const char *target, const char *name);
bool mv(const char *from, const char *to);
cpio_rw() = default;
explicit cpio_rw(const char *file);
void load_cpio(const char *file);
void add(mode_t mode, const char *name, const char *file);
void mkdir(mode_t mode, const char *name);
void ln(const char *target, const char *name);
bool mv(const char *from, const char *to);
protected:
void insert(cpio_entry *e);
void mv(entry_map::iterator &it, const char *to);
void load_cpio(const char *buf, size_t sz);
void insert(cpio_entry *e);
void mv(entry_map::iterator &it, const char *to);
void load_cpio(const char *buf, size_t sz);
};
class cpio_mmap : public cpio {
public:
explicit cpio_mmap(const char *file);
~cpio_mmap();
explicit cpio_mmap(const char *file);
~cpio_mmap();
private:
char *buf;
size_t sz;
char *buf;
size_t sz;
};

View File

@@ -7,10 +7,10 @@
class stream {
public:
virtual int read(void *buf, size_t len);
virtual int write(const void *buf, size_t len);
virtual off_t seek(off_t off, int whence);
virtual ~stream() = default;
virtual int read(void *buf, size_t len);
virtual int write(const void *buf, size_t len);
virtual off_t seek(off_t off, int whence);
virtual ~stream() = default;
};
using stream_ptr = std::unique_ptr<stream>;
@@ -18,44 +18,44 @@ using stream_ptr = std::unique_ptr<stream>;
// Delegates all operations to base stream
class filter_stream : public stream {
public:
filter_stream(stream_ptr &&base) : base(std::move(base)) {}
filter_stream(stream_ptr &&base) : base(std::move(base)) {}
int read(void *buf, size_t len) override;
int write(const void *buf, size_t len) override;
int read(void *buf, size_t len) override;
int write(const void *buf, size_t len) override;
protected:
stream_ptr base;
stream_ptr base;
};
// Byte stream that dynamically allocates memory
class byte_stream : public stream {
public:
byte_stream(uint8_t *&buf, size_t &len);
template <class byte>
byte_stream(byte *&buf, size_t &len) : byte_stream(reinterpret_cast<uint8_t *&>(buf), len) {}
int read(void *buf, size_t len) override;
int write(const void *buf, size_t len) override;
off_t seek(off_t off, int whence) override;
byte_stream(uint8_t *&buf, size_t &len);
template <class byte>
byte_stream(byte *&buf, size_t &len) : byte_stream(reinterpret_cast<uint8_t *&>(buf), len) {}
int read(void *buf, size_t len) override;
int write(const void *buf, size_t len) override;
off_t seek(off_t off, int whence) override;
private:
uint8_t *&_buf;
size_t &_len;
size_t _pos = 0;
size_t _cap = 0;
uint8_t *&_buf;
size_t &_len;
size_t _pos = 0;
size_t _cap = 0;
void resize(size_t new_pos, bool zero = false);
void resize(size_t new_pos, bool zero = false);
};
// File stream but does not close the file descriptor at any time
class fd_stream : public stream {
public:
fd_stream(int fd) : fd(fd) {}
int read(void *buf, size_t len) override;
int write(const void *buf, size_t len) override;
off_t seek(off_t off, int whence) override;
fd_stream(int fd) : fd(fd) {}
int read(void *buf, size_t len) override;
int write(const void *buf, size_t len) override;
off_t seek(off_t off, int whence) override;
private:
int fd;
int fd;
};
/* ****************************************
@@ -65,14 +65,14 @@ private:
// sFILE -> stream_ptr
class fp_stream final : public stream {
public:
fp_stream(FILE *fp = nullptr) : fp(fp, fclose) {}
fp_stream(sFILE &&fp) : fp(std::move(fp)) {}
int read(void *buf, size_t len) override;
int write(const void *buf, size_t len) override;
off_t seek(off_t off, int whence) override;
fp_stream(FILE *fp = nullptr) : fp(fp, fclose) {}
fp_stream(sFILE &&fp) : fp(std::move(fp)) {}
int read(void *buf, size_t len) override;
int write(const void *buf, size_t len) override;
off_t seek(off_t off, int whence) override;
private:
sFILE fp;
sFILE fp;
};
// stream_ptr -> sFILE
@@ -80,5 +80,5 @@ sFILE make_stream_fp(stream_ptr &&strm);
template <class T, class... Args>
sFILE make_stream_fp(Args &&... args) {
return make_stream_fp(stream_ptr(new T(std::forward<Args>(args)...)));
return make_stream_fp(stream_ptr(new T(std::forward<Args>(args)...)));
}

View File

@@ -11,48 +11,48 @@ int nop_log(const char *, va_list) { return 0; }
void nop_ex(int) {}
log_callback log_cb = {
.d = nop_log,
.i = nop_log,
.w = nop_log,
.e = nop_log,
.ex = nop_ex
.d = nop_log,
.i = nop_log,
.w = nop_log,
.e = nop_log,
.ex = nop_ex
};
void no_logging() {
log_cb.d = nop_log;
log_cb.i = nop_log;
log_cb.w = nop_log;
log_cb.e = nop_log;
log_cb.ex = nop_ex;
log_cb.d = nop_log;
log_cb.i = nop_log;
log_cb.w = nop_log;
log_cb.e = nop_log;
log_cb.ex = nop_ex;
}
static int vprintfe(const char *fmt, va_list ap) {
return vfprintf(stderr, fmt, ap);
return vfprintf(stderr, fmt, ap);
}
void cmdline_logging() {
log_cb.d = vprintfe;
log_cb.i = vprintf;
log_cb.w = vprintfe;
log_cb.e = vprintfe;
log_cb.ex = exit;
log_cb.d = vprintfe;
log_cb.i = vprintf;
log_cb.w = vprintfe;
log_cb.e = vprintfe;
log_cb.ex = exit;
}
template <int type>
void log_handler(const char *fmt, ...) {
va_list argv;
va_start(argv, fmt);
if constexpr (type == L_DEBUG) {
log_cb.d(fmt, argv);
} else if constexpr (type == L_INFO) {
log_cb.i(fmt, argv);
} else if constexpr (type == L_WARN) {
log_cb.w(fmt, argv);
} else if constexpr (type == L_ERR) {
log_cb.e(fmt, argv);
log_cb.ex(1);
}
va_end(argv);
va_list argv;
va_start(argv, fmt);
if constexpr (type == L_DEBUG) {
log_cb.d(fmt, argv);
} else if constexpr (type == L_INFO) {
log_cb.i(fmt, argv);
} else if constexpr (type == L_WARN) {
log_cb.w(fmt, argv);
} else if constexpr (type == L_ERR) {
log_cb.e(fmt, argv);
log_cb.ex(1);
}
va_end(argv);
}
template void log_handler<L_INFO>(const char *fmt, ...);

View File

@@ -5,18 +5,18 @@
#include <cstring>
enum {
L_DEBUG,
L_INFO,
L_WARN,
L_ERR
L_DEBUG,
L_INFO,
L_WARN,
L_ERR
};
struct log_callback {
int (*d)(const char* fmt, va_list ap);
int (*i)(const char* fmt, va_list ap);
int (*w)(const char* fmt, va_list ap);
int (*e)(const char* fmt, va_list ap);
void (*ex)(int code);
int (*d)(const char* fmt, va_list ap);
int (*i)(const char* fmt, va_list ap);
int (*w)(const char* fmt, va_list ap);
int (*e)(const char* fmt, va_list ap);
void (*ex)(int code);
};
extern log_callback log_cb;

View File

@@ -14,23 +14,23 @@
using namespace std;
int fork_dont_care() {
if (int pid = xfork()) {
waitpid(pid, nullptr, 0);
return pid;
} else if (xfork()) {
exit(0);
}
return 0;
if (int pid = xfork()) {
waitpid(pid, nullptr, 0);
return pid;
} else if (xfork()) {
exit(0);
}
return 0;
}
int fork_no_orphan() {
int pid = xfork();
if (pid)
return pid;
prctl(PR_SET_PDEATHSIG, SIGTERM);
if (getppid() == 1)
exit(1);
return 0;
int pid = xfork();
if (pid)
return pid;
prctl(PR_SET_PDEATHSIG, SIGTERM);
if (getppid() == 1)
exit(1);
return 0;
}
constexpr char ALPHANUM[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -38,111 +38,111 @@ static bool seeded = false;
static std::mt19937 gen;
static std::uniform_int_distribution<int> dist(0, sizeof(ALPHANUM) - 2);
int gen_rand_str(char *buf, int len, bool varlen) {
if (!seeded) {
if (access("/dev/urandom", F_OK) != 0)
mknod("/dev/urandom", 0600 | S_IFCHR, makedev(1, 9));
int fd = xopen("/dev/urandom", O_RDONLY | O_CLOEXEC);
unsigned seed;
xxread(fd, &seed, sizeof(seed));
gen.seed(seed);
close(fd);
seeded = true;
}
if (varlen) {
std::uniform_int_distribution<int> len_dist(len / 2, len);
len = len_dist(gen);
}
for (int i = 0; i < len - 1; ++i)
buf[i] = ALPHANUM[dist(gen)];
buf[len - 1] = '\0';
return len - 1;
if (!seeded) {
if (access("/dev/urandom", F_OK) != 0)
mknod("/dev/urandom", 0600 | S_IFCHR, makedev(1, 9));
int fd = xopen("/dev/urandom", O_RDONLY | O_CLOEXEC);
unsigned seed;
xxread(fd, &seed, sizeof(seed));
gen.seed(seed);
close(fd);
seeded = true;
}
if (varlen) {
std::uniform_int_distribution<int> len_dist(len / 2, len);
len = len_dist(gen);
}
for (int i = 0; i < len - 1; ++i)
buf[i] = ALPHANUM[dist(gen)];
buf[len - 1] = '\0';
return len - 1;
}
int exec_command(exec_t &exec) {
int pipefd[] = {-1, -1};
int outfd = -1;
int pipefd[] = {-1, -1};
int outfd = -1;
if (exec.fd == -1) {
if (xpipe2(pipefd, O_CLOEXEC) == -1)
return -1;
outfd = pipefd[1];
} else if (exec.fd >= 0) {
outfd = exec.fd;
}
if (exec.fd == -1) {
if (xpipe2(pipefd, O_CLOEXEC) == -1)
return -1;
outfd = pipefd[1];
} else if (exec.fd >= 0) {
outfd = exec.fd;
}
int pid = exec.fork();
if (pid < 0) {
close(pipefd[0]);
close(pipefd[1]);
return -1;
} else if (pid) {
if (exec.fd == -1) {
exec.fd = pipefd[0];
close(pipefd[1]);
}
return pid;
}
int pid = exec.fork();
if (pid < 0) {
close(pipefd[0]);
close(pipefd[1]);
return -1;
} else if (pid) {
if (exec.fd == -1) {
exec.fd = pipefd[0];
close(pipefd[1]);
}
return pid;
}
// Unblock all signals
sigset_t set;
sigfillset(&set);
pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
// Unblock all signals
sigset_t set;
sigfillset(&set);
pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
if (outfd >= 0) {
xdup2(outfd, STDOUT_FILENO);
if (exec.err)
xdup2(outfd, STDERR_FILENO);
close(outfd);
}
if (outfd >= 0) {
xdup2(outfd, STDOUT_FILENO);
if (exec.err)
xdup2(outfd, STDERR_FILENO);
close(outfd);
}
// Call the pre-exec callback
if (exec.pre_exec)
exec.pre_exec();
// Call the pre-exec callback
if (exec.pre_exec)
exec.pre_exec();
execve(exec.argv[0], (char **) exec.argv, environ);
PLOGE("execve %s", exec.argv[0]);
exit(-1);
execve(exec.argv[0], (char **) exec.argv, environ);
PLOGE("execve %s", exec.argv[0]);
exit(-1);
}
int exec_command_sync(exec_t &exec) {
int pid = exec_command(exec);
if (pid < 0)
return -1;
int status;
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
int pid = exec_command(exec);
if (pid < 0)
return -1;
int status;
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
}
int new_daemon_thread(thread_entry entry, void *arg, const pthread_attr_t *attr) {
pthread_t thread;
int ret = xpthread_create(&thread, attr, entry, arg);
if (ret == 0)
pthread_detach(thread);
return ret;
pthread_t thread;
int ret = xpthread_create(&thread, attr, entry, arg);
if (ret == 0)
pthread_detach(thread);
return ret;
}
static void *proxy_routine(void *fp) {
auto fn = reinterpret_cast<std::function<void()>*>(fp);
(*fn)();
delete fn;
return nullptr;
auto fn = reinterpret_cast<std::function<void()>*>(fp);
(*fn)();
delete fn;
return nullptr;
}
int new_daemon_thread(std::function<void()> &&entry) {
return new_daemon_thread(proxy_routine, new std::function<void()>(std::move(entry)));
return new_daemon_thread(proxy_routine, new std::function<void()>(std::move(entry)));
}
static char *argv0;
static size_t name_len;
void init_argv0(int argc, char **argv) {
argv0 = argv[0];
name_len = (argv[argc - 1] - argv[0]) + strlen(argv[argc - 1]) + 1;
argv0 = argv[0];
name_len = (argv[argc - 1] - argv[0]) + strlen(argv[argc - 1]) + 1;
}
void set_nice_name(const char *name) {
memset(argv0, 0, name_len);
strlcpy(argv0, name, name_len);
prctl(PR_SET_NAME, name);
memset(argv0, 0, name_len);
strlcpy(argv0, name, name_len);
prctl(PR_SET_NAME, name);
}
/*
@@ -150,52 +150,52 @@ void set_nice_name(const char *name) {
* Use our own implementation for faster conversion.
*/
int parse_int(const char *s) {
int val = 0;
char c;
while ((c = *(s++))) {
if (c > '9' || c < '0')
return -1;
val = val * 10 + c - '0';
}
return val;
int val = 0;
char c;
while ((c = *(s++))) {
if (c > '9' || c < '0')
return -1;
val = val * 10 + c - '0';
}
return val;
}
uint32_t binary_gcd(uint32_t u, uint32_t v) {
if (u == 0) return v;
if (v == 0) return u;
auto shift = __builtin_ctz(u | v);
u >>= __builtin_ctz(u);
do {
v >>= __builtin_ctz(v);
if (u > v) {
auto t = v;
v = u;
u = t;
}
v -= u;
} while (v != 0);
return u << shift;
if (u == 0) return v;
if (v == 0) return u;
auto shift = __builtin_ctz(u | v);
u >>= __builtin_ctz(u);
do {
v >>= __builtin_ctz(v);
if (u > v) {
auto t = v;
v = u;
u = t;
}
v -= u;
} while (v != 0);
return u << shift;
}
int switch_mnt_ns(int pid) {
char mnt[32];
snprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid);
if (access(mnt, R_OK) == -1) return 1; // Maybe process died..
char mnt[32];
snprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid);
if (access(mnt, R_OK) == -1) return 1; // Maybe process died..
int fd, ret;
fd = xopen(mnt, O_RDONLY);
if (fd < 0) return 1;
// Switch to its namespace
ret = xsetns(fd, 0);
close(fd);
return ret;
int fd, ret;
fd = xopen(mnt, O_RDONLY);
if (fd < 0) return 1;
// Switch to its namespace
ret = xsetns(fd, 0);
close(fd);
return ret;
}
string &replace_all(string &str, string_view from, string_view to) {
size_t pos = 0;
while((pos = str.find(from, pos)) != string::npos) {
str.replace(pos, from.length(), to);
pos += to.length();
}
return str;
size_t pos = 0;
while((pos = str.find(from, pos)) != string::npos) {
str.replace(pos, from.length(), to);
pos += to.length();
}
return str;
}

View File

@@ -10,48 +10,48 @@
class mutex_guard {
public:
explicit mutex_guard(pthread_mutex_t &m): mutex(&m) {
pthread_mutex_lock(mutex);
}
explicit mutex_guard(pthread_mutex_t &m): mutex(&m) {
pthread_mutex_lock(mutex);
}
explicit mutex_guard(pthread_mutex_t *m): mutex(m) {
pthread_mutex_lock(mutex);
}
explicit mutex_guard(pthread_mutex_t *m): mutex(m) {
pthread_mutex_lock(mutex);
}
~mutex_guard() {
pthread_mutex_unlock(mutex);
}
~mutex_guard() {
pthread_mutex_unlock(mutex);
}
private:
pthread_mutex_t *mutex;
pthread_mutex_t *mutex;
};
template <class Func>
class run_finally {
public:
explicit run_finally(const Func &fn) : fn(fn) {}
~run_finally() { fn(); }
explicit run_finally(const Func &fn) : fn(fn) {}
~run_finally() { fn(); }
private:
const Func &fn;
const Func &fn;
};
template <typename T>
class reversed_container {
public:
reversed_container(T &base) : base(base) {}
decltype(std::declval<T>().rbegin()) begin() { return base.rbegin(); }
decltype(std::declval<T>().crbegin()) begin() const { return base.crbegin(); }
decltype(std::declval<T>().crbegin()) cbegin() const { return base.crbegin(); }
decltype(std::declval<T>().rend()) end() { return base.rend(); }
decltype(std::declval<T>().crend()) end() const { return base.crend(); }
decltype(std::declval<T>().crend()) cend() const { return base.crend(); }
reversed_container(T &base) : base(base) {}
decltype(std::declval<T>().rbegin()) begin() { return base.rbegin(); }
decltype(std::declval<T>().crbegin()) begin() const { return base.crbegin(); }
decltype(std::declval<T>().crbegin()) cbegin() const { return base.crbegin(); }
decltype(std::declval<T>().rend()) end() { return base.rend(); }
decltype(std::declval<T>().crend()) end() const { return base.crend(); }
decltype(std::declval<T>().crend()) cend() const { return base.crend(); }
private:
T &base;
T &base;
};
template <typename T>
reversed_container<T> reversed(T &base) {
return reversed_container<T>(base);
return reversed_container<T>(base);
}
int parse_int(const char *s);
@@ -63,13 +63,13 @@ int new_daemon_thread(thread_entry entry, void *arg = nullptr, const pthread_att
int new_daemon_thread(std::function<void()> &&entry);
static inline bool str_contains(std::string_view s, std::string_view ss) {
return s.find(ss) != std::string::npos;
return s.find(ss) != std::string::npos;
}
static inline bool str_starts(std::string_view s, std::string_view ss) {
return s.rfind(ss, 0) == 0;
return s.rfind(ss, 0) == 0;
}
static inline bool str_ends(std::string_view s, std::string_view ss) {
return s.size() >= ss.size() && s.compare(s.size() - ss.size(), std::string::npos, ss) == 0;
return s.size() >= ss.size() && s.compare(s.size() - ss.size(), std::string::npos, ss) == 0;
}
int fork_dont_care();
@@ -82,38 +82,38 @@ int gen_rand_str(char *buf, int len, bool varlen = true);
std::string &replace_all(std::string &str, std::string_view from, std::string_view to);
struct exec_t {
bool err = false;
int fd = -2;
void (*pre_exec)() = nullptr;
int (*fork)() = xfork;
const char **argv = nullptr;
bool err = false;
int fd = -2;
void (*pre_exec)() = nullptr;
int (*fork)() = xfork;
const char **argv = nullptr;
};
int exec_command(exec_t &exec);
template <class ...Args>
int exec_command(exec_t &exec, Args &&...args) {
const char *argv[] = {args..., nullptr};
exec.argv = argv;
return exec_command(exec);
const char *argv[] = {args..., nullptr};
exec.argv = argv;
return exec_command(exec);
}
int exec_command_sync(exec_t &exec);
template <class ...Args>
int exec_command_sync(exec_t &exec, Args &&...args) {
const char *argv[] = {args..., nullptr};
exec.argv = argv;
return exec_command_sync(exec);
const char *argv[] = {args..., nullptr};
exec.argv = argv;
return exec_command_sync(exec);
}
template <class ...Args>
int exec_command_sync(Args &&...args) {
exec_t exec{};
return exec_command_sync(exec, args...);
exec_t exec{};
return exec_command_sync(exec, args...);
}
template <class ...Args>
void exec_command_async(Args &&...args) {
const char *argv[] = {args..., nullptr};
exec_t exec {
.argv = argv,
.fork = fork_dont_care
};
exec_command(exec);
const char *argv[] = {args..., nullptr};
exec_t exec {
.argv = argv,
.fork = fork_dont_care
};
exec_command(exec);
}

View File

@@ -14,96 +14,96 @@
* License: BSD, full copyright notice please check original source */
ssize_t compat_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) {
char *ptr, *eptr;
char *ptr, *eptr;
if (*buf == nullptr || *bufsiz == 0) {
*bufsiz = BUFSIZ;
if ((*buf = (char *) malloc(*bufsiz)) == nullptr)
return -1;
}
if (*buf == nullptr || *bufsiz == 0) {
*bufsiz = BUFSIZ;
if ((*buf = (char *) malloc(*bufsiz)) == nullptr)
return -1;
}
for (ptr = *buf, eptr = *buf + *bufsiz;;) {
int c = fgetc(fp);
if (c == -1) {
if (feof(fp))
return ptr == *buf ? -1 : ptr - *buf;
else
return -1;
}
*ptr++ = c;
if (c == delimiter) {
*ptr = '\0';
return ptr - *buf;
}
if (ptr + 2 >= eptr) {
char *nbuf;
size_t nbufsiz = *bufsiz * 2;
ssize_t d = ptr - *buf;
if ((nbuf = (char *) realloc(*buf, nbufsiz)) == nullptr)
return -1;
*buf = nbuf;
*bufsiz = nbufsiz;
eptr = nbuf + nbufsiz;
ptr = nbuf + d;
}
}
for (ptr = *buf, eptr = *buf + *bufsiz;;) {
int c = fgetc(fp);
if (c == -1) {
if (feof(fp))
return ptr == *buf ? -1 : ptr - *buf;
else
return -1;
}
*ptr++ = c;
if (c == delimiter) {
*ptr = '\0';
return ptr - *buf;
}
if (ptr + 2 >= eptr) {
char *nbuf;
size_t nbufsiz = *bufsiz * 2;
ssize_t d = ptr - *buf;
if ((nbuf = (char *) realloc(*buf, nbufsiz)) == nullptr)
return -1;
*buf = nbuf;
*bufsiz = nbufsiz;
eptr = nbuf + nbufsiz;
ptr = nbuf + d;
}
}
}
ssize_t compat_getline(char **buf, size_t *bufsiz, FILE *fp) {
return getdelim(buf, bufsiz, '\n', fp);
return getdelim(buf, bufsiz, '\n', fp);
}
/* Original source: https://android.googlesource.com/platform/bionic/+/master/libc/bionic/mntent.cpp
* License: AOSP, full copyright notice please check original source */
struct mntent *compat_getmntent_r(FILE* fp, struct mntent* e, char* buf, int buf_len) {
memset(e, 0, sizeof(*e));
while (fgets(buf, buf_len, fp) != nullptr) {
// Entries look like "proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0".
// That is: mnt_fsname mnt_dir mnt_type mnt_opts 0 0.
int fsname0, fsname1, dir0, dir1, type0, type1, opts0, opts1;
if (sscanf(buf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
&fsname0, &fsname1, &dir0, &dir1, &type0, &type1, &opts0, &opts1,
&e->mnt_freq, &e->mnt_passno) == 2) {
e->mnt_fsname = &buf[fsname0];
buf[fsname1] = '\0';
e->mnt_dir = &buf[dir0];
buf[dir1] = '\0';
e->mnt_type = &buf[type0];
buf[type1] = '\0';
e->mnt_opts = &buf[opts0];
buf[opts1] = '\0';
return e;
}
}
return nullptr;
memset(e, 0, sizeof(*e));
while (fgets(buf, buf_len, fp) != nullptr) {
// Entries look like "proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0".
// That is: mnt_fsname mnt_dir mnt_type mnt_opts 0 0.
int fsname0, fsname1, dir0, dir1, type0, type1, opts0, opts1;
if (sscanf(buf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
&fsname0, &fsname1, &dir0, &dir1, &type0, &type1, &opts0, &opts1,
&e->mnt_freq, &e->mnt_passno) == 2) {
e->mnt_fsname = &buf[fsname0];
buf[fsname1] = '\0';
e->mnt_dir = &buf[dir0];
buf[dir1] = '\0';
e->mnt_type = &buf[type0];
buf[type1] = '\0';
e->mnt_opts = &buf[opts0];
buf[opts1] = '\0';
return e;
}
}
return nullptr;
}
FILE *compat_setmntent(const char* path, const char* mode) {
return fopen(path, mode);
return fopen(path, mode);
}
int compat_endmntent(FILE* fp) {
if (fp != nullptr) {
fclose(fp);
}
return 1;
if (fp != nullptr) {
fclose(fp);
}
return 1;
}
char *compat_hasmntopt(const struct mntent* mnt, const char* opt) {
char* token = mnt->mnt_opts;
char* const end = mnt->mnt_opts + strlen(mnt->mnt_opts);
const size_t optLen = strlen(opt);
while (token) {
char* const tokenEnd = token + optLen;
if (tokenEnd > end) break;
if (memcmp(token, opt, optLen) == 0 &&
(*tokenEnd == '\0' || *tokenEnd == ',' || *tokenEnd == '=')) {
return token;
}
token = strchr(token, ',');
if (token) token++;
}
return nullptr;
char* token = mnt->mnt_opts;
char* const end = mnt->mnt_opts + strlen(mnt->mnt_opts);
const size_t optLen = strlen(opt);
while (token) {
char* const tokenEnd = token + optLen;
if (tokenEnd > end) break;
if (memcmp(token, opt, optLen) == 0 &&
(*tokenEnd == '\0' || *tokenEnd == ',' || *tokenEnd == '=')) {
return token;
}
token = strchr(token, ',');
if (token) token++;
}
return nullptr;
}

View File

@@ -31,38 +31,38 @@ int compat_endmntent(FILE* fp);
char *compat_hasmntopt(const struct mntent* mnt, const char* opt);
static inline int compat_setns(int fd, int nstype) {
return syscall(__NR_setns, fd, nstype);
return syscall(__NR_setns, fd, nstype);
}
static inline int compat_unshare(int flags) {
return syscall(__NR_unshare, flags);
return syscall(__NR_unshare, flags);
}
static inline int compat_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
return syscall(__NR_accept4, sockfd, addr, addrlen, flags);
return syscall(__NR_accept4, sockfd, addr, addrlen, flags);
}
static inline int compat_dup3(int oldfd, int newfd, int flags) {
return syscall(__NR_dup3, oldfd, newfd, flags);
return syscall(__NR_dup3, oldfd, newfd, flags);
}
static inline ssize_t compat_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) {
return syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz);
return syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz);
}
static inline int compat_symlinkat(const char *target, int newdirfd, const char *linkpath) {
return syscall(__NR_symlinkat, target, newdirfd, linkpath);
return syscall(__NR_symlinkat, target, newdirfd, linkpath);
}
static inline int compat_linkat(int olddirfd, const char *oldpath,
int newdirfd, const char *newpath, int flags) {
return syscall(__NR_linkat, olddirfd, oldpath, newdirfd, newpath, flags);
int newdirfd, const char *newpath, int flags) {
return syscall(__NR_linkat, olddirfd, oldpath, newdirfd, newpath, flags);
}
static inline int compat_inotify_init1(int flags) {
return syscall(__NR_inotify_init1, flags);
return syscall(__NR_inotify_init1, flags);
}
static inline int compat_faccessat(int dirfd, const char *pathname, int mode, int flags) {
return syscall(__NR_faccessat, dirfd, pathname, mode, flags);
return syscall(__NR_faccessat, dirfd, pathname, mode, flags);
}

View File

@@ -12,67 +12,67 @@ static int stub(const char *) { return 0; }
static int stub(const char *, const char *) { return 0; }
static int stub(const char *, char **ctx) {
*ctx = strdup("");
return 0;
*ctx = strdup("");
return 0;
}
static int stub(int, const char *) { return 0; }
static int stub(int, char **ctx) {
*ctx = strdup("");
return 0;
*ctx = strdup("");
return 0;
}
// Builtin implementation
static void __freecon(char *s) {
free(s);
free(s);
}
static int __setcon(const char *ctx) {
int fd = open("/proc/self/attr/current", O_WRONLY | O_CLOEXEC);
if (fd < 0)
return fd;
size_t len = strlen(ctx) + 1;
int rc = write(fd, ctx, len);
close(fd);
return rc != len;
int fd = open("/proc/self/attr/current", O_WRONLY | O_CLOEXEC);
if (fd < 0)
return fd;
size_t len = strlen(ctx) + 1;
int rc = write(fd, ctx, len);
close(fd);
return rc != len;
}
static int __getfilecon(const char *path, char **ctx) {
char buf[1024];
int rc = syscall(__NR_getxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
if (rc >= 0)
*ctx = strdup(buf);
return rc;
char buf[1024];
int rc = syscall(__NR_getxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
if (rc >= 0)
*ctx = strdup(buf);
return rc;
}
static int __lgetfilecon(const char *path, char **ctx) {
char buf[1024];
int rc = syscall(__NR_lgetxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
if (rc >= 0)
*ctx = strdup(buf);
return rc;
char buf[1024];
int rc = syscall(__NR_lgetxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
if (rc >= 0)
*ctx = strdup(buf);
return rc;
}
static int __fgetfilecon(int fd, char **ctx) {
char buf[1024];
int rc = syscall(__NR_fgetxattr, fd, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
if (rc >= 0)
*ctx = strdup(buf);
return rc;
char buf[1024];
int rc = syscall(__NR_fgetxattr, fd, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1);
if (rc >= 0)
*ctx = strdup(buf);
return rc;
}
static int __setfilecon(const char *path, const char *ctx) {
return syscall(__NR_setxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
return syscall(__NR_setxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
}
static int __lsetfilecon(const char *path, const char *ctx) {
return syscall(__NR_lsetxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
return syscall(__NR_lsetxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
}
static int __fsetfilecon(int fd, const char *ctx) {
return syscall(__NR_fsetxattr, fd, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
return syscall(__NR_fsetxattr, fd, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0);
}
// Function pointers
@@ -87,34 +87,34 @@ int (*lsetfilecon)(const char *, const char *) = stub;
int (*fsetfilecon)(int, const char *) = stub;
void getfilecon_at(int dirfd, const char *name, char **con) {
char path[4096];
fd_pathat(dirfd, name, path, sizeof(path));
if (lgetfilecon(path, con))
*con = strdup("");
char path[4096];
fd_pathat(dirfd, name, path, sizeof(path));
if (lgetfilecon(path, con))
*con = strdup("");
}
void setfilecon_at(int dirfd, const char *name, const char *con) {
char path[4096];
fd_pathat(dirfd, name, path, sizeof(path));
lsetfilecon(path, con);
char path[4096];
fd_pathat(dirfd, name, path, sizeof(path));
lsetfilecon(path, con);
}
void selinux_builtin_impl() {
setcon = __setcon;
getfilecon = __getfilecon;
lgetfilecon = __lgetfilecon;
fgetfilecon = __fgetfilecon;
setfilecon = __setfilecon;
lsetfilecon = __lsetfilecon;
fsetfilecon = __fsetfilecon;
setcon = __setcon;
getfilecon = __getfilecon;
lgetfilecon = __lgetfilecon;
fgetfilecon = __fgetfilecon;
setfilecon = __setfilecon;
lsetfilecon = __lsetfilecon;
fsetfilecon = __fsetfilecon;
}
void dload_selinux() {
if (access("/system/lib/libselinux.so", F_OK))
return;
/* We only check whether libselinux.so exists but don't dlopen.
* For some reason calling symbols returned from dlsym
* will result to SEGV_ACCERR on some devices.
* Always use builtin implementations for SELinux stuffs. */
selinux_builtin_impl();
if (access("/system/lib/libselinux.so", F_OK))
return;
/* We only check whether libselinux.so exists but don't dlopen.
* For some reason calling symbols returned from dlsym
* will result to SEGV_ACCERR on some devices.
* Always use builtin implementations for SELinux stuffs. */
selinux_builtin_impl();
}

View File

@@ -2,128 +2,128 @@
#include <stream.hpp>
static int strm_read(void *v, char *buf, int len) {
auto strm = reinterpret_cast<stream *>(v);
return strm->read(buf, len);
auto strm = reinterpret_cast<stream *>(v);
return strm->read(buf, len);
}
static int strm_write(void *v, const char *buf, int len) {
auto strm = reinterpret_cast<stream *>(v);
return strm->write(buf, len);
auto strm = reinterpret_cast<stream *>(v);
return strm->write(buf, len);
}
static fpos_t strm_seek(void *v, fpos_t off, int whence) {
auto strm = reinterpret_cast<stream *>(v);
return strm->seek(off, whence);
auto strm = reinterpret_cast<stream *>(v);
return strm->seek(off, whence);
}
static int strm_close(void *v) {
auto strm = reinterpret_cast<stream *>(v);
delete strm;
return 0;
auto strm = reinterpret_cast<stream *>(v);
delete strm;
return 0;
}
sFILE make_stream_fp(stream_ptr &&strm) {
auto fp = make_file(funopen(strm.release(), strm_read, strm_write, strm_seek, strm_close));
setbuf(fp.get(), nullptr);
return fp;
auto fp = make_file(funopen(strm.release(), strm_read, strm_write, strm_seek, strm_close));
setbuf(fp.get(), nullptr);
return fp;
}
int stream::read(void *buf, size_t len) {
LOGE("This stream does not support read\n");
return -1;
LOGE("This stream does not support read\n");
return -1;
}
int stream::write(const void *buf, size_t len) {
LOGE("This stream does not support write\n");
return -1;
LOGE("This stream does not support write\n");
return -1;
}
off_t stream::seek(off_t off, int whence) {
LOGE("This stream does not support seek\n");
return -1;
LOGE("This stream does not support seek\n");
return -1;
}
int fp_stream::read(void *buf, size_t len) {
return fread(buf, 1, len, fp.get());
return fread(buf, 1, len, fp.get());
}
int fp_stream::write(const void *buf, size_t len) {
return fwrite(buf, 1, len, fp.get());
return fwrite(buf, 1, len, fp.get());
}
off_t fp_stream::seek(off_t off, int whence) {
return fseek(fp.get(), off, whence);
return fseek(fp.get(), off, whence);
}
int filter_stream::read(void *buf, size_t len) {
return base->read(buf, len);
return base->read(buf, len);
}
int filter_stream::write(const void *buf, size_t len) {
return base->write(buf, len);
return base->write(buf, len);
}
byte_stream::byte_stream(uint8_t *&buf, size_t &len) : _buf(buf), _len(len) {
buf = nullptr;
len = 0;
buf = nullptr;
len = 0;
}
int byte_stream::read(void *buf, size_t len) {
len = std::min(len, _len - _pos);
memcpy(buf, _buf + _pos, len);
return len;
len = std::min(len, _len - _pos);
memcpy(buf, _buf + _pos, len);
return len;
}
int byte_stream::write(const void *buf, size_t len) {
resize(_pos + len);
memcpy(_buf + _pos, buf, len);
_pos += len;
_len = std::max(_len, _pos);
return len;
resize(_pos + len);
memcpy(_buf + _pos, buf, len);
_pos += len;
_len = std::max(_len, _pos);
return len;
}
off_t byte_stream::seek(off_t off, int whence) {
off_t np;
switch (whence) {
case SEEK_CUR:
np = _pos + off;
break;
case SEEK_END:
np = _len + off;
break;
case SEEK_SET:
np = off;
break;
default:
return -1;
}
resize(np, true);
_pos = np;
return np;
off_t np;
switch (whence) {
case SEEK_CUR:
np = _pos + off;
break;
case SEEK_END:
np = _len + off;
break;
case SEEK_SET:
np = off;
break;
default:
return -1;
}
resize(np, true);
_pos = np;
return np;
}
void byte_stream::resize(size_t new_pos, bool zero) {
bool resize = false;
size_t old_cap = _cap;
while (new_pos > _cap) {
_cap = _cap ? (_cap << 1) - (_cap >> 1) : 1 << 12;
resize = true;
}
if (resize) {
_buf = (uint8_t *) xrealloc(_buf, _cap);
if (zero)
memset(_buf + old_cap, 0, _cap - old_cap);
}
bool resize = false;
size_t old_cap = _cap;
while (new_pos > _cap) {
_cap = _cap ? (_cap << 1) - (_cap >> 1) : 1 << 12;
resize = true;
}
if (resize) {
_buf = (uint8_t *) xrealloc(_buf, _cap);
if (zero)
memset(_buf + old_cap, 0, _cap - old_cap);
}
}
int fd_stream::read(void *buf, size_t len) {
return ::read(fd, buf, len);
return ::read(fd, buf, len);
}
int fd_stream::write(const void *buf, size_t len) {
return ::write(fd, buf, len);
return ::write(fd, buf, len);
}
off_t fd_stream::seek(off_t off, int whence) {
return lseek(fd, off, whence);
return lseek(fd, off, whence);
}

View File

@@ -15,458 +15,458 @@
using namespace std;
FILE *xfopen(const char *pathname, const char *mode) {
FILE *fp = fopen(pathname, mode);
if (fp == nullptr) {
PLOGE("fopen: %s", pathname);
}
return fp;
FILE *fp = fopen(pathname, mode);
if (fp == nullptr) {
PLOGE("fopen: %s", pathname);
}
return fp;
}
FILE *xfdopen(int fd, const char *mode) {
FILE *fp = fdopen(fd, mode);
if (fp == nullptr) {
PLOGE("fopen");
}
return fp;
FILE *fp = fdopen(fd, mode);
if (fp == nullptr) {
PLOGE("fopen");
}
return fp;
}
int xopen(const char *pathname, int flags) {
int fd = open(pathname, flags);
if (fd < 0) {
PLOGE("open: %s", pathname);
}
return fd;
int fd = open(pathname, flags);
if (fd < 0) {
PLOGE("open: %s", pathname);
}
return fd;
}
int xopen(const char *pathname, int flags, mode_t mode) {
int fd = open(pathname, flags, mode);
if (fd < 0) {
PLOGE("open: %s", pathname);
}
return fd;
int fd = open(pathname, flags, mode);
if (fd < 0) {
PLOGE("open: %s", pathname);
}
return fd;
}
int xopenat(int dirfd, const char *pathname, int flags) {
int fd = openat(dirfd, pathname, flags);
if (fd < 0) {
PLOGE("openat: %s", pathname);
}
return fd;
int fd = openat(dirfd, pathname, flags);
if (fd < 0) {
PLOGE("openat: %s", pathname);
}
return fd;
}
int xopenat(int dirfd, const char *pathname, int flags, mode_t mode) {
int fd = openat(dirfd, pathname, flags, mode);
if (fd < 0) {
PLOGE("openat: %s", pathname);
}
return fd;
int fd = openat(dirfd, pathname, flags, mode);
if (fd < 0) {
PLOGE("openat: %s", pathname);
}
return fd;
}
ssize_t xwrite(int fd, const void *buf, size_t count) {
int ret = write(fd, buf, count);
if (count != ret) {
PLOGE("write");
}
return ret;
int ret = write(fd, buf, count);
if (count != ret) {
PLOGE("write");
}
return ret;
}
// Read error other than EOF
ssize_t xread(int fd, void *buf, size_t count) {
int ret = read(fd, buf, count);
if (ret < 0) {
PLOGE("read");
}
return ret;
int ret = read(fd, buf, count);
if (ret < 0) {
PLOGE("read");
}
return ret;
}
// Read exact same size as count
ssize_t xxread(int fd, void *buf, size_t count) {
int ret = read(fd, buf, count);
if (count != ret) {
PLOGE("read (%zu != %d)", count, ret);
}
return ret;
int ret = read(fd, buf, count);
if (count != ret) {
PLOGE("read (%zu != %d)", count, ret);
}
return ret;
}
int xpipe2(int pipefd[2], int flags) {
int ret = pipe2(pipefd, flags);
if (ret < 0) {
PLOGE("pipe2");
}
return ret;
int ret = pipe2(pipefd, flags);
if (ret < 0) {
PLOGE("pipe2");
}
return ret;
}
int xsetns(int fd, int nstype) {
int ret = setns(fd, nstype);
if (ret < 0) {
PLOGE("setns");
}
return ret;
int ret = setns(fd, nstype);
if (ret < 0) {
PLOGE("setns");
}
return ret;
}
int xunshare(int flags) {
int ret = unshare(flags);
if (ret < 0) {
PLOGE("unshare");
}
return ret;
int ret = unshare(flags);
if (ret < 0) {
PLOGE("unshare");
}
return ret;
}
DIR *xopendir(const char *name) {
DIR *d = opendir(name);
if (d == nullptr) {
PLOGE("opendir: %s", name);
}
return d;
DIR *d = opendir(name);
if (d == nullptr) {
PLOGE("opendir: %s", name);
}
return d;
}
DIR *xfdopendir(int fd) {
DIR *d = fdopendir(fd);
if (d == nullptr) {
PLOGE("fdopendir");
}
return d;
DIR *d = fdopendir(fd);
if (d == nullptr) {
PLOGE("fdopendir");
}
return d;
}
struct dirent *xreaddir(DIR *dirp) {
errno = 0;
for (dirent *e;;) {
e = readdir(dirp);
if (e == nullptr) {
if (errno)
PLOGE("readdir");
return nullptr;
} else if (e->d_name == "."sv || e->d_name == ".."sv) {
// Filter . and .. for users
continue;
}
return e;
}
errno = 0;
for (dirent *e;;) {
e = readdir(dirp);
if (e == nullptr) {
if (errno)
PLOGE("readdir");
return nullptr;
} else if (e->d_name == "."sv || e->d_name == ".."sv) {
// Filter . and .. for users
continue;
}
return e;
}
}
pid_t xsetsid() {
pid_t pid = setsid();
if (pid < 0) {
PLOGE("setsid");
}
return pid;
pid_t pid = setsid();
if (pid < 0) {
PLOGE("setsid");
}
return pid;
}
int xsocket(int domain, int type, int protocol) {
int fd = socket(domain, type, protocol);
if (fd < 0) {
PLOGE("socket");
}
return fd;
int fd = socket(domain, type, protocol);
if (fd < 0) {
PLOGE("socket");
}
return fd;
}
int xbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
int ret = bind(sockfd, addr, addrlen);
if (ret < 0) {
PLOGE("bind");
}
return ret;
int ret = bind(sockfd, addr, addrlen);
if (ret < 0) {
PLOGE("bind");
}
return ret;
}
int xlisten(int sockfd, int backlog) {
int ret = listen(sockfd, backlog);
if (ret < 0) {
PLOGE("listen");
}
return ret;
int ret = listen(sockfd, backlog);
if (ret < 0) {
PLOGE("listen");
}
return ret;
}
static int accept4_compat(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
int fd = accept(sockfd, addr, addrlen);
if (fd < 0) {
PLOGE("accept");
} else {
if (flags & SOCK_CLOEXEC)
fcntl(fd, F_SETFD, FD_CLOEXEC);
if (flags & SOCK_NONBLOCK) {
int i = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, i | O_NONBLOCK);
}
}
return fd;
int fd = accept(sockfd, addr, addrlen);
if (fd < 0) {
PLOGE("accept");
} else {
if (flags & SOCK_CLOEXEC)
fcntl(fd, F_SETFD, FD_CLOEXEC);
if (flags & SOCK_NONBLOCK) {
int i = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, i | O_NONBLOCK);
}
}
return fd;
}
int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
int fd = accept4(sockfd, addr, addrlen, flags);
if (fd < 0) {
if (errno == ENOSYS)
return accept4_compat(sockfd, addr, addrlen, flags);
PLOGE("accept4");
}
return fd;
int fd = accept4(sockfd, addr, addrlen, flags);
if (fd < 0) {
if (errno == ENOSYS)
return accept4_compat(sockfd, addr, addrlen, flags);
PLOGE("accept4");
}
return fd;
}
void *xmalloc(size_t size) {
void *p = malloc(size);
if (p == nullptr) {
PLOGE("malloc");
}
return p;
void *p = malloc(size);
if (p == nullptr) {
PLOGE("malloc");
}
return p;
}
void *xcalloc(size_t nmemb, size_t size) {
void *p = calloc(nmemb, size);
if (p == nullptr) {
PLOGE("calloc");
}
return p;
void *p = calloc(nmemb, size);
if (p == nullptr) {
PLOGE("calloc");
}
return p;
}
void *xrealloc(void *ptr, size_t size) {
void *p = realloc(ptr, size);
if (p == nullptr) {
PLOGE("realloc");
}
return p;
void *p = realloc(ptr, size);
if (p == nullptr) {
PLOGE("realloc");
}
return p;
}
ssize_t xsendmsg(int sockfd, const struct msghdr *msg, int flags) {
int sent = sendmsg(sockfd, msg, flags);
if (sent < 0) {
PLOGE("sendmsg");
}
return sent;
int sent = sendmsg(sockfd, msg, flags);
if (sent < 0) {
PLOGE("sendmsg");
}
return sent;
}
ssize_t xrecvmsg(int sockfd, struct msghdr *msg, int flags) {
int rec = recvmsg(sockfd, msg, flags);
if (rec < 0) {
PLOGE("recvmsg");
}
return rec;
int rec = recvmsg(sockfd, msg, flags);
if (rec < 0) {
PLOGE("recvmsg");
}
return rec;
}
int xpthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg) {
errno = pthread_create(thread, attr, start_routine, arg);
if (errno) {
PLOGE("pthread_create");
}
return errno;
void *(*start_routine) (void *), void *arg) {
errno = pthread_create(thread, attr, start_routine, arg);
if (errno) {
PLOGE("pthread_create");
}
return errno;
}
int xstat(const char *pathname, struct stat *buf) {
int ret = stat(pathname, buf);
if (ret < 0) {
PLOGE("stat %s", pathname);
}
return ret;
int ret = stat(pathname, buf);
if (ret < 0) {
PLOGE("stat %s", pathname);
}
return ret;
}
int xlstat(const char *pathname, struct stat *buf) {
int ret = lstat(pathname, buf);
if (ret < 0) {
PLOGE("lstat %s", pathname);
}
return ret;
int ret = lstat(pathname, buf);
if (ret < 0) {
PLOGE("lstat %s", pathname);
}
return ret;
}
int xfstat(int fd, struct stat *buf) {
int ret = fstat(fd, buf);
if (ret < 0) {
PLOGE("fstat %d", fd);
}
return ret;
int ret = fstat(fd, buf);
if (ret < 0) {
PLOGE("fstat %d", fd);
}
return ret;
}
int xdup(int fd) {
int ret = dup(fd);
if (ret < 0) {
PLOGE("dup");
}
return ret;
int ret = dup(fd);
if (ret < 0) {
PLOGE("dup");
}
return ret;
}
int xdup2(int oldfd, int newfd) {
int ret = dup2(oldfd, newfd);
if (ret < 0) {
PLOGE("dup2");
}
return ret;
int ret = dup2(oldfd, newfd);
if (ret < 0) {
PLOGE("dup2");
}
return ret;
}
int xdup3(int oldfd, int newfd, int flags) {
int ret = dup3(oldfd, newfd, flags);
if (ret < 0) {
PLOGE("dup3");
}
return ret;
int ret = dup3(oldfd, newfd, flags);
if (ret < 0) {
PLOGE("dup3");
}
return ret;
}
ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz) {
ssize_t ret = readlink(pathname, buf, bufsiz);
if (ret < 0) {
PLOGE("readlink %s", pathname);
} else {
buf[ret] = '\0';
}
return ret;
ssize_t ret = readlink(pathname, buf, bufsiz);
if (ret < 0) {
PLOGE("readlink %s", pathname);
} else {
buf[ret] = '\0';
}
return ret;
}
ssize_t xreadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) {
// readlinkat() may fail on x86 platform, returning random value
// instead of number of bytes placed in buf (length of link)
// readlinkat() may fail on x86 platform, returning random value
// instead of number of bytes placed in buf (length of link)
#if defined(__i386__) || defined(__x86_64__)
memset(buf, 0, bufsiz);
ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz);
if (ret < 0) {
PLOGE("readlinkat %s", pathname);
}
return ret;
memset(buf, 0, bufsiz);
ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz);
if (ret < 0) {
PLOGE("readlinkat %s", pathname);
}
return ret;
#else
ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz);
if (ret < 0) {
PLOGE("readlinkat %s", pathname);
} else {
buf[ret] = '\0';
}
return ret;
ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz);
if (ret < 0) {
PLOGE("readlinkat %s", pathname);
} else {
buf[ret] = '\0';
}
return ret;
#endif
}
int xsymlink(const char *target, const char *linkpath) {
int ret = symlink(target, linkpath);
if (ret < 0) {
PLOGE("symlink %s->%s", target, linkpath);
}
return ret;
int ret = symlink(target, linkpath);
if (ret < 0) {
PLOGE("symlink %s->%s", target, linkpath);
}
return ret;
}
int xsymlinkat(const char *target, int newdirfd, const char *linkpath) {
int ret = symlinkat(target, newdirfd, linkpath);
if (ret < 0) {
PLOGE("symlinkat %s->%s", target, linkpath);
}
return ret;
int ret = symlinkat(target, newdirfd, linkpath);
if (ret < 0) {
PLOGE("symlinkat %s->%s", target, linkpath);
}
return ret;
}
int xlinkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) {
int ret = linkat(olddirfd, oldpath, newdirfd, newpath, flags);
if (ret < 0) {
PLOGE("linkat %s->%s", oldpath, newpath);
}
return ret;
int ret = linkat(olddirfd, oldpath, newdirfd, newpath, flags);
if (ret < 0) {
PLOGE("linkat %s->%s", oldpath, newpath);
}
return ret;
}
int xmount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data) {
int ret = mount(source, target, filesystemtype, mountflags, data);
if (ret < 0) {
PLOGE("mount %s->%s", source, target);
}
return ret;
const char *filesystemtype, unsigned long mountflags,
const void *data) {
int ret = mount(source, target, filesystemtype, mountflags, data);
if (ret < 0) {
PLOGE("mount %s->%s", source, target);
}
return ret;
}
int xumount(const char *target) {
int ret = umount(target);
if (ret < 0) {
PLOGE("umount %s", target);
}
return ret;
int ret = umount(target);
if (ret < 0) {
PLOGE("umount %s", target);
}
return ret;
}
int xumount2(const char *target, int flags) {
int ret = umount2(target, flags);
if (ret < 0) {
PLOGE("umount2 %s", target);
}
return ret;
int ret = umount2(target, flags);
if (ret < 0) {
PLOGE("umount2 %s", target);
}
return ret;
}
int xrename(const char *oldpath, const char *newpath) {
int ret = rename(oldpath, newpath);
if (ret < 0) {
PLOGE("rename %s->%s", oldpath, newpath);
}
return ret;
int ret = rename(oldpath, newpath);
if (ret < 0) {
PLOGE("rename %s->%s", oldpath, newpath);
}
return ret;
}
int xmkdir(const char *pathname, mode_t mode) {
int ret = mkdir(pathname, mode);
if (ret < 0 && errno != EEXIST) {
PLOGE("mkdir %s %u", pathname, mode);
}
return ret;
int ret = mkdir(pathname, mode);
if (ret < 0 && errno != EEXIST) {
PLOGE("mkdir %s %u", pathname, mode);
}
return ret;
}
int xmkdirs(const char *pathname, mode_t mode) {
int ret = mkdirs(pathname, mode);
if (ret < 0) {
PLOGE("mkdirs %s", pathname);
}
return ret;
int ret = mkdirs(pathname, mode);
if (ret < 0) {
PLOGE("mkdirs %s", pathname);
}
return ret;
}
int xmkdirat(int dirfd, const char *pathname, mode_t mode) {
int ret = mkdirat(dirfd, pathname, mode);
if (ret < 0 && errno != EEXIST) {
PLOGE("mkdirat %s %u", pathname, mode);
}
return ret;
int ret = mkdirat(dirfd, pathname, mode);
if (ret < 0 && errno != EEXIST) {
PLOGE("mkdirat %s %u", pathname, mode);
}
return ret;
}
void *xmmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset) {
void *ret = mmap(addr, length, prot, flags, fd, offset);
if (ret == MAP_FAILED) {
PLOGE("mmap");
}
return ret;
int fd, off_t offset) {
void *ret = mmap(addr, length, prot, flags, fd, offset);
if (ret == MAP_FAILED) {
PLOGE("mmap");
}
return ret;
}
ssize_t xsendfile(int out_fd, int in_fd, off_t *offset, size_t count) {
ssize_t ret = sendfile(out_fd, in_fd, offset, count);
if (count != ret) {
PLOGE("sendfile");
}
return ret;
ssize_t ret = sendfile(out_fd, in_fd, offset, count);
if (count != ret) {
PLOGE("sendfile");
}
return ret;
}
pid_t xfork() {
int ret = fork();
if (ret < 0) {
PLOGE("fork");
}
return ret;
int ret = fork();
if (ret < 0) {
PLOGE("fork");
}
return ret;
}
int xpoll(struct pollfd *fds, nfds_t nfds, int timeout) {
int ret = poll(fds, nfds, timeout);
if (ret < 0) {
PLOGE("poll");
}
return ret;
int ret = poll(fds, nfds, timeout);
if (ret < 0) {
PLOGE("poll");
}
return ret;
}
int xinotify_init1(int flags) {
int ret = inotify_init1(flags);
if (ret < 0) {
PLOGE("inotify_init1");
}
return ret;
int ret = inotify_init1(flags);
if (ret < 0) {
PLOGE("inotify_init1");
}
return ret;
}
char *xrealpath(const char *path, char *resolved_path) {
char buf[PATH_MAX];
char *ret = realpath(path, buf);
if (ret == nullptr) {
PLOGE("xrealpath");
} else {
strcpy(resolved_path, buf);
}
return ret;
char buf[PATH_MAX];
char *ret = realpath(path, buf);
if (ret == nullptr) {
PLOGE("xrealpath");
} else {
strcpy(resolved_path, buf);
}
return ret;
}
int xmknod(const char *pathname, mode_t mode, dev_t dev) {
int ret = mknod(pathname, mode, dev);
if (ret < 0) {
PLOGE("mknod");
}
return ret;
int ret = mknod(pathname, mode, dev);
if (ret < 0) {
PLOGE("mknod");
}
return ret;
}

View File

@@ -32,7 +32,7 @@ extern "C" void *xrealloc(void *ptr, size_t size);
ssize_t xsendmsg(int sockfd, const struct msghdr *msg, int flags);
ssize_t xrecvmsg(int sockfd, struct msghdr *msg, int flags);
int xpthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
void *(*start_routine) (void *), void *arg);
int xstat(const char *pathname, struct stat *buf);
int xlstat(const char *pathname, struct stat *buf);
int xfstat(int fd, struct stat *buf);
@@ -45,8 +45,8 @@ int xsymlink(const char *target, const char *linkpath);
int xsymlinkat(const char *target, int newdirfd, const char *linkpath);
int xlinkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags);
int xmount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data);
const char *filesystemtype, unsigned long mountflags,
const void *data);
int xumount(const char *target);
int xumount2(const char *target, int flags);
int xrename(const char *oldpath, const char *newpath);