diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 9e6f10c97..6c1ba2175 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -131,7 +131,7 @@ void node_entry::create_module_tree(const char *module) { auto full_path = get_path(); snprintf(buf, PATH_MAX, "%s/%s%s", MODULEROOT, module, full_path.c_str()); - unique_ptr dir(xopendir(buf), closedir); + auto dir = xopen_dir(buf); if (!dir) return; @@ -148,7 +148,7 @@ void node_entry::create_module_tree(const char *module) { return; } - for (struct dirent *entry; (entry = xreaddir(dir.get()));) { + for (dirent *entry; (entry = xreaddir(dir.get()));) { if (entry->d_name == "."sv || entry->d_name == ".."sv) continue; // Create new node @@ -207,22 +207,18 @@ void node_entry::create_module_tree(const char *module) { } void node_entry::clone_skeleton() { - DIR *dir; - struct dirent *entry; - // Clone the structure auto full_path = get_path(); - snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path.c_str()); - if (!(dir = xopendir(buf))) - return; - while ((entry = xreaddir(dir))) { - if (entry->d_name == "."sv || entry->d_name == ".."sv) - continue; - // Create dummy node - auto dummy = new node_entry(entry->d_name, entry->d_type, IS_DUMMY); - insert(dummy); - } - closedir(dir); + snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path.data()); + if (auto dir = xopen_dir(buf); dir) { + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (entry->d_name == "."sv || entry->d_name == ".."sv) + continue; + // Create dummy node + auto dummy = new node_entry(entry->d_name, entry->d_type, IS_DUMMY); + insert(dummy); + } + } else { return; } if (status & IS_SKEL) { file_attr attr; @@ -460,9 +456,8 @@ void remove_modules() { LOGI("* Remove all modules and reboot"); chdir(MODULEROOT); rm_rf("lost+found"); - DIR *dir = xopendir("."); - struct dirent *entry; - while ((entry = xreaddir(dir))) { + auto dir = xopen_dir("."); + for (dirent *entry; (entry = xreaddir(dir.get()));) { if (entry->d_type == DT_DIR) { if (entry->d_name == "."sv || entry->d_name == ".."sv || entry->d_name == ".core"sv) continue; @@ -471,7 +466,6 @@ void remove_modules() { chdir(".."); } } - closedir(dir); chdir("/"); reboot(); } @@ -479,9 +473,8 @@ void remove_modules() { static void collect_modules() { chdir(MODULEROOT); rm_rf("lost+found"); - DIR *dir = xopendir("."); - struct dirent *entry; - while ((entry = xreaddir(dir))) { + auto dir = xopen_dir("."); + for (dirent *entry; (entry = xreaddir(dir.get()));) { if (entry->d_type == DT_DIR) { if (entry->d_name == "."sv || entry->d_name == ".."sv || entry->d_name == ".core"sv) continue; @@ -501,7 +494,6 @@ static void collect_modules() { chdir(".."); } } - closedir(dir); chdir("/"); } @@ -575,15 +567,14 @@ static bool check_data() { } void unlock_blocks() { - DIR *dir; - struct dirent *entry; int fd, dev, OFF = 0; - if (!(dir = xopendir("/dev/block"))) + auto dir = xopen_dir("/dev/block"); + if (!dir) return; - dev = dirfd(dir); + dev = dirfd(dir.get()); - while((entry = readdir(dir))) { + for (dirent *entry; (entry = readdir(dir.get()));) { if (entry->d_type == DT_BLK) { if ((fd = openat(dev, entry->d_name, O_RDONLY | O_CLOEXEC)) < 0) continue; @@ -592,7 +583,6 @@ void unlock_blocks() { close(fd); } } - closedir(dir); } static bool log_dump = false; diff --git a/native/jni/core/daemon.cpp b/native/jni/core/daemon.cpp index d923b1671..c772b3a8a 100644 --- a/native/jni/core/daemon.cpp +++ b/native/jni/core/daemon.cpp @@ -118,10 +118,10 @@ static void main_daemon() { // Unmount pre-init patches if (access(ROOTMNT, F_OK) == 0) { - file_readline(ROOTMNT, [](auto line) -> bool { + file_readline(true, ROOTMNT, [](auto line) -> bool { umount2(line.data(), MNT_DETACH); return true; - }, true); + }); } LOGI(SHOW_VER(Magisk) " daemon started\n"); diff --git a/native/jni/core/scripting.cpp b/native/jni/core/scripting.cpp index ccb4e8da7..070e9c3d2 100644 --- a/native/jni/core/scripting.cpp +++ b/native/jni/core/scripting.cpp @@ -26,15 +26,14 @@ void exec_script(const char *script) { void exec_common_script(const char *stage) { char path[4096]; - DIR *dir; - struct dirent *entry; sprintf(path, SECURE_DIR "/%s.d", stage); - if (!(dir = xopendir(path))) + auto dir = xopen_dir(path); + if (!dir) return; chdir(path); - bool pfs = strcmp(stage, "post-fs-data") == 0; - while ((entry = xreaddir(dir))) { + bool pfs = stage == "post-fs-data"sv; + for (dirent *entry; (entry = xreaddir(dir.get()));) { if (entry->d_type == DT_REG) { if (access(entry->d_name, X_OK) == -1) continue; @@ -50,13 +49,12 @@ void exec_common_script(const char *stage) { } } - closedir(dir); chdir("/"); } void exec_module_script(const char *stage, const vector &module_list) { char path[4096]; - bool pfs = strcmp(stage, "post-fs-data") == 0; + bool pfs = stage == "post-fs-data"sv; for (auto &m : module_list) { const char* module = m.c_str(); sprintf(path, MODULEROOT "/%s/%s.sh", module, stage); diff --git a/native/jni/init/init.cpp b/native/jni/init/init.cpp index 23a3d6f06..394a4dded 100644 --- a/native/jni/init/init.cpp +++ b/native/jni/init/init.cpp @@ -197,10 +197,10 @@ int main(int argc, char *argv[]) { return test_main(argc, argv); #endif - if (argc > 1 && strcmp(argv[1], "-x") == 0) { - if (strcmp(argv[2], "magisk") == 0) + if (argc > 1 && argv[1] == "-x"sv) { + if (argv[2] == "magisk"sv) return dump_magisk(argv[3], 0755); - else if (strcmp(argv[2], "manager") == 0) + else if (argv[2] == "manager"sv) return dump_manager(argv[3], 0644); } @@ -208,27 +208,28 @@ int main(int argc, char *argv[]) { return 1; setup_klog(); - if (argc > 1 && argv[1] == "selinux_setup"sv) { - auto init = make_unique(argv); - init->start(); - } - - cmdline cmd{}; - load_kernel_info(&cmd); - unique_ptr init; - if (cmd.force_normal_boot) { - init = make_unique(argv, &cmd); - } else if (cmd.skip_initramfs) { - init = make_unique(argv, &cmd); + cmdline cmd{}; + + if (argc > 1 && argv[1] == "selinux_setup"sv) { + init = make_unique(argv); } else { - decompress_ramdisk(); - if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0) - init = make_unique(argv, &cmd); - else if (access("/apex", F_OK) == 0) - init = make_unique(argv, &cmd); - else - init = make_unique(argv, &cmd); + // This will also mount /sys and /proc + load_kernel_info(&cmd); + + if (cmd.force_normal_boot) { + init = make_unique(argv, &cmd); + } else if (cmd.skip_initramfs) { + init = make_unique(argv, &cmd); + } else { + decompress_ramdisk(); + if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0) + init = make_unique(argv, &cmd); + else if (access("/apex", F_OK) == 0) + init = make_unique(argv, &cmd); + else + init = make_unique(argv, &cmd); + } } // Run the main routine diff --git a/native/jni/init/mount.cpp b/native/jni/init/mount.cpp index 49b7a27e5..c8bcbc5bf 100644 --- a/native/jni/init/mount.cpp +++ b/native/jni/init/mount.cpp @@ -44,17 +44,15 @@ static void parse_device(devinfo *dev, const char *uevent) { static void collect_devices() { char path[128]; devinfo dev{}; - DIR *dir = xopendir("/sys/dev/block"); - if (dir == nullptr) - return; - for (dirent *entry; (entry = readdir(dir));) { - if (entry->d_name == "."sv || entry->d_name == ".."sv) - continue; - sprintf(path, "/sys/dev/block/%s/uevent", entry->d_name); - parse_device(&dev, path); - dev_list.push_back(dev); + if (auto dir = xopen_dir("/sys/dev/block"); dir) { + for (dirent *entry; (entry = readdir(dir.get()));) { + if (entry->d_name == "."sv || entry->d_name == ".."sv) + continue; + sprintf(path, "/sys/dev/block/%s/uevent", entry->d_name); + parse_device(&dev, path); + dev_list.push_back(dev); + } } - closedir(dir); } static int64_t setup_block(bool write_block = true) { diff --git a/native/jni/init/rootdir.cpp b/native/jni/init/rootdir.cpp index 27fde186d..c1ab38c5b 100644 --- a/native/jni/init/rootdir.cpp +++ b/native/jni/init/rootdir.cpp @@ -426,17 +426,16 @@ static void patch_fstab(const string &fstab) { #define FSR "/first_stage_ramdisk" void ABFirstStageInit::prepare() { - DIR *dir = xopendir(FSR); + auto dir = xopen_dir(FSR); if (!dir) return; string fstab(FSR "/"); - for (dirent *de; (de = readdir(dir));) { + for (dirent *de; (de = xreaddir(dir.get()));) { if (strstr(de->d_name, "fstab")) { fstab += de->d_name; break; } } - closedir(dir); if (fstab.length() == sizeof(FSR)) return; @@ -453,14 +452,13 @@ void ABFirstStageInit::prepare() { } void AFirstStageInit::prepare() { - DIR *dir = xopendir("/"); - for (dirent *de; (de = readdir(dir));) { + auto dir = xopen_dir("/"); + for (dirent *de; (de = xreaddir(dir.get()));) { if (strstr(de->d_name, "fstab")) { patch_fstab(de->d_name); break; } } - closedir(dir); // Move stuffs for next stage xmkdir("/system", 0755); diff --git a/native/jni/magiskboot/bootimg.cpp b/native/jni/magiskboot/bootimg.cpp index 93745bb88..3ab44d753 100644 --- a/native/jni/magiskboot/bootimg.cpp +++ b/native/jni/magiskboot/bootimg.cpp @@ -22,14 +22,14 @@ uint32_t dyn_img_hdr::j32 = 0; uint64_t dyn_img_hdr::j64 = 0; static void decompress(format_t type, int fd, const void *in, size_t size) { - auto ptr = get_decoder(type, make_stream(fd)); + auto ptr = get_decoder(type, make_unique(fd)); ptr->write(in, size); } static off_t compress(format_t type, int fd, const void *in, size_t size) { auto prev = lseek(fd, 0, SEEK_CUR); { - auto strm = get_encoder(type, make_stream(fd)); + auto strm = get_encoder(type, make_unique(fd)); strm->write(in, size); } auto now = lseek(fd, 0, SEEK_CUR); diff --git a/native/jni/magiskboot/compress.cpp b/native/jni/magiskboot/compress.cpp index 8059aa3d1..ee5bae9b8 100644 --- a/native/jni/magiskboot/compress.cpp +++ b/native/jni/magiskboot/compress.cpp @@ -57,7 +57,7 @@ protected: ENCODE } mode; - gz_strm(mode_t mode, sFILE &&fp) : cpr_stream(std::move(fp)), mode(mode) { + gz_strm(mode_t mode, stream_ptr &&base) : cpr_stream(std::move(base)), mode(mode) { switch(mode) { case DECODE: inflateInit2(&strm, 15 | 16); @@ -99,12 +99,12 @@ private: class gz_decoder : public gz_strm { public: - explicit gz_decoder(sFILE &&fp) : gz_strm(DECODE, std::move(fp)) {}; + explicit gz_decoder(stream_ptr &&base) : gz_strm(DECODE, std::move(base)) {}; }; class gz_encoder : public gz_strm { public: - explicit gz_encoder(sFILE &&fp) : gz_strm(ENCODE, std::move(fp)) {}; + explicit gz_encoder(stream_ptr &&base) : gz_strm(ENCODE, std::move(base)) {}; }; class bz_strm : public cpr_stream { @@ -131,7 +131,7 @@ protected: ENCODE } mode; - bz_strm(mode_t mode, sFILE &&fp) : cpr_stream(std::move(fp)), mode(mode) { + bz_strm(mode_t mode, stream_ptr &&base) : cpr_stream(std::move(base)), mode(mode) { switch(mode) { case DECODE: BZ2_bzDecompressInit(&strm, 0, 0); @@ -173,12 +173,12 @@ private: class bz_decoder : public bz_strm { public: - explicit bz_decoder(sFILE &&fp) : bz_strm(DECODE, std::move(fp)) {}; + explicit bz_decoder(stream_ptr &&base) : bz_strm(DECODE, std::move(base)) {}; }; class bz_encoder : public bz_strm { public: - explicit bz_encoder(sFILE &&fp) : bz_strm(ENCODE, std::move(fp)) {}; + explicit bz_encoder(stream_ptr &&base) : bz_strm(ENCODE, std::move(base)) {}; }; class lzma_strm : public cpr_stream { @@ -199,8 +199,8 @@ protected: ENCODE_LZMA } mode; - lzma_strm(mode_t mode, sFILE &&fp) - : cpr_stream(std::move(fp)), mode(mode), strm(LZMA_STREAM_INIT) { + lzma_strm(mode_t mode, stream_ptr &&base) + : cpr_stream(std::move(base)), mode(mode), strm(LZMA_STREAM_INIT) { lzma_options_lzma opt; // Initialize preset @@ -247,22 +247,22 @@ private: class lzma_decoder : public lzma_strm { public: - explicit lzma_decoder(sFILE &&fp) : lzma_strm(DECODE, std::move(fp)) {} + explicit lzma_decoder(stream_ptr &&base) : lzma_strm(DECODE, std::move(base)) {} }; class xz_encoder : public lzma_strm { public: - explicit xz_encoder(sFILE &&fp) : lzma_strm(ENCODE_XZ, std::move(fp)) {} + explicit xz_encoder(stream_ptr &&base) : lzma_strm(ENCODE_XZ, std::move(base)) {} }; class lzma_encoder : public lzma_strm { public: - explicit lzma_encoder(sFILE &&fp) : lzma_strm(ENCODE_LZMA, std::move(fp)) {} + explicit lzma_encoder(stream_ptr &&base) : lzma_strm(ENCODE_LZMA, std::move(base)) {} }; class LZ4F_decoder : public cpr_stream { public: - explicit LZ4F_decoder(sFILE &&fp) : cpr_stream(std::move(fp)), outbuf(nullptr) { + explicit LZ4F_decoder(stream_ptr &&base) : cpr_stream(std::move(base)), outbuf(nullptr) { LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION); } @@ -317,8 +317,8 @@ private: class LZ4F_encoder : public cpr_stream { public: - explicit LZ4F_encoder(sFILE &&fp) - : cpr_stream(std::move(fp)), outbuf(nullptr), outCapacity(0) { + explicit LZ4F_encoder(stream_ptr &&base) + : cpr_stream(std::move(base)), outbuf(nullptr), outCapacity(0) { LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); } @@ -378,8 +378,8 @@ private: class LZ4_decoder : public cpr_stream { public: - explicit LZ4_decoder(sFILE &&fp) - : cpr_stream(std::move(fp)), out_buf(new char[LZ4_UNCOMPRESSED]), + explicit LZ4_decoder(stream_ptr &&base) + : cpr_stream(std::move(base)), out_buf(new char[LZ4_UNCOMPRESSED]), buffer(new char[LZ4_COMPRESSED]), init(false), block_sz(0), buf_off(0) {} ~LZ4_decoder() override { @@ -439,8 +439,8 @@ private: class LZ4_encoder : public cpr_stream { public: - explicit LZ4_encoder(sFILE &&fp) - : cpr_stream(std::move(fp)), outbuf(new char[LZ4_COMPRESSED]), buf(new char[LZ4_UNCOMPRESSED]), + explicit LZ4_encoder(stream_ptr &&base) + : cpr_stream(std::move(base)), outbuf(new char[LZ4_COMPRESSED]), buf(new char[LZ4_UNCOMPRESSED]), init(false), buf_off(0), in_total(0) {} int write(const void *in, size_t size) override { @@ -500,38 +500,38 @@ private: unsigned in_total; }; -stream_ptr get_encoder(format_t type, sFILE &&fp) { +stream_ptr get_encoder(format_t type, stream_ptr &&base) { switch (type) { case XZ: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); case LZMA: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); case BZIP2: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); case LZ4: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); case LZ4_LEGACY: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); case GZIP: default: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); } } -stream_ptr get_decoder(format_t type, sFILE &&fp) { +stream_ptr get_decoder(format_t type, stream_ptr &&base) { switch (type) { case XZ: case LZMA: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); case BZIP2: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); case LZ4: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); case LZ4_LEGACY: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); case GZIP: default: - return make_unique(std::move(fp)); + return make_unique(std::move(base)); } } @@ -573,7 +573,7 @@ void decompress(char *infile, const char *outfile) { } FILE *out_fp = outfile == "-"sv ? stdout : xfopen(outfile, "we"); - strm = get_decoder(type, make_sFILE(out_fp)); + strm = get_decoder(type, make_unique(out_fp)); if (ext) *ext = '.'; } if (strm->write(buf, len) < 0) @@ -614,7 +614,7 @@ void compress(const char *method, const char *infile, const char *outfile) { out_fp = outfile == "-"sv ? stdout : xfopen(outfile, "we"); } - auto strm = get_encoder(it->second, make_sFILE(out_fp)); + auto strm = get_encoder(it->second, make_unique(out_fp)); char buf[4096]; size_t len; diff --git a/native/jni/magiskboot/compress.h b/native/jni/magiskboot/compress.h index bb162455f..7a8ab9c23 100644 --- a/native/jni/magiskboot/compress.h +++ b/native/jni/magiskboot/compress.h @@ -4,9 +4,9 @@ #include "format.h" -stream_ptr get_encoder(format_t type, sFILE &&fp); +stream_ptr get_encoder(format_t type, stream_ptr &&base); -stream_ptr get_decoder(format_t type, sFILE &&fp); +stream_ptr get_decoder(format_t type, stream_ptr &&base); void compress(const char *method, const char *infile, const char *outfile); diff --git a/native/jni/magiskboot/ramdisk.cpp b/native/jni/magiskboot/ramdisk.cpp index 798292409..67a65e7da 100644 --- a/native/jni/magiskboot/ramdisk.cpp +++ b/native/jni/magiskboot/ramdisk.cpp @@ -244,7 +244,7 @@ void magisk_cpio::compress() { uint8_t *data; size_t len; - auto strm = make_stream(get_encoder(XZ, make_stream(data, len))); + auto strm = make_stream_fp(get_encoder(XZ, make_unique(data, len))); dump(strm.release()); entries.clear(); @@ -264,7 +264,7 @@ void magisk_cpio::decompress() { char *data; size_t len; { - auto strm = get_decoder(XZ, make_stream(data, len)); + auto strm = get_decoder(XZ, make_unique(data, len)); strm->write(it->second->data, it->second->filesize); } diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index c08a8eacc..b451fa386 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -183,7 +183,7 @@ bool init_list() { // Migrate old hide list into database if (access(LEGACY_LIST, R_OK) == 0) { - file_readline(LEGACY_LIST, [](string_view s) -> bool { + file_readline(true, LEGACY_LIST, [](string_view s) -> bool { add_list(s.data()); return true; }); diff --git a/native/jni/magiskpolicy/policydb.cpp b/native/jni/magiskpolicy/policydb.cpp index 2ffaacfad..6c775b1c2 100644 --- a/native/jni/magiskpolicy/policydb.cpp +++ b/native/jni/magiskpolicy/policydb.cpp @@ -178,7 +178,7 @@ int dump_policydb(const char *file) { size_t len; { - auto fp = make_stream(data, len); + auto fp = make_stream_fp(data, len); struct policy_file pf; policy_file_init(&pf); pf.type = PF_USE_STDIO; diff --git a/native/jni/magiskpolicy/statement.cpp b/native/jni/magiskpolicy/statement.cpp index bf97ae5e4..43f8b8bff 100644 --- a/native/jni/magiskpolicy/statement.cpp +++ b/native/jni/magiskpolicy/statement.cpp @@ -416,10 +416,10 @@ void parse_statement(const char *statement) { } void load_rule_file(const char *file) { - file_readline(file, [](string_view line) -> bool { + file_readline(true, file, [](string_view line) -> bool { if (line.empty() || line[0] == '#') return true; parse_statement(line.data()); return true; - }, true); + }); } diff --git a/native/jni/utils/file.cpp b/native/jni/utils/file.cpp index 42f8463b5..9af4365b3 100644 --- a/native/jni/utils/file.cpp +++ b/native/jni/utils/file.cpp @@ -1,8 +1,4 @@ -/* file.cpp - Contains all files related utilities - */ - #include -#include #include #include #include @@ -359,7 +355,7 @@ void write_zero(int fd, size_t size) { } } -void file_readline(const char *file, const function &fn, bool trim) { +void file_readline(bool trim, const char *file, const std::function &fn) { FILE *fp = xfopen(file, "re"); if (fp == nullptr) return; @@ -384,7 +380,7 @@ void file_readline(const char *file, const function &fn, boo } void parse_prop_file(const char *file, const function &fn) { - file_readline(file, [&](string_view line_view) -> bool { + file_readline(true, file, [&](string_view line_view) -> bool { char *line = (char *) line_view.data(); if (line[0] == '#') return true; @@ -393,7 +389,7 @@ void parse_prop_file(const char *file, const function &fn) { diff --git a/native/jni/utils/files.h b/native/jni/utils/files.h index 26880258b..a53f632c5 100644 --- a/native/jni/utils/files.h +++ b/native/jni/utils/files.h @@ -1,17 +1,16 @@ #pragma once +#include +#include #include #include #include +#include "xwrap.h" + #define do_align(p, a) (((p) + (a) - 1) / (a) * (a)) #define align_off(p, a) (do_align(p, a) - (p)) -using sFILE = std::unique_ptr; -static inline sFILE make_sFILE(FILE *fp = nullptr) { - return sFILE(fp, fclose); -} - struct file_attr { struct stat st; char con[128]; @@ -36,12 +35,15 @@ void clone_attr(const char *source, const char *target); void fd_full_read(int fd, void **buf, size_t *size); void full_read(const char *filename, void **buf, size_t *size); void write_zero(int fd, size_t size); - -void file_readline(const char *file, const std::function &fn, bool trim = false); -void parse_prop_file(const char *file, const std::function - &fn); +void file_readline(bool trim, const char *file, const std::function &fn); +static inline void file_readline(const char *file, + const std::function &fn) { + file_readline(false, file, fn); +} +void parse_prop_file(const char *file, + const std::function &fn); void *__mmap(const char *filename, size_t *size, bool rw); -void frm_rf(int dirfd, std::initializer_list excl = std::initializer_list()); +void frm_rf(int dirfd, std::initializer_list excl = {}); void clone_dir(int src, int dest, bool overwrite = true); void parse_mnt(const char *file, const std::function &fn); @@ -80,3 +82,22 @@ void mmap_rw(const char *filename, B &buf, L &sz) { buf = (B) __mmap(filename, &__sz, true); sz = __sz; } + +using sFILE = std::unique_ptr; +using sDIR = std::unique_ptr; + +static inline sDIR open_dir(const char *path) { + return sDIR(opendir(path), closedir); +} + +static inline sDIR xopen_dir(const char *path) { + return sDIR(xopendir(path), closedir); +} + +static inline sFILE open_file(const char *path, const char *mode) { + return sFILE(fopen(path, mode), fclose); +} + +static inline sFILE xopen_file(const char *path, const char *mode) { + return sFILE(xfopen(path, mode), fclose); +} diff --git a/native/jni/utils/include/stream.h b/native/jni/utils/include/stream.h index a07097fce..4e07dce25 100644 --- a/native/jni/utils/include/stream.h +++ b/native/jni/utils/include/stream.h @@ -5,17 +5,6 @@ #include "../files.h" -class stream; - -using stream_ptr = std::unique_ptr; - -sFILE make_stream(stream_ptr &&strm); - -template -sFILE make_stream(Args &&... args) { - return make_stream(stream_ptr(new T(std::forward(args)...))); -} - class stream { public: virtual int read(void *buf, size_t len); @@ -24,35 +13,22 @@ public: virtual ~stream() = default; }; -// Delegates all operations to the base FILE pointer +using stream_ptr = std::unique_ptr; + +// Delegates all operations to base stream class filter_stream : public stream { public: - filter_stream(sFILE &&fp = make_sFILE()) : fp(std::move(fp)) {} + 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; - void set_base(sFILE &&f); - template - void set_base(Args&&... args) { - set_base(make_stream(std::forward(args)...)); - } - protected: - sFILE fp; -}; - -// Handy interface for classes that need custom seek logic -class seekable_stream : public stream { -protected: - size_t _pos = 0; - - off_t seek_pos(off_t off, int whence); - virtual size_t end_pos() = 0; + stream_ptr base; }; // Byte stream that dynamically allocates memory -class byte_stream : public seekable_stream { +class byte_stream : public stream { public: byte_stream(uint8_t *&buf, size_t &len); template @@ -64,10 +40,10 @@ public: private: uint8_t *&_buf; size_t &_len; + size_t _pos = 0; size_t _cap = 0; void resize(size_t new_pos, bool zero = false); - size_t end_pos() final { return _len; } }; // File stream but does not close the file descriptor at any time @@ -81,3 +57,28 @@ public: private: int fd; }; + +/* **************************************** + * Bridge between stream class and C stdio + * ****************************************/ + +// 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; + +private: + sFILE fp; +}; + +// stream_ptr -> sFILE +sFILE make_stream_fp(stream_ptr &&strm); + +template +sFILE make_stream_fp(Args &&... args) { + return make_stream_fp(stream_ptr(new T(std::forward(args)...))); +} diff --git a/native/jni/utils/include/utils.h b/native/jni/utils/include/utils.h index 77638f7d7..e2c71fede 100644 --- a/native/jni/utils/include/utils.h +++ b/native/jni/utils/include/utils.h @@ -1,14 +1,5 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - #include "../missing.h" #include "../xwrap.h" #include "../files.h" diff --git a/native/jni/utils/misc.h b/native/jni/utils/misc.h index e5cd3721b..ac0d51f99 100644 --- a/native/jni/utils/misc.h +++ b/native/jni/utils/misc.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include diff --git a/native/jni/utils/selinux.cpp b/native/jni/utils/selinux.cpp index f41fd8106..616f1a954 100644 --- a/native/jni/utils/selinux.cpp +++ b/native/jni/utils/selinux.cpp @@ -207,11 +207,10 @@ void restore_rootcon() { setfilecon(MIRRDIR, ROOT_CON); setfilecon(BLOCKDIR, ROOT_CON); - struct dirent *entry; - DIR *dir = xopendir("/sbin"); - int dfd = dirfd(dir); + auto dir = xopen_dir("/sbin"); + int dfd = dirfd(dir.get()); - while ((entry = xreaddir(dir))) { + for (dirent *entry; (entry = xreaddir(dir.get()));) { if (entry->d_name == "."sv || entry->d_name == ".."sv) continue; setfilecon_at(dfd, entry->d_name, ROOT_CON); @@ -220,6 +219,4 @@ void restore_rootcon() { setfilecon("/sbin/magisk.bin", MAGISK_CON); setfilecon("/sbin/magisk", MAGISK_CON); setfilecon("/sbin/magiskinit", MAGISK_CON); - - closedir(dir); } diff --git a/native/jni/utils/stream.cpp b/native/jni/utils/stream.cpp index a0b687578..ee80cb0a5 100644 --- a/native/jni/utils/stream.cpp +++ b/native/jni/utils/stream.cpp @@ -23,7 +23,7 @@ static int strm_close(void *v) { return 0; } -sFILE make_stream(stream_ptr &&strm) { +sFILE make_stream_fp(stream_ptr &&strm) { sFILE fp(funopen(strm.release(), strm_read, strm_write, strm_seek, strm_close), fclose); setbuf(fp.get(), nullptr); return fp; @@ -44,29 +44,24 @@ off_t stream::seek(off_t off, int whence) { return -1; } -int filter_stream::read(void *buf, size_t len) { +int fp_stream::read(void *buf, size_t len) { return fread(buf, 1, len, fp.get()); } -int filter_stream::write(const void *buf, size_t len) { +int fp_stream::write(const void *buf, size_t len) { return fwrite(buf, 1, len, fp.get()); } -void filter_stream::set_base(sFILE &&f) { - fp = std::move(f); +off_t fp_stream::seek(off_t off, int whence) { + return fseek(fp.get(), off, whence); } -off_t seekable_stream::seek_pos(off_t off, int whence) { - switch (whence) { - case SEEK_CUR: - return _pos + off; - case SEEK_END: - return end_pos() + off; - case SEEK_SET: - return off; - default: - return -1; - } +int filter_stream::read(void *buf, size_t len) { + return base->read(buf, len); +} + +int filter_stream::write(const void *buf, size_t len) { + return base->write(buf, len); } byte_stream::byte_stream(uint8_t *&buf, size_t &len) : _buf(buf), _len(len) { @@ -89,9 +84,20 @@ int byte_stream::write(const void *buf, size_t len) { } off_t byte_stream::seek(off_t off, int whence) { - off_t np = seek_pos(off, whence); - if (np < 0) - return -1; + 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; diff --git a/native/jni/utils/xwrap.cpp b/native/jni/utils/xwrap.cpp index 122cef6a9..29a6db369 100644 --- a/native/jni/utils/xwrap.cpp +++ b/native/jni/utils/xwrap.cpp @@ -1,17 +1,6 @@ -/* xwrap.cpp - wrappers around existing library functions. - * - * Functions with the x prefix are wrappers that either succeed or log the - * error message. They usually have the same arguments and return value - * as the function they wrap. - * - */ - #include -#include #include #include -#include -#include #include #include #include diff --git a/native/jni/utils/xwrap.h b/native/jni/utils/xwrap.h index 106e15b87..ffa4f6536 100644 --- a/native/jni/utils/xwrap.h +++ b/native/jni/utils/xwrap.h @@ -1,5 +1,10 @@ #pragma once +#include +#include +#include +#include + FILE *xfopen(const char *pathname, const char *mode); FILE *xfdopen(int fd, const char *mode); int xopen(const char *pathname, int flags);