├── src ├── libc-compat │ ├── placeholder.c │ ├── rs │ │ ├── .gitignore │ │ ├── emscripten │ │ │ ├── mod.rs │ │ │ ├── missing_defs.rs │ │ │ └── defs.rs │ │ ├── common │ │ │ ├── mod.rs │ │ │ ├── overrides.rs │ │ │ └── stubs │ │ │ │ ├── fcntl.rs │ │ │ │ ├── sc_num.rs │ │ │ │ ├── errno.rs │ │ │ │ ├── lfs64.rs │ │ │ │ ├── mod.rs │ │ │ │ └── sendfile.rs │ │ ├── windows │ │ │ ├── mod.rs │ │ │ ├── missing_defs.rs │ │ │ ├── defs.rs │ │ │ └── stubs.rs │ │ ├── Cargo.toml │ │ ├── lib.rs │ │ └── macros.rs │ ├── winsup │ │ ├── crt_flags.c │ │ ├── internal │ │ │ ├── errno.h │ │ │ ├── assert.h │ │ │ ├── errno.c │ │ │ ├── assert.c │ │ │ ├── fd.h │ │ │ └── fd.c │ │ ├── mknod_stub.c │ │ ├── mkdir.c │ │ ├── io.c │ │ ├── str.c │ │ ├── acl.c │ │ ├── uio.c │ │ ├── file.c │ │ ├── open.c │ │ ├── link.c │ │ ├── stat.c │ │ └── dirent.c │ ├── common │ │ └── __errno.c │ ├── include │ │ ├── libbsd │ │ │ └── str_compat.h │ │ ├── winsup │ │ │ ├── mkdir_compat.h │ │ │ ├── str_compat.h │ │ │ ├── io_compat.h │ │ │ ├── uio_compat.h │ │ │ ├── stat_compat.h │ │ │ ├── acl_compat.h │ │ │ ├── link_compat.h │ │ │ ├── mknod_compat.h │ │ │ ├── at_compat.h │ │ │ └── dirent_compat.h │ │ └── emsup │ │ │ └── mkdev_stubs.h │ ├── non-linux │ │ └── sendfile_fallback.c │ ├── libbsd │ │ └── str.c │ └── emsup │ │ └── mmap_hack.c ├── winsup-rs │ ├── lib.rs │ ├── .gitignore │ ├── Cargo.toml │ └── fd.rs ├── magiskbase-rs-wrapper.cc └── magiskboot-rs-wrapper.cc ├── .gitignore ├── .github ├── __debug_release_template.md ├── ISSUE_TEMPLATE │ ├── question-or-suggestion.md │ └── bug_report.md ├── __release_template.md └── workflows │ └── release.yaml ├── .gitattributes ├── include-android ├── fortify_stub.h └── libbsd_stub.h ├── include └── flags.h.in ├── scripts ├── clone_submodules.sh └── magiskboot_test.sh ├── patches ├── android_libbase │ ├── 0008-fix-header-include-for-non-Linux.patch │ ├── 0009-file-stub-GetExecutablePath-for-non-Linux.patch │ ├── 0001-android-base-endian.h-fix-build-on-musl.patch │ ├── 0002-remove-glibc-internal-headers-cdefs.h.patch │ ├── 0004-Don-t-use-thread-safety-annotations-with-gcc.patch │ ├── 0003-logging.h-only-activate-ostream-warnings-when-clang-.patch │ ├── 0005-fix-unique_fd.h-for-Termux.patch │ ├── 0007-fix-properties-for-Termux.patch │ └── 0006-remove-usage-of-__builtin_available.patch ├── android_logging │ ├── 0002-Fix-inclusion-of-stdatomic.h-with-g.patch │ ├── 0005-disable-logd-and-pmsg-on-Android.patch │ ├── 0007-liblog-logger-don-t-use-std-namespace-on-Windows.patch │ ├── 0006-Cygwin-has-getprogname.patch │ ├── 0004-fix-initializer-element-is-not-constant-error-when-b.patch │ ├── 0003-fix-__INTRODUCED_IN-attributes-for-Termux.patch │ └── 0001-Don-t-use-the-internal-glibc-header-sys-cdefs.h.patch ├── msvc_getline │ ├── 0002-support-cpp.patch │ └── 0001-adapt-to-MinGW.patch ├── Magisk │ ├── 0010-workaround-UTF-8-issues-on-Windows.patch │ ├── 0009-drop-rust-funcs-unused-by-magiskboot.patch │ ├── 0004-disable-funcs-not-used-by-magiskboot.patch │ ├── 0007-HACK-support-cfg-attribute-in-build-script.patch │ ├── 0002-fix-builds-for-some-OS.patch │ ├── 0003-base-files-disable-BLKGETSIZE-for-non-Linux.patch │ ├── 0005-base-rust-add-fd_path-impl-for-other-OS.patch │ ├── 0006-disable-libc-funcs-not-used-by-magiskboot.patch │ └── 0001-native-fix-header-includes.patch ├── corrosion │ ├── 0002-suppress-rustup-target-not-installed-error.patch │ ├── 0001-support-pc-windows-gnullvm-targets.patch │ └── 0003-allow-adding-required-cargo-rust-flags-when-detectin.patch ├── android_core │ ├── 0001-Fix-inclusion-of-stdatomic.h-with-g.patch │ ├── 0010-Correct-version-in-which-gettid-was-introduced-to-gl.patch │ └── 0008-Vector-don-t-assign-to-const-object.patch └── mman-win32 │ ├── 0001-set-winerr-via-winsup.patch │ └── 0002-implement-MAP_PRIVATE-using-copy-on-write-protection.patch ├── Makefile ├── .gitmodules ├── CMakeLists.rust.txt ├── CMakeLists.android.txt ├── patches-contrib └── Magisk │ └── 0029-workaround-support-building-with-libstdcxx.patch ├── CMakeLists.patch.txt ├── CMakeLists.magiskboot.txt ├── CMakeLists.magisk.txt ├── CMakeLists.compat.txt ├── CMakeLists.stub.txt └── CMakeLists.txt /src/libc-compat/placeholder.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/winsup-rs/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod fd; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /include/flags.h 3 | 4 | -------------------------------------------------------------------------------- /src/winsup-rs/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target/ 3 | -------------------------------------------------------------------------------- /src/libc-compat/rs/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target/ 3 | -------------------------------------------------------------------------------- /src/magiskbase-rs-wrapper.cc: -------------------------------------------------------------------------------- 1 | // dynamtically generated during build 2 | #include "Magisk/native/src/base/base-rs.cpp" 3 | -------------------------------------------------------------------------------- /src/magiskboot-rs-wrapper.cc: -------------------------------------------------------------------------------- 1 | // dynamtically generated during build 2 | #include "Magisk/native/src/boot/boot-rs.cpp" 3 | -------------------------------------------------------------------------------- /src/libc-compat/rs/emscripten/mod.rs: -------------------------------------------------------------------------------- 1 | mod defs; 2 | mod missing_defs; 3 | 4 | pub use defs::*; 5 | pub use missing_defs::*; 6 | -------------------------------------------------------------------------------- /src/libc-compat/rs/common/mod.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | mod stubs; 3 | 4 | pub use stubs::*; 5 | 6 | #[macro_use] 7 | mod overrides; 8 | -------------------------------------------------------------------------------- /src/libc-compat/rs/common/overrides.rs: -------------------------------------------------------------------------------- 1 | macro_rules! post_defs_overrides { 2 | () => { 3 | add_sendfile_stubs_if_needed!(); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/libc-compat/rs/windows/mod.rs: -------------------------------------------------------------------------------- 1 | mod defs; 2 | mod missing_defs; 3 | mod stubs; 4 | 5 | pub use defs::*; 6 | pub use missing_defs::*; 7 | pub use stubs::*; 8 | -------------------------------------------------------------------------------- /src/libc-compat/rs/common/stubs/fcntl.rs: -------------------------------------------------------------------------------- 1 | // for platform those doesn't have O_PATH 2 | 3 | #[cfg(mbb_stubs_O_PATH)] 4 | pub const O_PATH: crate::c_int = 0; // no-op 5 | -------------------------------------------------------------------------------- /src/libc-compat/rs/common/stubs/sc_num.rs: -------------------------------------------------------------------------------- 1 | // no actually used, just for passing build 2 | 3 | #[cfg(mbb_stubs_SYS_dup3)] 4 | pub const SYS_dup3: crate::c_int = 0; // stub 5 | -------------------------------------------------------------------------------- /.github/__debug_release_template.md: -------------------------------------------------------------------------------- 1 | > [!Note] 2 | > 3 | > Debug builds are not frequently updated or guaranteed to be kept in sync with normal Release builds (for saving CI time) 4 | -------------------------------------------------------------------------------- /src/libc-compat/rs/common/stubs/errno.rs: -------------------------------------------------------------------------------- 1 | // android (bionic libc) errno 2 | 3 | #[cfg(mbb_stubs___errno)] 4 | extern "C" { 5 | pub fn __errno() -> *mut crate::c_int; 6 | } 7 | -------------------------------------------------------------------------------- /src/libc-compat/rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "libc" 3 | version = "0.0.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | path = "lib.rs" 8 | 9 | [dependencies] 10 | libc = "*" 11 | cfg-if = "*" 12 | -------------------------------------------------------------------------------- /src/winsup-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "winsup" 3 | version = "0.0.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | path = "lib.rs" 8 | 9 | [dependencies] 10 | libc = { path = "../libc-compat/rs" } 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | src/winsup/internal/winerr_map.h linguist-generated=true 2 | libc-compat/winsup/internal/winerr_map.h linguist-generated=true 3 | src/libc-compat/winsup/internal/winerr_map.h linguist-generated=true 4 | -------------------------------------------------------------------------------- /src/libc-compat/rs/windows/missing_defs.rs: -------------------------------------------------------------------------------- 1 | // stat 2 | 3 | pub type mode_t = crate::c_ushort; 4 | pub type gid_t = crate::c_short; 5 | pub type uid_t = crate::c_short; 6 | 7 | // stdlib 8 | 9 | pub const F_OK: crate::c_int = 0; 10 | -------------------------------------------------------------------------------- /src/libc-compat/rs/common/stubs/lfs64.rs: -------------------------------------------------------------------------------- 1 | // just aliases 2 | 3 | #[cfg(mbb_stubs_lseek64)] 4 | extern "C" { 5 | #[link_name = "lseek"] 6 | pub fn lseek64(fd: crate::c_int, offset: crate::off_t, whence: crate::c_int) -> crate::off_t; 7 | } 8 | -------------------------------------------------------------------------------- /src/libc-compat/rs/common/stubs/mod.rs: -------------------------------------------------------------------------------- 1 | mod errno; 2 | pub use errno::*; 3 | 4 | mod fcntl; 5 | pub use fcntl::*; 6 | 7 | mod lfs64; 8 | pub use lfs64::*; 9 | 10 | mod sc_num; 11 | pub use sc_num::*; 12 | 13 | #[macro_use] 14 | mod sendfile; 15 | -------------------------------------------------------------------------------- /include-android/fortify_stub.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_FORTIFY_STUB 2 | #define _MAGISKBOOT_BUILD_FORTIFY_STUB 3 | 4 | #ifndef __call_bypassing_fortify 5 | # define __call_bypassing_fortify(x) x 6 | #endif 7 | 8 | #endif /* _MAGISKBOOT_BUILD_FORTIFY_STUB */ 9 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/crt_flags.c: -------------------------------------------------------------------------------- 1 | // wildcard matching for file paths in argument could be enabled by 2 | // default if the MinGW runtime is configured with `--enable-wildcard` 3 | // but we explicitly dont want this behavior on Windows 4 | int _dowildcard = 0; 5 | -------------------------------------------------------------------------------- /include-android/libbsd_stub.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_LIBBSD_STUB 2 | #define _MAGISKBOOT_BUILD_LIBBSD_STUB 3 | 4 | #ifndef __printflike 5 | # define __printflike(fmt, var) __attribute__((format(printf,fmt,var))) 6 | #endif 7 | 8 | #endif /* _MAGISKBOOT_BUILD_LIBBSD_STUB */ 9 | -------------------------------------------------------------------------------- /src/libc-compat/common/__errno.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int *__errno (void) { 4 | #ifdef HAVE___errno_location 5 | return __errno_location(); 6 | #elif defined(HAVE___error) 7 | return __error(); 8 | #elif defined(HAVE__errno) 9 | return _errno(); 10 | #else 11 | # error "Unreachable" 12 | #endif 13 | } 14 | -------------------------------------------------------------------------------- /include/flags.h.in: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define quote(s) #s 3 | #define str(s) quote(s) 4 | #define MAGISK_FULL_VER MAGISK_VERSION "(" str(MAGISK_VER_CODE) ")" 5 | #define NAME_WITH_VER(name) str(name) " " MAGISK_FULL_VER 6 | #define MAGISK_VERSION "@MAGISK_VERSION@" 7 | #define MAGISK_VER_CODE @MAGISK_VER_CODE@ 8 | #define MAGISK_DEBUG !MAGISK_DEBUG! 9 | -------------------------------------------------------------------------------- /scripts/clone_submodules.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # fail fast 4 | set -e 5 | 6 | set -x 7 | git submodule update --init --depth=1 --single-branch -j $(nproc) "$@" \ 8 | src/{Magisk,android_{core,fmtlib,libbase,logging},corrosion,mman-win32,msvc_getline}/ 9 | git -C src/Magisk submodule update --init --depth=1 --single-branch -j $(nproc) "$@" native/src/external/{cxx-rs,zopfli}/ 10 | set +x 11 | -------------------------------------------------------------------------------- /src/libc-compat/include/libbsd/str_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_LIBBSD_STR_COMPAT 2 | #define _MAGISKBOOT_BUILD_LIBBSD_STR_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | size_t strlcpy(char *dst, const char *src, size_t siz); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif /* _MAGISKBOOT_BUILD_LIBBSD_STR_COMPAT */ 17 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/mkdir_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_MKDIR_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_MKDIR_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | int _mkdir_stub (const char *path, mode_t mode); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif /* _MAGISKBOOT_BUILD_WINSUP_MKDIR_COMPAT */ 17 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/str_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_STR_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_STR_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | void *memmem(const void *haystack, int haystacklen, const void *needle, int needlelen); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif /* _MAGISKBOOT_BUILD_WINSUP_STR_COMPAT */ 17 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/internal/errno.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_INTERNAL_ERRNO 2 | #define _MAGISKBOOT_BUILD_WINSUP_INTERNAL_ERRNO 3 | 4 | #ifndef WIN32_LEAN_AND_MEAN 5 | # define WIN32_LEAN_AND_MEAN 6 | #endif 7 | #include 8 | 9 | void __set_errno_via_winerr(DWORD winerr); 10 | 11 | #ifdef WIN32_LEAN_AND_MEAN 12 | # undef WIN32_LEAN_AND_MEAN 13 | #endif 14 | 15 | #endif /* _MAGISKBOOT_BUILD_WINSUP_INTERNAL_ERRNO */ 16 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/io_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_IO_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_IO_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | ssize_t _read_stub(int fd, void *buf, size_t count); 12 | 13 | ssize_t _write_stub(int fd, const void *buf, size_t count); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* _MAGISKBOOT_BUILD_WINSUP_IO_COMPAT */ 20 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/internal/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_INTERNAL_ASSERT 2 | #define _MAGISKBOOT_BUILD_WINSUP_INTERNAL_ASSERT 3 | 4 | #include 5 | 6 | #ifndef WIN32_LEAN_AND_MEAN 7 | # define WIN32_LEAN_AND_MEAN 8 | #endif 9 | #include 10 | 11 | #define LOG_ERR(_fmt, ...) \ 12 | fprintf(stderr, "winsup " LOG_TAG ": " _fmt "\n", ##__VA_ARGS__) 13 | 14 | const char* win_strerror(DWORD); 15 | 16 | #ifdef WIN32_LEAN_AND_MEAN 17 | # undef WIN32_LEAN_AND_MEAN 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/libc-compat/rs/emscripten/missing_defs.rs: -------------------------------------------------------------------------------- 1 | // at 2 | 3 | extern "C" { 4 | pub fn faccessat( 5 | dirfd: crate::c_int, 6 | pathname: *const crate::c_char, 7 | mode: crate::c_int, 8 | flags: crate::c_int, 9 | ) -> crate::c_int; 10 | } 11 | 12 | // string 13 | 14 | extern "C" { 15 | pub fn memmem( 16 | haystack: *const crate::c_void, 17 | haystacklen: crate::size_t, 18 | needle: *const crate::c_void, 19 | needlelen: crate::size_t, 20 | ) -> *mut crate::c_void; 21 | } 22 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/mknod_stub.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../include/winsup/mknod_compat.h" 6 | 7 | int mknod (const char *path, mode_t mode, dev_t dev ) { 8 | if (access(path, R_OK) == 0) { 9 | errno = EEXIST; 10 | 11 | return -1; 12 | } 13 | 14 | // no easy way to implement mknod properly on Win32 15 | // since we don't have device files in normal filesystem 16 | errno = ENOTSUP; // maybe set a listed errno in man page? 17 | return -1; 18 | } 19 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/uio_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_UIO_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_UIO_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | struct iovec { 12 | void *iov_base; 13 | size_t iov_len; 14 | }; 15 | 16 | ssize_t readv(int fd, const struct iovec *iov, int iov_cnt); 17 | ssize_t writev(int fd, const struct iovec *iov, int iov_cnt); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif /* _MAGISKBOOT_BUILD_WINSUP_UIO_COMPAT */ 24 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/mkdir.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../include/winsup/mkdir_compat.h" 9 | 10 | int _mkdir_stub (const char *path, mode_t mode) { 11 | if (mkdir(path) < 0) 12 | return -1; 13 | 14 | if (chmod(path, mode) < 0) { 15 | int old_errno = errno; 16 | assert(!rmdir(path)); // mkdir() just succeed, how come 17 | errno = old_errno; 18 | return -1; 19 | } 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/stat_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_STAT_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_STAT_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | #define S_IFLNK 0x6000 11 | #define S_IFSOCK 0xC000 12 | 13 | #define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) 14 | #define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) 15 | 16 | int lstat (const char *__restrict path, struct stat *__restrict buf); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif /* _MAGISKBOOT_BUILD_WINSUP_STAT_COMPAT */ 23 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/acl_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_ACL_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_ACL_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | typedef short uid_t, gid_t; 11 | 12 | int chown (const char *path, uid_t owner, gid_t group); 13 | int fchmod (int fd, mode_t mode); 14 | int fchown (int fildes, uid_t owner, gid_t group); 15 | int lchown (const char *path, uid_t owner, gid_t group); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif /* _MAGISKBOOT_BUILD_WINSUP_ACL_COMPAT */ 22 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/link_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_LINK_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_LINK_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | ssize_t readlink (const char *__restrict path, 12 | char *__restrict buf, size_t len); 13 | 14 | int link(const char *path1, const char *path2); 15 | 16 | int symlink (const char *name1, const char *name2); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif /* _MAGISKBOOT_BUILD_WINSUP_LINK_COMPAT */ 23 | -------------------------------------------------------------------------------- /src/libc-compat/rs/emscripten/defs.rs: -------------------------------------------------------------------------------- 1 | pub use libc::*; 2 | 3 | // shadowing these functions to use our stubs 4 | // check src/libc-compat/emsup/mmap_hack.c for details 5 | 6 | extern "C" { 7 | #[link_name = "_mmap_stub_impl"] 8 | pub fn mmap( 9 | addr: *mut c_void, 10 | len: size_t, 11 | prot: c_int, 12 | flags: c_int, 13 | fd: c_int, 14 | offset: off_t, 15 | ) -> *mut c_void; 16 | 17 | #[link_name = "_munmap_stub_impl"] 18 | pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; 19 | 20 | // close() is shadowed using a --wrap ldflag 21 | } 22 | -------------------------------------------------------------------------------- /patches/android_libbase/0008-fix-header-include-for-non-Linux.patch: -------------------------------------------------------------------------------- 1 | From 4dd2d39f64e754b43b068905bba29f17b3077b03 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Sat, 29 Jul 2023 16:13:35 +0800 4 | Subject: [PATCH] fix header include non-Linux 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | cmsg.cpp | 2 ++ 9 | 1 file changed, 2 insertions(+) 10 | 11 | diff --git a/cmsg.cpp b/cmsg.cpp 12 | index 95db303..aa36686 100644 13 | --- a/cmsg.cpp 14 | +++ b/cmsg.cpp 15 | @@ -20,7 +20,9 @@ 16 | #include 17 | #include 18 | #include 19 | +#if 0 20 | #include 21 | +#endif 22 | 23 | #include 24 | 25 | -- 26 | 2.41.0 27 | 28 | -------------------------------------------------------------------------------- /patches/android_libbase/0009-file-stub-GetExecutablePath-for-non-Linux.patch: -------------------------------------------------------------------------------- 1 | From 48bd561bc79bae4df24297968a4e841f036e3359 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Tue, 9 Jan 2024 23:21:57 +0800 4 | Subject: [PATCH] file: stub GetExecutablePath for non-Linux 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | file.cpp | 2 ++ 9 | 1 file changed, 2 insertions(+) 10 | 11 | diff --git a/file.cpp b/file.cpp 12 | index bc831e3..a0c694d 100644 13 | --- a/file.cpp 14 | +++ b/file.cpp 15 | @@ -489,7 +489,7 @@ std::string GetExecutablePath() { 16 | path[PATH_MAX - 1] = 0; 17 | return path; 18 | #else 19 | -#error unknown OS 20 | + abort(); 21 | #endif 22 | } 23 | 24 | -- 25 | 2.43.0 26 | 27 | -------------------------------------------------------------------------------- /src/libc-compat/rs/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow( 2 | non_camel_case_types, unused_macros, unused_imports, non_upper_case_globals 3 | )] 4 | 5 | #[macro_use] 6 | mod macros; 7 | 8 | cfg_if::cfg_if! { 9 | if #[cfg(target_os = "windows")] { 10 | // windows has some missing defs, 11 | // we also need to shadow add some extra stuffs 12 | 13 | mod windows; 14 | pub use windows::*; 15 | } else if #[cfg(target_os = "emscripten")] { 16 | // emscripten has some missing defs 17 | // and we want to shadow some mman funcs 18 | 19 | mod emscripten; 20 | pub use emscripten::*; 21 | } else { 22 | pub use libc::*; 23 | } 24 | } 25 | 26 | #[macro_use] 27 | mod common; 28 | 29 | post_defs_overrides!(); 30 | 31 | pub use common::*; 32 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/internal/errno.c: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | 4 | #include "winerr_map.h" 5 | 6 | #include "errno.h" 7 | 8 | #ifndef NDEBUG 9 | # include "assert.h" 10 | 11 | # define LOG_TAG "errno_internal" 12 | #endif 13 | 14 | void __set_errno_via_winerr(DWORD winerr) { 15 | if (winerr == NO_ERROR) 16 | errno = 0; 17 | else if (winerr < __winerr_map_size) { 18 | int mapped_err = __winerr_map[winerr]; 19 | 20 | if (!mapped_err) 21 | goto unk_err; 22 | 23 | errno = mapped_err; 24 | } else { 25 | unk_err: 26 | #ifndef NDEBUG 27 | LOG_ERR("Unmapped winerr: %s (%ld)", win_strerror(winerr), winerr); 28 | #endif 29 | 30 | errno = -1; 31 | } 32 | 33 | return; 34 | } 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question-or-suggestion.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question or suggestion 3 | about: Any thought on improving this project? Or just some questions. 4 | title: '' 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | 10 | 22 | -------------------------------------------------------------------------------- /patches/android_logging/0002-Fix-inclusion-of-stdatomic.h-with-g.patch: -------------------------------------------------------------------------------- 1 | From e878c6856f9b828a9538b7bc962c7697039e58d5 Mon Sep 17 00:00:00 2001 2 | From: John Zimmermann 3 | Date: Thu, 18 Mar 2021 15:14:03 +0100 4 | Subject: [PATCH] Fix inclusion of stdatomic.h with g++ 5 | 6 | See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932#c5 7 | --- 8 | liblog/logger.h | 5 +++++ 9 | 1 file changed, 5 insertions(+) 10 | 11 | diff --git a/liblog/logger.h b/liblog/logger.h 12 | index 263859db..46361731 100644 13 | --- a/liblog/logger.h 14 | +++ b/liblog/logger.h 15 | @@ -16,7 +16,12 @@ 16 | 17 | #pragma once 18 | 19 | +#ifdef __cplusplus 20 | +#include 21 | +using namespace std; 22 | +#else 23 | #include 24 | +#endif 25 | 26 | #include 27 | 28 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/io.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // for _fmode 4 | #include 5 | #include 6 | 7 | #include "../include/winsup/io_compat.h" 8 | 9 | ssize_t _read_stub(int fd, void *buf, size_t count) { 10 | return read(fd, buf, count); 11 | } 12 | 13 | ssize_t _write_stub(int fd, const void *buf, size_t count) { 14 | return write(fd, buf, count); 15 | } 16 | 17 | // From libnt: 18 | // https://github.com/svoboda18/libnt/blob/f3027ff6261a1bfdbcec32de09ac6987aca80f22/libnt.c#L308-L324 19 | __attribute__((constructor)) static void __init_io_mode(void) { 20 | _fmode = O_BINARY; 21 | _setmode(_fileno(stdin), O_BINARY); 22 | _setmode(_fileno(stdout), O_BINARY); 23 | _setmode(_fileno(stderr), O_BINARY); 24 | } 25 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/internal/assert.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #include 5 | 6 | #include "assert.h" 7 | 8 | #ifndef NDEBUG 9 | # define LOG_TAG "assert_internal" 10 | #endif 11 | 12 | static char __win_strerror_buf[64 * 1024 - 1]; 13 | 14 | const char *win_strerror(DWORD winerr) { 15 | if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 16 | winerr, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 17 | __win_strerror_buf, sizeof(__win_strerror_buf), NULL)) { 18 | #ifndef NDEBUG 19 | LOG_ERR("FormatMessage for WinError %ld failed (WinError %ld)", winerr, GetLastError()); 20 | #endif 21 | return "Unknown error (win_strerror failed)"; 22 | } 23 | 24 | return __win_strerror_buf; 25 | } 26 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/internal/fd.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_INTERNAL_FD 2 | #define _MAGISKBOOT_BUILD_WINSUP_INTERNAL_FD 3 | 4 | #include 5 | #ifndef WIN32_LEAN_AND_MEAN 6 | # define WIN32_LEAN_AND_MEAN 7 | #endif 8 | #include 9 | 10 | char *__fd_get_path(int fd); 11 | 12 | char *__get_path_at(int dirfd, const char *name); 13 | 14 | int __open_dir_fd(const char *path, DWORD access, DWORD share_mode, int flags); 15 | 16 | bool __is_dirfd(int fd); 17 | 18 | int __open_symlink_fd(const char *path, DWORD access, DWORD share_mode, int flags); 19 | 20 | int __get_osfhandle_oflag(HANDLE h); 21 | 22 | void __fd_cache_oflag(int fd, int oflag); 23 | 24 | #ifdef WIN32_LEAN_AND_MEAN 25 | # undef WIN32_LEAN_AND_MEAN 26 | #endif 27 | 28 | #endif /* _MAGISKBOOT_BUILD_WINSUP_INTERNAL_FD */ 29 | -------------------------------------------------------------------------------- /src/libc-compat/include/emsup/mkdev_stubs.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_EMSUP_MKDEV_STUBS 2 | #define _MAGISKBOOT_BUILD_EMSUP_MKDEV_STUBS 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | #define major(dev) __gnu_dev_major(dev) 11 | #define minor(dev) __gnu_dev_minor(dev) 12 | #define makedev(maj, min) __gnu_dev_makedev(maj, min) 13 | 14 | static inline dev_t 15 | __gnu_dev_makedev(int maj, int min) 16 | { 17 | return (((maj) << 16) | ((min) & 0xffff)); 18 | } 19 | 20 | static inline int 21 | __gnu_dev_major(dev_t dev) 22 | { 23 | return (int)(((dev) >> 16) & 0xffff); 24 | } 25 | 26 | static inline int 27 | __gnu_dev_minor(dev_t dev) 28 | { 29 | return (int)((dev) & 0xffff); 30 | } 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif /* _MAGISKBOOT_BUILD_EMSUP_MKDEV_STUBS */ 37 | -------------------------------------------------------------------------------- /patches/android_libbase/0001-android-base-endian.h-fix-build-on-musl.patch: -------------------------------------------------------------------------------- 1 | From c57c764c290e09eac3b177848a87bf6356f76d18 Mon Sep 17 00:00:00 2001 2 | From: jershell 3 | Date: Tue, 7 Jun 2022 00:29:25 +0300 4 | Subject: [PATCH] android-base/endian.h: fix build on musl 5 | 6 | --- 7 | include/android-base/endian.h | 2 +- 8 | 1 file changed, 1 insertion(+), 1 deletion(-) 9 | 10 | diff --git a/include/android-base/endian.h b/include/android-base/endian.h 11 | index b47494b..ddfe36f 100644 12 | --- a/include/android-base/endian.h 13 | +++ b/include/android-base/endian.h 14 | @@ -25,7 +25,7 @@ 15 | 16 | #include 17 | 18 | -#elif defined(__GLIBC__) || defined(ANDROID_HOST_MUSL) 19 | +#elif defined(__GLIBC__) || defined(ANDROID_HOST_MUSL) || defined(__linux__) 20 | 21 | /* glibc and musl's are like bionic's . */ 22 | #include 23 | -------------------------------------------------------------------------------- /patches/android_logging/0005-disable-logd-and-pmsg-on-Android.patch: -------------------------------------------------------------------------------- 1 | From 0d126f64100e275c737e4da3d5d6c15b61740ee8 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?=3D=3FUTF-8=3Fq=3F=3DE9=3D9F=3DA9=3DE6=3D9C=3DB4=3DE5=3DAE?= 3 | =?UTF-8?q?=3D87=3F=3D?= 4 | Date: Thu, 8 Apr 2021 00:51:30 +0800 5 | Subject: [PATCH] disable logd and pmsg on Android 6 | 7 | Signed-off-by: Ookiineko 8 | --- 9 | liblog/logger_write.cpp | 2 ++ 10 | 1 file changed, 2 insertions(+) 11 | 12 | diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp 13 | index 596b1af..7057a60 100644 14 | --- a/liblog/logger_write.cpp 15 | +++ b/liblog/logger_write.cpp 16 | @@ -39,6 +39,8 @@ 17 | #include "logger.h" 18 | #include "uio.h" 19 | 20 | +#undef __ANDROID__ 21 | + 22 | #ifdef __ANDROID__ 23 | #include "logd_writer.h" 24 | #include "pmsg_writer.h" 25 | -- 26 | 2.39.2 27 | 28 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/mknod_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_MKNOD_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_MKNOD_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | #define major(dev) __gnu_dev_major(dev) 11 | #define minor(dev) __gnu_dev_minor(dev) 12 | #define makedev(maj, min) __gnu_dev_makedev(maj, min) 13 | 14 | static inline dev_t 15 | __gnu_dev_makedev(int maj, int min) 16 | { 17 | return (((maj) << 16) | ((min) & 0xffff)); 18 | } 19 | 20 | static inline int 21 | __gnu_dev_major(dev_t dev) 22 | { 23 | return (int)(((dev) >> 16) & 0xffff); 24 | } 25 | 26 | static inline int 27 | __gnu_dev_minor(dev_t dev) 28 | { 29 | return (int)((dev) & 0xffff); 30 | } 31 | 32 | int mknod (const char *path, mode_t mode, dev_t dev ); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* _MAGISKBOOT_BUILD_WINSUP_MKNOD_COMPAT */ 39 | 40 | -------------------------------------------------------------------------------- /patches/msvc_getline/0002-support-cpp.patch: -------------------------------------------------------------------------------- 1 | From 1361cc5d12a62c3caad765bd13a5de22233fe244 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Tue, 1 Aug 2023 18:10:39 +0800 4 | Subject: [PATCH] support c++ 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | getline.h | 8 ++++++++ 9 | 1 file changed, 8 insertions(+) 10 | 11 | diff --git a/getline.h b/getline.h 12 | index b7bab62..3a33017 100644 13 | --- a/getline.h 14 | +++ b/getline.h 15 | @@ -1,6 +1,10 @@ 16 | #ifndef GETLINE_H 17 | #define GETLINE_H 18 | 19 | +#ifdef __cplusplus 20 | +extern "C" { 21 | +#endif 22 | + 23 | #include 24 | 25 | #define restrict __restrict 26 | @@ -135,4 +139,8 @@ COLOPHON 27 | GNU 2019-03-06 GETLINE(3) 28 | */ 29 | 30 | +#ifdef __cplusplus 31 | +} 32 | +#endif 33 | + 34 | #endif /* GETLINE_H */ 35 | -- 36 | 2.41.0.windows.3 37 | 38 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | 3 | clean: 4 | rm -rf build 5 | ifneq ($(wildcard .git),) 6 | rm -f include/flags.h 7 | ifeq ($(OS),Windows_NT) 8 | git submodule foreach --recursive git config core.symlinks true 9 | endif # Windows_NT 10 | git submodule update -f --recursive 11 | git submodule foreach --recursive git clean -fd 12 | # HACK: On Windows, symlinks have two different types: file and directory, 13 | # if the target path doesn't exist when the symlink is created, 14 | # Cygwin will fallback to create a non-native link, which makes the 15 | # symlink unusable to pure Win32 apps (e.g. our compilers) later. 16 | # 17 | # Since the target path may not exist at the time of creation, we can fix 18 | # this by deleting all the symlinks after the first checkout and 19 | # letting Git to re-create them for us. 20 | ifeq ($(OS),Windows_NT) 21 | find -type l -exec rm -f {} + 22 | git submodule update -f --recursive 23 | endif # Windows_NT 24 | endif # wildcard .git 25 | -------------------------------------------------------------------------------- /patches/android_logging/0007-liblog-logger-don-t-use-std-namespace-on-Windows.patch: -------------------------------------------------------------------------------- 1 | From c1163f7c74113301e7a2a66de371e78e728c1c40 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Mon, 20 Mar 2023 08:27:45 +0800 4 | Subject: [PATCH] liblog: logger: don't use std namespace on Windows 5 | 6 | - it causes std::byte to conflict with the one in MinGW headers 7 | (when you include windows.h it will appear) 8 | 9 | Signed-off-by: Ookiineko 10 | --- 11 | liblog/logger.h | 2 +- 12 | 1 file changed, 1 insertion(+), 1 deletion(-) 13 | 14 | diff --git a/liblog/logger.h b/liblog/logger.h 15 | index 4636173..bcf6e0f 100644 16 | --- a/liblog/logger.h 17 | +++ b/liblog/logger.h 18 | @@ -18,7 +18,11 @@ 19 | 20 | #ifdef __cplusplus 21 | #include 22 | +#ifdef _WIN32 23 | +using std::atomic_int; 24 | +#else 25 | using namespace std; 26 | +#endif 27 | #else 28 | #include 29 | #endif 30 | -- 31 | 2.40.0.windows.1 32 | 33 | -------------------------------------------------------------------------------- /patches/android_logging/0006-Cygwin-has-getprogname.patch: -------------------------------------------------------------------------------- 1 | From 9e32730427f4045158ff7a643b25ab3e7ba73b75 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Sat, 29 Jul 2023 16:49:40 +0800 4 | Subject: [PATCH] Cygwin has getprogname 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | liblog/logger_write.cpp | 2 +- 9 | 1 file changed, 1 insertion(+), 1 deletion(-) 10 | 11 | diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp 12 | index 7057a605..397ece1a 100644 13 | --- a/liblog/logger_write.cpp 14 | +++ b/liblog/logger_write.cpp 15 | @@ -120,7 +120,7 @@ void __android_log_close() { 16 | } 17 | 18 | // BSD-based systems like Android/macOS have getprogname(). Others need us to provide one. 19 | -#if !defined(__APPLE__) && !defined(__BIONIC__) 20 | +#if !defined(__APPLE__) && !defined(__BIONIC__) && !defined(__CYGWIN__) 21 | static const char* getprogname() { 22 | #ifdef _WIN32 23 | static bool first = true; 24 | -- 25 | 2.41.0 26 | 27 | -------------------------------------------------------------------------------- /patches/Magisk/0010-workaround-UTF-8-issues-on-Windows.patch: -------------------------------------------------------------------------------- 1 | From 7f4f80f0d520abb0fdf25a02bdc656f66fb5b797 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Tue, 9 Apr 2024 00:45:17 +0800 4 | Subject: [PATCH] workaround UTF-8 issues on Windows 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | native/src/base/cstr.rs | 2 ++ 9 | 1 file changed, 2 insertions(+) 10 | 11 | diff --git a/native/src/base/cstr.rs b/native/src/base/cstr.rs 12 | index d93db87..4bbbeb9 100644 13 | --- a/native/src/base/cstr.rs 14 | +++ b/native/src/base/cstr.rs 15 | @@ -312,7 +312,9 @@ pub struct Utf8CStr([u8]); 16 | impl Utf8CStr { 17 | pub fn from_cstr(cstr: &CStr) -> Result<&Utf8CStr, StrErr> { 18 | // Validate the buffer during construction 19 | + #[cfg(not(target_os = "windows"))] 20 | str::from_utf8(cstr.to_bytes())?; 21 | + 22 | Ok(unsafe { Self::from_bytes_unchecked(cstr.to_bytes_with_nul()) }) 23 | } 24 | 25 | -- 26 | 2.44.0 27 | 28 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/str.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../include/winsup/str_compat.h" 4 | 5 | // by deltamind106 from: 6 | // https://stackoverflow.com/questions/52988769/writing-own-memmem-for-windows 7 | void *memmem(const void *haystack, int haystacklen, const void *needle, int needlelen) { 8 | unsigned char *csrc = (unsigned char *)haystack; 9 | unsigned char *ctrg = (unsigned char *)needle; 10 | unsigned char *tptr, *cptr; 11 | int searchlen; 12 | int ndx = 0; 13 | 14 | if (!haystack || !haystacklen || !needle || !needlelen) 15 | return NULL; 16 | 17 | while (ndx <= haystacklen) { 18 | cptr = &csrc[ndx]; 19 | if ((searchlen = haystacklen - ndx - needlelen + 1) <= 0) { 20 | return NULL; 21 | } 22 | if ((tptr = memchr(cptr, *ctrg, searchlen)) == NULL) { 23 | return NULL; 24 | } 25 | if (memcmp(tptr, ctrg, needlelen) == 0) { 26 | return tptr; 27 | } 28 | ndx += tptr - cptr + 1; 29 | } 30 | 31 | return NULL; 32 | } 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Magisk"] 2 | path = src/Magisk 3 | url = https://github.com/topjohnwu/Magisk.git 4 | branch = master 5 | shallow = true 6 | [submodule "android_logging"] 7 | path = src/android_logging 8 | url = https://android.googlesource.com/platform/system/logging.git 9 | shallow = true 10 | [submodule "android_libbase"] 11 | path = src/android_libbase 12 | url = https://android.googlesource.com/platform/system/libbase.git 13 | shallow = true 14 | [submodule "android_fmtlib"] 15 | path = src/android_fmtlib 16 | url = https://android.googlesource.com/platform/external/fmtlib.git 17 | shallow = true 18 | [submodule "android_core"] 19 | path = src/android_core 20 | url = https://android.googlesource.com/platform/system/core.git 21 | shallow = true 22 | [submodule "mman-win32"] 23 | path = src/mman-win32 24 | url = https://github.com/alitrack/mman-win32.git 25 | shallow = true 26 | [submodule "msvc_getline"] 27 | path = src/msvc_getline 28 | url = https://github.com/CostantinoGrana/msvc_getline.git 29 | shallow = true 30 | [submodule "corrosion"] 31 | path = src/corrosion 32 | url = https://github.com/corrosion-rs/corrosion.git 33 | shallow = true 34 | -------------------------------------------------------------------------------- /patches/android_logging/0004-fix-initializer-element-is-not-constant-error-when-b.patch: -------------------------------------------------------------------------------- 1 | From 0287fb7244568a5f08c0ac153dcb464df67ff140 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?S=C3=B6ren=20Tempel?= 3 | Date: Tue, 27 Feb 2018 17:37:12 +0100 4 | Subject: [PATCH] fix "initializer element is not constant"-error when building 5 | with g++ 6 | 7 | --- 8 | liblog/logprint.cpp | 6 +++--- 9 | 1 file changed, 3 insertions(+), 3 deletions(-) 10 | 11 | diff --git a/liblog/logprint.cpp b/liblog/logprint.cpp 12 | index a5c5edd0..71868a35 100644 13 | --- a/liblog/logprint.cpp 14 | +++ b/liblog/logprint.cpp 15 | @@ -884,9 +884,9 @@ static int android_log_printBinaryEvent(const unsigned char** pEventData, size_t 16 | } 17 | break; 18 | case TYPE_MONOTONIC: { 19 | - static const uint64_t minute = 60; 20 | - static const uint64_t hour = 60 * minute; 21 | - static const uint64_t day = 24 * hour; 22 | + #define minute (60) 23 | + #define hour (60 * minute) 24 | + #define day (24 * hour) 25 | 26 | /* Repaint as unsigned seconds, minutes, hours ... */ 27 | outBuf -= outCount; 28 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/at_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_AT_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_AT_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define AT_REMOVEDIR 1 13 | #define AT_SYMLINK_NOFOLLOW 2 14 | 15 | ssize_t readlinkat (int dirfd, const char *__restrict path, 16 | char *__restrict buf, size_t len); 17 | 18 | int symlinkat (const char *, int, const char *); 19 | 20 | int linkat (int dirfd1, const char *path1, int dirfd2, const char *path2, int flags); 21 | 22 | int unlinkat (int dirfd, const char *pathname, int flags); 23 | 24 | int openat (int dirfd, const char *pathname, int flags, ...); 25 | 26 | int faccessat (int dirfd, const char *path, int mode, int flags); 27 | 28 | int fstatat (int dirfd, const char *__restrict pathname, struct stat *__restrict buf, int flags); 29 | 30 | int mkdirat (int dirfd, const char *pathname, mode_t mode); 31 | 32 | int renameat (int, const char *, int, const char *); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* _MAGISKBOOT_BUILD_WINSUP_AT_COMPAT */ 39 | -------------------------------------------------------------------------------- /patches/android_libbase/0002-remove-glibc-internal-headers-cdefs.h.patch: -------------------------------------------------------------------------------- 1 | From 412a557f67209e17d680fae14287acef91a1aaab Mon Sep 17 00:00:00 2001 2 | From: jershell 3 | Date: Mon, 30 May 2022 15:19:59 +0300 4 | Subject: [PATCH] remove glibc internal headers cdefs.h 5 | 6 | --- 7 | include/android-base/endian.h | 2 +- 8 | include/android-base/properties.h | 1 - 9 | 2 files changed, 1 insertion(+), 2 deletions(-) 10 | 11 | diff --git a/include/android-base/endian.h b/include/android-base/endian.h 12 | index b47494b..c29845e 100644 13 | --- a/include/android-base/endian.h 14 | +++ b/include/android-base/endian.h 15 | @@ -19,7 +19,7 @@ 16 | /* A cross-platform equivalent of bionic's . */ 17 | 18 | /* For __BIONIC__ and __GLIBC__ */ 19 | -#include 20 | +#include 21 | 22 | #if defined(__BIONIC__) 23 | 24 | diff --git a/include/android-base/properties.h b/include/android-base/properties.h 25 | index 021f466..53b8ea1 100644 26 | --- a/include/android-base/properties.h 27 | +++ b/include/android-base/properties.h 28 | @@ -16,7 +16,6 @@ 29 | 30 | #pragma once 31 | 32 | -#include 33 | 34 | #include 35 | #include 36 | -------------------------------------------------------------------------------- /patches/Magisk/0009-drop-rust-funcs-unused-by-magiskboot.patch: -------------------------------------------------------------------------------- 1 | --- b/native/src/base/cstr.rs 2 | +++ a/native/src/base/cstr.rs 3 | @@ -2,7 +2,10 @@ 4 | use std::ffi::{CStr, FromBytesWithNulError, OsStr}; 5 | use std::fmt::{Arguments, Debug, Display, Formatter, Write}; 6 | use std::ops::{Deref, DerefMut}; 7 | + 8 | +#[cfg(unix)] 9 | use std::os::unix::ffi::OsStrExt; 10 | + 11 | use std::path::{Path, PathBuf}; 12 | use std::str::{Utf8Chunks, Utf8Error}; 13 | use std::{fmt, mem, slice, str}; 14 | @@ -123,6 +122,7 @@ 15 | } 16 | } 17 | 18 | +#[cfg(unix)] 19 | impl StringExt for PathBuf { 20 | #[allow(mutable_transmutes)] 21 | fn nul_terminate(&mut self) -> &mut [u8] { 22 | --- a/native/src/base/files.rs 23 | +++ b/native/src/base/files.rs 24 | @@ -981,6 +981,8 @@ pub(crate) fn map_fd(fd: BorrowedFd, sz: usize, rw: bool) -> io::Result<&'static 25 | } 26 | } 27 | 28 | +cfg_if::cfg_if! { 29 | + if #[cfg(any(target_os = "android", target_os = "linux"))] { 30 | #[allow(dead_code)] 31 | pub struct MountInfo { 32 | pub id: u32, 33 | @@ -1059,4 +1061,6 @@ pub fn parse_mount_info(pid: &str) -> Vec { 34 | }); 35 | } 36 | res 37 | +} 38 | + } 39 | } 40 | -------------------------------------------------------------------------------- /patches/android_libbase/0004-Don-t-use-thread-safety-annotations-with-gcc.patch: -------------------------------------------------------------------------------- 1 | From cceac8459bda753b1709499f47606d83a47c1452 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?= 3 | 4 | Date: Sat, 31 Oct 2020 19:41:43 +0700 5 | Subject: [PATCH] Don't use thread safety annotations with gcc 6 | 7 | These annotations are primarily useful for detecting race conditions in 8 | code. They don't seem to have any runtime effect and are not supported 9 | by gcc. 10 | 11 | See: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html 12 | --- 13 | include/android-base/thread_annotations.h | 4 ++++ 14 | 1 file changed, 4 insertions(+) 15 | 16 | diff --git a/include/android-base/thread_annotations.h b/include/android-base/thread_annotations.h 17 | index 53fe6da..bc62f80 100644 18 | --- a/include/android-base/thread_annotations.h 19 | +++ b/include/android-base/thread_annotations.h 20 | @@ -18,7 +18,11 @@ 21 | 22 | #include 23 | 24 | +#ifdef __clang__ 25 | #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) 26 | +#else 27 | +#define THREAD_ANNOTATION_ATTRIBUTE__(x) 28 | +#endif 29 | 30 | #define CAPABILITY(x) \ 31 | THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) 32 | -------------------------------------------------------------------------------- /src/libc-compat/rs/common/stubs/sendfile.rs: -------------------------------------------------------------------------------- 1 | // defined in src/libc-compat/non-linux/sendfile_fallback.c 2 | 3 | macro_rules! add_sendfile_stubs_if_needed { 4 | () => { 5 | cfg_if::cfg_if! { 6 | if #[cfg(mbb_stubs_sendfile)] { 7 | extern "C" { 8 | #[link_name = "__sendfile_stub"] 9 | fn real_sendfile( 10 | out_fd: crate::c_int, 11 | in_fd: crate::c_int, 12 | count: crate::size_t 13 | ); 14 | } 15 | 16 | f! { 17 | pub fn sendfile( 18 | out_fd: crate::c_int, 19 | in_fd: crate::c_int, 20 | offset: *mut crate::off_t, 21 | count: crate::size_t 22 | ) -> crate::ssize_t { 23 | if offset.is_null() { 24 | real_sendfile(out_fd, in_fd, count); 25 | 0 26 | } else { 27 | panic!("unreachable code") 28 | } 29 | } 30 | } 31 | } 32 | } 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /patches/android_libbase/0003-logging.h-only-activate-ostream-warnings-when-clang-.patch: -------------------------------------------------------------------------------- 1 | From 8f57183a68460bca9d57b75c4b394fc3d7b3286c Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?= 3 | 4 | Date: Sat, 31 Oct 2020 19:40:34 +0700 5 | Subject: [PATCH] logging.h: only activate ostream warnings when clang is used 6 | 7 | --- 8 | include/android-base/logging.h | 2 ++ 9 | 1 file changed, 2 insertions(+) 10 | 11 | diff --git a/include/android-base/logging.h b/include/android-base/logging.h 12 | index 9064075..239cb2e 100644 13 | --- a/include/android-base/logging.h 14 | +++ b/include/android-base/logging.h 15 | @@ -467,6 +467,7 @@ namespace std { // NOLINT(cert-dcl58-cpp) 16 | // Note: to print the pointer, use "<< static_cast(string_pointer)" instead. 17 | // Note: a not-recommended alternative is to let Clang ignore the warning by adding 18 | // -Wno-user-defined-warnings to CPPFLAGS. 19 | +#ifdef __clang__ 20 | #pragma clang diagnostic push 21 | #pragma clang diagnostic ignored "-Wgcc-compat" 22 | #define OSTREAM_STRING_POINTER_USAGE_WARNING \ 23 | @@ -476,5 +477,6 @@ std::ostream& operator<<(std::ostream& stream, const std::string* string_pointer 24 | return stream << static_cast(string_pointer); 25 | } 26 | #pragma clang diagnostic pop 27 | +#endif /* defined(__clang__) */ 28 | 29 | } // namespace std 30 | -------------------------------------------------------------------------------- /patches/corrosion/0002-suppress-rustup-target-not-installed-error.patch: -------------------------------------------------------------------------------- 1 | From ce3ab90de811b243bb87f9db43feafafe3f5d8cd Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Sun, 7 Apr 2024 23:43:53 +0900 4 | Subject: [PATCH] suppress rustup target not installed error 5 | 6 | - we want to be able to prefer building STD from source 7 | 8 | Signed-off-by: Ookiineko 9 | --- 10 | cmake/Corrosion.cmake | 2 +- 11 | 1 file changed, 1 insertion(+), 1 deletion(-) 12 | 13 | diff --git a/cmake/Corrosion.cmake b/cmake/Corrosion.cmake 14 | index b78e283..22f44f2 100644 15 | --- a/cmake/Corrosion.cmake 16 | +++ b/cmake/Corrosion.cmake 17 | @@ -47,7 +47,7 @@ if(Rust_TOOLCHAIN_IS_RUSTUP_MANAGED) 18 | message(DEBUG "Cargo target ${Rust_CARGO_TARGET} is an official target-triple") 19 | message(DEBUG "Installed targets: ${INSTALLED_TARGETS}") 20 | if(NOT ("${Rust_CARGO_TARGET}" IN_LIST INSTALLED_TARGETS)) 21 | - message(FATAL_ERROR "Target ${Rust_CARGO_TARGET} is not installed for toolchain ${Rust_TOOLCHAIN}.\n" 22 | + message(WARNING "Target ${Rust_CARGO_TARGET} is not installed for toolchain ${Rust_TOOLCHAIN}.\n" 23 | "Help: Run `rustup target add --toolchain ${Rust_TOOLCHAIN} ${Rust_CARGO_TARGET}` to install " 24 | "the missing target." 25 | ) 26 | -- 27 | 2.44.0 28 | 29 | -------------------------------------------------------------------------------- /src/libc-compat/rs/windows/defs.rs: -------------------------------------------------------------------------------- 1 | pub use libc::*; 2 | 3 | // mkdir 4 | 5 | // this shadows the original one provided by MinGW 6 | // we add the missing mode arg here :) 7 | 8 | extern "C" { 9 | #[link_name = "_mkdir_stub"] 10 | pub fn mkdir(path: *const crate::c_char, mode: crate::mode_t) -> crate::c_int; 11 | } 12 | 13 | // io 14 | 15 | // wtf 16 | 17 | extern "C" { 18 | #[link_name = "_read_stub"] 19 | pub fn read(fd: crate::c_int, buf: *mut crate::c_void, count: crate::size_t) -> crate::ssize_t; 20 | 21 | #[link_name = "_write_stub"] 22 | pub fn write(fd: crate::c_int, buf: *const crate::c_void, count: crate::size_t) -> crate::ssize_t; 23 | } 24 | 25 | // type mismatch 26 | 27 | // changed from c_int to mode_t (c_short) 28 | // values are not chanegd :) 29 | 30 | pub const S_IFCHR: crate::mode_t = 8192; 31 | pub const S_IFDIR: crate::mode_t = 16384; 32 | pub const S_IFREG: crate::mode_t = 32768; 33 | pub const S_IFMT: crate::mode_t = 61440; 34 | pub const S_IEXEC: crate::mode_t = 64; 35 | pub const S_IWRITE: crate::mode_t = 128; 36 | pub const S_IREAD: crate::mode_t = 256; 37 | 38 | // acl 39 | 40 | // for mode_t type mismatch 41 | 42 | extern "C" { 43 | #[link_name = "chmod"] 44 | fn old_chmod(path: *const c_char, mode: c_int) -> c_int; 45 | } 46 | 47 | f! { 48 | pub fn chmod(path: *const c_char, mode: crate::mode_t) -> c_int { 49 | old_chmod(path, mode as c_int) 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /src/libc-compat/include/winsup/dirent_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAGISKBOOT_BUILD_WINSUP_DIRENT_COMPAT 2 | #define _MAGISKBOOT_BUILD_WINSUP_DIRENT_COMPAT 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | #define DT_UNKNOWN 0 11 | #define DT_REG 1 12 | #define DT_LNK 2 13 | #define DT_DIR 3 14 | #define DT_FIFO 4 15 | #define DT_SOCK 5 16 | #define DT_BLK 6 17 | #define DT_CHR 7 18 | 19 | typedef struct _DIR_wrap _DIR_stub; 20 | 21 | struct _dirent_stub 22 | { 23 | long d_ino; /* Always zero. */ 24 | unsigned char d_type; /* file type. this may not be supported 25 | by all the file systems */ 26 | unsigned short d_reclen; /* Always zero. */ 27 | unsigned short d_namlen; /* Length of name in d_name. */ 28 | char d_name[260]; /* [FILENAME_MAX] */ /* File name. */ 29 | }; 30 | 31 | struct _DIR_wrap { 32 | DIR *dirp; 33 | int fd; 34 | }; 35 | 36 | _DIR_stub *_opendir_stub (const char*); 37 | 38 | _DIR_stub *fdopendir(int fd); 39 | 40 | struct _dirent_stub* _readdir_stub (_DIR_stub*); 41 | 42 | int _closedir_stub (_DIR_stub*); 43 | 44 | void _rewinddir_stub (_DIR_stub*); 45 | 46 | long _telldir_stub (_DIR_stub*); 47 | 48 | void _seekdir_stub (_DIR_stub*, long); 49 | 50 | int dirfd (_DIR_stub*); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | #endif /* _MAGISKBOOT_BUILD_WINSUP_DIRENT_COMPAT */ 57 | -------------------------------------------------------------------------------- /patches/Magisk/0004-disable-funcs-not-used-by-magiskboot.patch: -------------------------------------------------------------------------------- 1 | --- a/native/src/base/misc.cpp 2 | +++ b/native/src/base/misc.cpp 3 | @@ -68,6 +68,7 @@ int fork_dont_care() { 4 | return 0; 5 | } 6 | 7 | +#ifdef __linux__ 8 | int fork_no_orphan() { 9 | int pid = xfork(); 10 | if (pid) 11 | @@ -77,6 +78,7 @@ int fork_no_orphan() { 12 | exit(1); 13 | return 0; 14 | } 15 | +#endif 16 | 17 | int exec_command(exec_t &exec) { 18 | auto pipefd = array{-1, -1}; 19 | @@ -270,6 +270,7 @@ uint32_t binary_gcd(uint32_t u, uint32_t v) { 20 | return u << shift; 21 | } 22 | 23 | +#ifdef __linux__ 24 | int switch_mnt_ns(int pid) { 25 | char mnt[32]; 26 | ssprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid); 27 | @@ -283,6 +284,7 @@ int switch_mnt_ns(int pid) { 28 | close(fd); 29 | return ret; 30 | } 31 | +#endif 32 | 33 | string &replace_all(string &str, string_view from, string_view to) { 34 | size_t pos = 0; 35 | --- a/native/src/base/stream.cpp 36 | +++ b/native/src/base/stream.cpp 37 | @@ -9,6 +9,7 @@ 38 | 39 | using namespace std; 40 | 41 | +#if 0 42 | static int strm_read(void *v, char *buf, int len) { 43 | auto strm = static_cast(v); 44 | return strm->read(buf, len); 45 | @@ -34,6 +50,7 @@ sFILE make_channel_fp(channel_ptr &&strm) { 46 | setbuf(fp.get(), nullptr); 47 | return fp; 48 | } 49 | +#endif 50 | 51 | ssize_t in_stream::readFully(void *buf, size_t len) { 52 | size_t read_sz = 0; 53 | -------------------------------------------------------------------------------- /.github/__release_template.md: -------------------------------------------------------------------------------- 1 | > [!IMPORTANT] 2 | > 3 | > The official magiskboot only supports running on Android and Linux, 4 | > 5 | > If you find something that works on the officially supported platforms, 6 | > but not on the extra platforms supported by magiskboot_build, then that 7 | > is a magiskboot_build-specific bug. 8 | > 9 | > Please, do ***NOT*** report magiskboot_build bugs to the upstream Magisk! 10 | 11 | > [!NOTE] 12 | > 13 | > Android and Linux CI builds are not / no longer uploaded to Release to save space, please use `libmagiskboot.so` extracted from the official [Magisk][Magisk] APKs instead. 14 | 15 | For debug builds, please download from [here](../../releases/last-debug-ci) instead. 16 | 17 | #### For Windows releases 18 | 19 | - `msvcrt`: usually works on most Windows versions without extra setup 20 | 21 | - `ucrt`: available by default only since Windows 10+, sometimes requires installing or shipping with C runtime library manually to use on older version 22 | 23 | #### For macOS users 24 | 25 | OS release number is minimal required version to run the binary, binaries from the previous OS release(s) should work. 26 | 27 | #### About Web builds 28 | 29 | - `noderawfs`: using NodeJS's host filesystem API (requires NodeJS to run, see the *WebAssembly*->*Emscripten* section in [README.md](README.md#emscripten) for more details), build with this tag is intended for running on desktop OS that is not yet supported by magiskboot_build 30 | 31 | [Magisk]: https://github.com/topjohnwu/Magisk/releases 32 | -------------------------------------------------------------------------------- /patches/android_core/0001-Fix-inclusion-of-stdatomic.h-with-g.patch: -------------------------------------------------------------------------------- 1 | From 448fa2a3c470ff3a58135458fb34d33732600f67 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?S=C3=B6ren=20Tempel?= 3 | Date: Tue, 27 Feb 2018 16:30:30 +0100 4 | Subject: [PATCH] Fix inclusion of stdatomic.h with g++ 5 | 6 | See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932#c5 7 | --- 8 | libcutils/include/cutils/atomic.h | 6 ++++++ 9 | libcutils/include/cutils/trace.h | 5 +++++ 10 | 2 files changed, 11 insertions(+) 11 | 12 | diff --git a/libcutils/include/cutils/atomic.h b/libcutils/include/cutils/atomic.h 13 | index 0c88bfedd..84606e307 100644 14 | --- a/libcutils/include/cutils/atomic.h 15 | +++ b/libcutils/include/cutils/atomic.h 16 | @@ -19,7 +19,13 @@ 17 | 18 | #include 19 | #include 20 | + 21 | +#ifdef __cplusplus 22 | +#include 23 | +using namespace std; 24 | +#else 25 | #include 26 | +#endif 27 | 28 | #ifndef ANDROID_ATOMIC_INLINE 29 | #define ANDROID_ATOMIC_INLINE static inline 30 | diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h 31 | index ef426ff7b..f7d7ccc3c 100644 32 | --- a/libcutils/include/cutils/trace.h 33 | +++ b/libcutils/include/cutils/trace.h 34 | @@ -18,7 +18,12 @@ 35 | #define _LIBS_CUTILS_TRACE_H 36 | 37 | #include 38 | +#ifdef __cplusplus 39 | +#include 40 | +using namespace std; 41 | +#else 42 | #include 43 | +#endif 44 | #include 45 | #include 46 | #include 47 | -------------------------------------------------------------------------------- /patches/android_libbase/0005-fix-unique_fd.h-for-Termux.patch: -------------------------------------------------------------------------------- 1 | From dc8972eff142d2455420ac01ff6bd069f1a8f8d6 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?=3D=3FUTF-8=3Fq=3F=3DE9=3D9F=3DA9=3DE6=3D9C=3DB4=3DE5=3DAE?= 3 | =?UTF-8?q?=3D87=3F=3D?= 4 | Date: Thu, 8 Apr 2021 00:51:30 +0800 5 | Subject: [PATCH] fix unique_fd.h for Termux 6 | 7 | Signed-off-by: Ookiineko 8 | --- 9 | include/android-base/unique_fd.h | 4 ++-- 10 | 1 file changed, 2 insertions(+), 2 deletions(-) 11 | 12 | diff --git a/include/android-base/unique_fd.h b/include/android-base/unique_fd.h 13 | index 1ffe02f..d7a8376 100644 14 | --- a/include/android-base/unique_fd.h 15 | +++ b/include/android-base/unique_fd.h 16 | @@ -29,7 +29,7 @@ 17 | // Including other headers from libbase frequently results in inclusion of 18 | // android-base/macros.h, which causes macro collisions. 19 | 20 | -#if defined(__BIONIC__) 21 | +#if 0 22 | #include 23 | #endif 24 | #if !defined(_WIN32) && !defined(__TRUSTY__) 25 | @@ -151,7 +151,7 @@ class unique_fd_impl final { 26 | // The actual details of closing are factored out to support unusual cases. 27 | // Almost everyone will want this DefaultCloser, which handles fdsan on bionic. 28 | struct DefaultCloser { 29 | -#if defined(__BIONIC__) 30 | +#if 0 31 | static void Tag(int fd, void* old_addr, void* new_addr) { 32 | if (android_fdsan_exchange_owner_tag) { 33 | uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD, 34 | -- 35 | 2.39.2 36 | 37 | -------------------------------------------------------------------------------- /CMakeLists.rust.txt: -------------------------------------------------------------------------------- 1 | if (CMAKE_BUILD_TYPE MATCHES "MinSize") 2 | message(STATUS "Rust build will be optimized for size") 3 | list(APPEND RUSTFLAGS -Copt-level=z) 4 | endif() 5 | 6 | if (CMAKE_BUILD_TYPE MATCHES "WithDebInfo") 7 | message(STATUS "Debug info enabled for Rust build") 8 | list(APPEND RUSTFLAGS -g) 9 | endif() 10 | 11 | list(APPEND RUSTFLAGS -A dead_code 12 | -A unused_imports 13 | -A redundant_semicolons 14 | -A unused_unsafe) 15 | 16 | if (RUST_BUILD_STD) 17 | message(STATUS "Building Rust STD from source") 18 | set(CARGO_FLAGS ${CARGO_FLAGS} -Zbuild-std) 19 | set(Rust_Detect_CARGO_FLAGS ${Rust_Detect_CARGO_FLAGS} -Zbuild-std) 20 | else() 21 | message(STATUS "Using prebuilt Rust STD") 22 | endif() 23 | 24 | set(Rust_Detect_ENV_VARS RUSTC_BOOTSTRAP=${RUSTC_BOOTSTRAP}) 25 | 26 | if (FULL_RUST_LTO) 27 | message(STATUS "Full LTO enabled") 28 | list(APPEND RUSTFLAGS -Clto=yes) 29 | list(APPEND RUSTFLAGS -Clinker-plugin-lto=yes) 30 | list(APPEND RUSTFLAGS -Cembed-bitcode=yes) 31 | else() 32 | message(STATUS "Full LTO disabled") 33 | list(APPEND RUSTFLAGS -Clto=no) 34 | list(APPEND RUSTFLAGS -Clinker-plugin-lto=no) 35 | list(APPEND RUSTFLAGS -Cembed-bitcode=no) 36 | endif() 37 | 38 | message(STATUS "RUSTFLAGS: ${RUSTFLAGS}") 39 | message(STATUS "CARGO_FLAGS: ${CARGO_FLAGS}") 40 | 41 | # Rust/Cargo integration for CMake (aka cmake-cargo) 42 | # Doc: https://corrosion-rs.github.io/corrosion/ 43 | add_subdirectory(src/corrosion) 44 | -------------------------------------------------------------------------------- /patches/android_core/0010-Correct-version-in-which-gettid-was-introduced-to-gl.patch: -------------------------------------------------------------------------------- 1 | From 0950d4ac7ab12f3fc493e9e5b5e2e74154291bbd Mon Sep 17 00:00:00 2001 2 | From: munix9 <44939650+munix9@users.noreply.github.com> 3 | Date: Mon, 5 Jul 2021 23:33:46 +0200 4 | Subject: [PATCH] Correct version in which gettid was introduced to glibc 5 | 6 | --- 7 | libcutils/include/cutils/threads.h | 2 +- 8 | libcutils/threads.cpp | 2 +- 9 | 2 files changed, 2 insertions(+), 2 deletions(-) 10 | 11 | diff --git a/libcutils/include/cutils/threads.h b/libcutils/include/cutils/threads.h 12 | index 0082c6c63..a85e12988 100644 13 | --- a/libcutils/include/cutils/threads.h 14 | +++ b/libcutils/include/cutils/threads.h 15 | @@ -31,7 +31,7 @@ extern "C" { 16 | // 17 | // Deprecated: use android::base::GetThreadId instead, which doesn't truncate on Mac/Windows. 18 | // 19 | -#if !defined(__GLIBC__) || __GLIBC__ >= 2 && __GLIBC_MINOR__ < 32 20 | +#if !defined(__GLIBC__) || __GLIBC__ >= 2 && __GLIBC_MINOR__ < 31 21 | extern pid_t gettid(); 22 | #endif 23 | 24 | diff --git a/libcutils/threads.cpp b/libcutils/threads.cpp 25 | index 6ece7a3af..a15ff6aa3 100644 26 | --- a/libcutils/threads.cpp 27 | +++ b/libcutils/threads.cpp 28 | @@ -25,7 +25,7 @@ 29 | #include 30 | #endif 31 | 32 | -#if defined(__BIONIC__) || defined(__GLIBC__) && __GLIBC_MINOR__ >= 32 33 | +#if defined(__BIONIC__) || defined(__GLIBC__) && __GLIBC_MINOR__ >= 31 34 | // No definition needed for Android because we'll just pick up bionic's copy. 35 | // No definition needed for Glibc >= 2.32 because it exposes its own copy. 36 | #else 37 | -------------------------------------------------------------------------------- /patches/corrosion/0001-support-pc-windows-gnullvm-targets.patch: -------------------------------------------------------------------------------- 1 | From 84bd18c9af0bec8bcd36706a60f7b71cba6b7873 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Sun, 7 Apr 2024 22:50:35 +0900 4 | Subject: [PATCH] support `*-pc-windows-gnullvm` targets 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | cmake/Corrosion.cmake | 5 ++++- 9 | 1 file changed, 4 insertions(+), 1 deletion(-) 10 | 11 | diff --git a/cmake/Corrosion.cmake b/cmake/Corrosion.cmake 12 | index e47efe4..b78e283 100644 13 | --- a/cmake/Corrosion.cmake 14 | +++ b/cmake/Corrosion.cmake 15 | @@ -347,6 +347,7 @@ function(_corrosion_add_library_target) 16 | 17 | set(is_windows "") 18 | set(is_windows_gnu "") 19 | + set(is_windows_gnullvm "") 20 | set(is_windows_msvc "") 21 | set(is_macos "") 22 | if(Rust_CARGO_TARGET_OS STREQUAL "windows") 23 | @@ -355,6 +356,8 @@ function(_corrosion_add_library_target) 24 | set(is_windows_msvc TRUE) 25 | elseif(Rust_CARGO_TARGET_ENV STREQUAL "gnu") 26 | set(is_windows_gnu TRUE) 27 | + elseif(Rust_CARGO_TARGET_ENV STREQUAL "gnullvm") 28 | + set(is_windows_gnullvm TRUE) 29 | endif() 30 | elseif(Rust_CARGO_TARGET_OS STREQUAL "darwin") 31 | set(is_macos TRUE) 32 | @@ -379,7 +382,7 @@ function(_corrosion_add_library_target) 33 | 34 | if(is_windows_msvc) 35 | set(implib_name "${lib_name}.dll.lib") 36 | - elseif(is_windows_gnu) 37 | + elseif(is_windows_gnu OR is_windows_gnullvm) 38 | set(implib_name "lib${lib_name}.dll.a") 39 | elseif(is_windows) 40 | message(FATAL_ERROR "Unknown windows environment - Can't determine implib name") 41 | -- 42 | 2.44.0 43 | 44 | -------------------------------------------------------------------------------- /CMakeLists.android.txt: -------------------------------------------------------------------------------- 1 | # the followings are copied from android-tools 2 | 3 | add_subdirectory(src/android_fmtlib EXCLUDE_FROM_ALL) 4 | 5 | add_library(android_liblog STATIC 6 | src/android_logging/liblog/log_event_list.cpp 7 | src/android_logging/liblog/log_event_write.cpp 8 | src/android_logging/liblog/logger_name.cpp 9 | src/android_logging/liblog/logger_read.cpp 10 | src/android_logging/liblog/logger_write.cpp 11 | src/android_logging/liblog/properties.cpp 12 | src/android_logging/liblog/logprint.cpp) 13 | target_compile_definitions(android_liblog PRIVATE 14 | -DLIBLOG_LOG_TAG=1006 -D_XOPEN_SOURCE=700 -DFAKE_LOG_DEVICE=1) 15 | target_include_directories(android_liblog PUBLIC 16 | src/android_core/include 17 | src/android_logging/liblog/include 18 | src/android_core/libcutils/include 19 | src/android_libbase/include) 20 | 21 | add_library(android_libbase STATIC 22 | src/android_libbase/abi_compatibility.cpp 23 | src/android_libbase/chrono_utils.cpp 24 | src/android_libbase/file.cpp 25 | src/android_libbase/hex.cpp 26 | src/android_libbase/logging.cpp 27 | src/android_libbase/mapped_file.cpp 28 | src/android_libbase/parsebool.cpp 29 | src/android_libbase/parsenetaddress.cpp 30 | src/android_libbase/posix_strerror_r.cpp 31 | src/android_libbase/properties.cpp 32 | src/android_libbase/stringprintf.cpp 33 | src/android_libbase/strings.cpp 34 | src/android_libbase/threads.cpp 35 | src/android_libbase/test_utils.cpp 36 | src/android_libbase/errors_unix.cpp) 37 | target_include_directories(android_libbase PUBLIC 38 | src/android_libbase/include src/android_core/include) 39 | target_link_libraries(android_libbase PUBLIC fmt::fmt android_liblog) 40 | 41 | -------------------------------------------------------------------------------- /src/libc-compat/non-linux/sendfile_fallback.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifndef NDEBUG 8 | # include 9 | #endif 10 | 11 | #ifndef MIN 12 | # define MIN(a, b) (((a) < (b)) ? (a) : (b)) 13 | #endif 14 | 15 | #define sf_buf_size 8192 16 | 17 | void __sendfile_stub(int out_fd, int in_fd, size_t count) { 18 | char sf_buf[sf_buf_size]; 19 | size_t n_read, n_write, n_write_new; 20 | off_t n_left = count; 21 | 22 | while (n_left) { 23 | n_read = read(in_fd, &sf_buf, MIN(n_left, sf_buf_size)); 24 | if (n_read == 0) 25 | break; 26 | if (n_read < 0) { 27 | if (errno == EINTR) // operation interrupted by signal 28 | continue; // retry the read 29 | #ifndef NDEBUG 30 | perror("read"); 31 | #endif 32 | break; 33 | } 34 | n_write = write(out_fd, &sf_buf, n_read); 35 | assert(n_write != 0); 36 | if (n_write < 0) { 37 | if (errno == EINTR) // operation interrupted by signal 38 | n_write = 0; // allow retrying the write 39 | else { 40 | #ifndef NDEBUG 41 | perror("write"); 42 | #endif 43 | return; 44 | } 45 | } 46 | while (n_write < n_read) { 47 | n_write_new = write(out_fd, (&sf_buf) + n_write, n_read - n_write); 48 | assert(n_write_new != 0); 49 | if (n_write_new < 0) { 50 | if (errno == EINTR) // operation interrupted by signal 51 | continue; // retry the write 52 | #ifndef NDEBUG 53 | perror("write"); 54 | #endif 55 | return; 56 | } 57 | n_write += n_write_new; 58 | } 59 | n_left -= n_write; 60 | } 61 | 62 | return; 63 | } 64 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Tell us if something doesn't work correctly. 4 | title: "[bug report] CHANGE ME TO A SHORT TITLE" 5 | labels: unconfirmed 6 | assignees: '' 7 | 8 | --- 9 | 10 | 31 | 32 | **Basic information** 33 | 34 | 35 | * Am I using debug build: CHANGE TO YES OR NO 36 | 37 | 38 | * OS and machine: FILLME 39 | 40 | 42 | * ZIP file name of the magiskboot binary I am using: FILLME 43 | 44 | **Description of the bug** 45 | 46 | 47 | 48 | FILLME 49 | 50 | **Expected behavior** 51 | 52 | 54 | 55 | FILLME 56 | 57 | **Bug hehavior** 58 | 59 | 60 | 61 | FILLME 62 | 63 | **Extra links** 64 | 65 | 66 | 67 | FILLME 68 | -------------------------------------------------------------------------------- /patches/android_core/0008-Vector-don-t-assign-to-const-object.patch: -------------------------------------------------------------------------------- 1 | From 55a4b14b6557c7e767afd043571c2b7485c6e1eb Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?=C4=90o=C3=A0n=20Tr=E1=BA=A7n=20C=C3=B4ng=20Danh?= 3 | 4 | Date: Sun, 1 Nov 2020 10:14:11 +0700 5 | Subject: [PATCH] Vector: don't assign to const object 6 | 7 | --- 8 | libutils/include/utils/Vector.h | 15 --------------- 9 | 1 file changed, 15 deletions(-) 10 | 11 | diff --git a/libutils/include/utils/Vector.h b/libutils/include/utils/Vector.h 12 | index be35ea2f0..20804f702 100644 13 | --- a/libutils/include/utils/Vector.h 14 | +++ b/libutils/include/utils/Vector.h 15 | @@ -67,10 +67,7 @@ public: 16 | virtual ~Vector(); 17 | 18 | /*! copy operator */ 19 | - const Vector& operator = (const Vector& rhs) const; 20 | Vector& operator = (const Vector& rhs); 21 | - 22 | - const Vector& operator = (const SortedVector& rhs) const; 23 | Vector& operator = (const SortedVector& rhs); 24 | 25 | /* 26 | @@ -254,24 +251,12 @@ Vector& Vector::operator = (const Vector& rhs) { 27 | return *this; 28 | } 29 | 30 | -template inline 31 | -const Vector& Vector::operator = (const Vector& rhs) const { 32 | - VectorImpl::operator = (static_cast(rhs)); 33 | - return *this; 34 | -} 35 | - 36 | template inline 37 | Vector& Vector::operator = (const SortedVector& rhs) { 38 | VectorImpl::operator = (static_cast(rhs)); 39 | return *this; 40 | } 41 | 42 | -template inline 43 | -const Vector& Vector::operator = (const SortedVector& rhs) const { 44 | - VectorImpl::operator = (rhs); 45 | - return *this; 46 | -} 47 | - 48 | template inline 49 | const TYPE* Vector::array() const { 50 | return static_cast(arrayImpl()); 51 | -------------------------------------------------------------------------------- /patches/corrosion/0003-allow-adding-required-cargo-rust-flags-when-detectin.patch: -------------------------------------------------------------------------------- 1 | From e35d1fc471466eb9194f57803c90ff305024ca05 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Mon, 8 Apr 2024 01:09:20 +0900 4 | Subject: [PATCH] allow adding required cargo/rust flags when detecting LDLIBs 5 | for staticlib 6 | 7 | - this is useful when the STD is supported but built from source instead 8 | 9 | Signed-off-by: Ookiineko 10 | --- 11 | cmake/FindRust.cmake | 6 ++++-- 12 | 1 file changed, 4 insertions(+), 2 deletions(-) 13 | 14 | diff --git a/cmake/FindRust.cmake b/cmake/FindRust.cmake 15 | index 97c65db..678c7dd 100644 16 | --- a/cmake/FindRust.cmake 17 | +++ b/cmake/FindRust.cmake 18 | @@ -147,7 +147,9 @@ function(_corrosion_determine_libs_new target_triple out_libs) 19 | execute_process( 20 | COMMAND ${CMAKE_COMMAND} -E env 21 | "CARGO_BUILD_RUSTC=${Rust_COMPILER_CACHED}" 22 | - ${Rust_CARGO_CACHED} rustc --verbose --color never --target=${target_triple} -- --print=native-static-libs 23 | + "RUSTFLAGS=${Rust_Detect_RUSTFLAGS}" 24 | + ${Rust_Detect_ENV_VARS} 25 | + ${Rust_CARGO_CACHED} ${Rust_Detect_CARGO_FLAGS} rustc --verbose --color never --target=${target_triple} -- --print=native-static-libs 26 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/corrosion/required_libs" 27 | RESULT_VARIABLE cargo_build_result 28 | ERROR_VARIABLE cargo_build_error_message 29 | @@ -286,7 +288,7 @@ if (NOT Rust_RUSTUP) 30 | endif() 31 | 32 | # List of user variables that will override any toolchain-provided setting 33 | -set(_Rust_USER_VARS Rust_COMPILER Rust_CARGO Rust_CARGO_TARGET Rust_CARGO_HOST_TARGET) 34 | +set(_Rust_USER_VARS Rust_COMPILER Rust_CARGO Rust_CARGO_TARGET Rust_CARGO_HOST_TARGET Rust_Detect_RUSTFLAGS Rust_Detect_CARGO_FLAGS Rust_Detect_ENV_VARS) 35 | foreach(_VAR ${_Rust_USER_VARS}) 36 | if (DEFINED "${_VAR}") 37 | set(${_VAR}_CACHED "${${_VAR}}" CACHE INTERNAL "Internal cache of ${_VAR}") 38 | -- 39 | 2.44.0 40 | 41 | -------------------------------------------------------------------------------- /patches/Magisk/0007-HACK-support-cfg-attribute-in-build-script.patch: -------------------------------------------------------------------------------- 1 | From b6f6e76b8586065ca5f706605a94b17fc3c7844f Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Fri, 28 Jul 2023 08:57:59 +0800 4 | Subject: [PATCH] HACK: support cfg attribute in build script 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | native/src/external/cxx-rs/gen/src/cfg.rs | 25 +++++++++++++++++++++---- 9 | 1 file changed, 21 insertions(+), 4 deletions(-) 10 | 11 | diff --git a/native/src/external/cxx-rs/gen/src/cfg.rs b/native/src/external/cxx-rs/gen/src/cfg.rs 12 | index da589085..fd3d2542 100644 13 | --- a/native/src/external/cxx-rs/gen/src/cfg.rs 14 | +++ b/native/src/external/cxx-rs/gen/src/cfg.rs 15 | @@ -5,15 +5,32 @@ use crate::syntax::Api; 16 | use quote::quote; 17 | use std::collections::BTreeSet as Set; 18 | use syn::{Error, LitStr}; 19 | +use std::env; 20 | 21 | pub(super) struct UnsupportedCfgEvaluator; 22 | 23 | impl CfgEvaluator for UnsupportedCfgEvaluator { 24 | fn eval(&self, name: &str, value: Option<&str>) -> CfgResult { 25 | - let _ = name; 26 | - let _ = value; 27 | + if name == "target_os" { 28 | + if let Ok(target_os_value) = env::var("CXXBRIDGE_GEN_TARGET_OS") { 29 | + if let Some(value) = value { 30 | + if target_os_value == value { 31 | + CfgResult::True 32 | + } else { 33 | + CfgResult::False 34 | + } 35 | + } else { 36 | + let msg = "specify the value for the 'target_os' cfg attribute"; 37 | + CfgResult::Undetermined { msg: msg.to_owned() } 38 | + } 39 | + } else { 40 | + let msg = "set the environment variable 'CXXBRIDGE_GEN_TARGET_OS' to use this attribute"; 41 | + CfgResult::Undetermined { msg: msg.to_owned() } 42 | + } 43 | + } else { 44 | let msg = "cfg attribute is not supported".to_owned(); 45 | CfgResult::Undetermined { msg } 46 | + } 47 | } 48 | } 49 | 50 | -- 51 | 2.41.0 52 | 53 | -------------------------------------------------------------------------------- /patches/Magisk/0002-fix-builds-for-some-OS.patch: -------------------------------------------------------------------------------- 1 | diff --git a/native/src/boot/cpio.rs b/native/src/boot/cpio.rs 2 | index d19ce29..0e36b4d 100644 3 | --- a/native/src/boot/cpio.rs 4 | +++ b/native/src/boot/cpio.rs 5 | @@ -353,7 +353,7 @@ impl Cpio { 6 | FsPath::from(&buf).symlink_to(out)?; 7 | } 8 | S_IFBLK | S_IFCHR => { 9 | - let dev = makedev(entry.rdevmajor.try_into()?, entry.rdevminor.try_into()?); 10 | + let dev = unsafe { makedev(entry.rdevmajor.try_into()?, entry.rdevminor.try_into()?) }; 11 | unsafe { mknod(out.as_ptr().cast(), entry.mode, dev) }; 12 | } 13 | _ => { 14 | diff --git a/native/src/base/files.rs b/native/src/base/files.rs 15 | index 6582eee..8678392 100644 16 | --- a/native/src/base/files.rs 17 | +++ b/native/src/base/files.rs 18 | @@ -206,7 +206,7 @@ impl FileAttr { 19 | #[inline(always)] 20 | #[allow(clippy::unnecessary_cast)] 21 | fn is(&self, mode: mode_t) -> bool { 22 | - (self.st.st_mode & libc::S_IFMT as u32) as mode_t == mode 23 | + ((self.st.st_mode as mode_t) & libc::S_IFMT) == mode 24 | } 25 | 26 | pub fn is_dir(&self) -> bool { 27 | diff --git a/native/src/boot/bootimg.cpp b/native/src/boot/bootimg.cpp 28 | index f853e61..1f6b2dc 100644 29 | --- a/native/src/boot/bootimg.cpp 30 | +++ b/native/src/boot/bootimg.cpp 31 | @@ -16,6 +16,23 @@ 32 | 33 | using namespace std; 34 | 35 | +// refs: https://github.com/AcademySoftwareFoundation/Imath/pull/350 36 | +// https://stackoverflow.com/questions/67521312/safe-equivalent-of-stdbit-cast-in-c11 37 | +#if !defined(__cpp_lib_bit_cast) || __cpp_lib_bit_cast < 201806L 38 | +template 39 | +constexpr T2 cpp11_bit_cast(T1 t1) { 40 | + static_assert(sizeof(T1)==sizeof(T2), "Types must match sizes"); 41 | + static_assert(std::is_pod::value, "Requires POD input"); 42 | + static_assert(std::is_pod::value, "Requires POD output"); 43 | + 44 | + T2 t2; 45 | + std::memcpy( std::addressof(t2), std::addressof(t1), sizeof(T1) ); 46 | + return t2; 47 | +} 48 | + 49 | +#define bit_cast cpp11_bit_cast 50 | +#endif 51 | + 52 | #define PADDING 15 53 | #define SHA256_DIGEST_SIZE 32 54 | #define SHA_DIGEST_SIZE 20 55 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/acl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define WIN32_MEAN_AND_LEAN 6 | #include 7 | 8 | #include "../include/winsup/acl_compat.h" 9 | #include "../include/winsup/stat_compat.h" 10 | 11 | #include "internal/errno.h" 12 | 13 | #include "../include/winsup/acl_compat.h" 14 | 15 | #ifndef NDEBUG 16 | # include 17 | #endif 18 | 19 | int fchmod (int fd, mode_t mode) { 20 | HANDLE h = (HANDLE) _get_osfhandle(fd); 21 | 22 | if (h == INVALID_HANDLE_VALUE) 23 | return -1; // errno is already set to EBADF by _get_osfhandle 24 | 25 | BY_HANDLE_FILE_INFORMATION hfi = {}; 26 | 27 | if (!GetFileInformationByHandle(h, &hfi)) { 28 | __set_errno_via_winerr(GetLastError()); 29 | 30 | #ifndef NDEBUG 31 | perror("GetFileInformationByHandle"); 32 | #endif 33 | 34 | return -1; 35 | } 36 | 37 | // ref: https://github.com/reactos/reactos/blob/7f346b1aa350942540c7dee9fce3869bea2a72a6/sdk/lib/crt/stdio/file.c#L764 38 | 39 | DWORD new_attr = (mode & (S_IWUSR | S_IWGRP | S_IWOTH)) ? (hfi.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY) : (hfi.dwFileAttributes | FILE_ATTRIBUTE_READONLY); 40 | 41 | if (new_attr == hfi.dwFileAttributes) 42 | return 0; // attr unchanged 43 | 44 | FILE_BASIC_INFO info = {}; 45 | 46 | info.FileAttributes = new_attr; 47 | 48 | if (!SetFileInformationByHandle(h, FileBasicInfo, &info, sizeof(info))) { 49 | __set_errno_via_winerr(GetLastError()); 50 | 51 | #ifndef NDEBUG 52 | perror("SetFileInformationByHandle"); 53 | #endif 54 | 55 | return -1; 56 | } 57 | 58 | return 0; 59 | } 60 | 61 | int chown (const char *path, uid_t owner, gid_t group) { 62 | if (access(path, F_OK) != 0) 63 | return -1; 64 | 65 | return 0; // FIXME: stub 66 | } 67 | 68 | int fchown (int fildes, uid_t owner, gid_t group) { 69 | struct stat buf; 70 | 71 | if (fstat(fildes, &buf) < 0) 72 | return -1; 73 | 74 | return 0; // FIXME: stub 75 | } 76 | 77 | int lchown (const char *path, uid_t owner, gid_t group) { 78 | struct stat buf; 79 | 80 | if (lstat(path, &buf) < 0) 81 | return -1; 82 | 83 | return 0; // FIXME: stub 84 | } 85 | -------------------------------------------------------------------------------- /patches/android_libbase/0007-fix-properties-for-Termux.patch: -------------------------------------------------------------------------------- 1 | From aa360f6b6062589e0e9946e54cea3a10f0adfdb0 Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?=3D=3FUTF-8=3Fq=3F=3DE9=3D9F=3DA9=3DE6=3D9C=3DB4=3DE5=3DAE?= 3 | =?UTF-8?q?=3D87=3F=3D?= 4 | Date: Fri, 29 Oct 2021 14:52:25 +0800 5 | Subject: [PATCH] fix properties for Termux 6 | 7 | Co-authored-by: Ian Hu 8 | 9 | Signed-off-by: Ookiineko 10 | --- 11 | properties.cpp | 12 ++++-------- 12 | 1 file changed, 4 insertions(+), 8 deletions(-) 13 | 14 | diff --git a/properties.cpp b/properties.cpp 15 | index 8190987..6d48ab8 100644 16 | --- a/properties.cpp 17 | +++ b/properties.cpp 18 | @@ -16,7 +16,7 @@ 19 | 20 | #include "android-base/properties.h" 21 | 22 | -#if defined(__BIONIC__) 23 | +#if 0 24 | #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 25 | #include 26 | #include 27 | @@ -32,11 +32,9 @@ 28 | #include 29 | #include 30 | 31 | -#if !defined(__BIONIC__) 32 | - 33 | #define PROP_VALUE_MAX 92 34 | 35 | -static std::map& g_properties = *new std::map; 36 | +static std::map g_properties; 37 | 38 | int __system_property_set(const char* key, const char* value) { 39 | if (key == nullptr || *key == '\0') return -1; 40 | @@ -63,8 +61,6 @@ int __system_property_get(const char* key, char* value) { 41 | return strlen(value); 42 | } 43 | 44 | -#endif 45 | - 46 | namespace android { 47 | namespace base { 48 | 49 | @@ -108,7 +104,7 @@ template uint64_t GetUintProperty(const std::string&, uint64_t, uint64_t); 50 | 51 | std::string GetProperty(const std::string& key, const std::string& default_value) { 52 | std::string property_value; 53 | -#if defined(__BIONIC__) 54 | +#if 0 55 | const prop_info* pi = __system_property_find(key.c_str()); 56 | if (pi == nullptr) return default_value; 57 | 58 | @@ -134,7 +130,7 @@ bool SetProperty(const std::string& key, const std::string& value) { 59 | return (__system_property_set(key.c_str(), value.c_str()) == 0); 60 | } 61 | 62 | -#if defined(__BIONIC__) 63 | +#if 0 64 | 65 | struct WaitForPropertyData { 66 | bool done; 67 | -- 68 | 2.39.2 69 | 70 | -------------------------------------------------------------------------------- /src/libc-compat/rs/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! __item { 2 | ($i:item) => { 3 | $i 4 | }; 5 | } 6 | 7 | macro_rules! s { 8 | ($($(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($( 9 | s!(it: $(#[$attr])* pub $t $i { $($field)* }); 10 | )*); 11 | (it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => ( 12 | compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead"); 13 | ); 14 | (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => ( 15 | __item! { 16 | #[repr(C)] 17 | #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] 18 | #[allow(deprecated)] 19 | $(#[$attr])* 20 | pub struct $i { $($field)* } 21 | } 22 | #[allow(deprecated)] 23 | impl core::marker::Copy for $i {} 24 | #[allow(deprecated)] 25 | impl core::clone::Clone for $i { 26 | fn clone(&self) -> $i { *self } 27 | } 28 | ); 29 | } 30 | 31 | macro_rules! s_no_extra_traits { 32 | ($($(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($( 33 | s_no_extra_traits!(it: $(#[$attr])* pub $t $i { $($field)* }); 34 | )*); 35 | (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => ( 36 | __item! { 37 | #[repr(C)] 38 | $(#[$attr])* 39 | pub struct $i { $($field)* } 40 | } 41 | #[allow(deprecated)] 42 | impl core::marker::Copy for $i {} 43 | #[allow(deprecated)] 44 | impl core::clone::Clone for $i { 45 | fn clone(&self) -> $i { *self } 46 | } 47 | ); 48 | } 49 | 50 | macro_rules! f { 51 | ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident( 52 | $($arg:ident: $argty:ty),* 53 | ) -> $ret:ty { 54 | $($body:stmt);* 55 | })*) => ($( 56 | #[inline] 57 | $(#[$attr])* 58 | pub unsafe extern fn $i($($arg: $argty),* 59 | ) -> $ret { 60 | $($body);* 61 | } 62 | )*) 63 | } 64 | 65 | macro_rules! safe_f { 66 | ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident( 67 | $($arg:ident: $argty:ty),* 68 | ) -> $ret:ty { 69 | $($body:stmt);* 70 | })*) => ($( 71 | #[inline] 72 | $(#[$attr])* 73 | pub extern fn $i($($arg: $argty),* 74 | ) -> $ret { 75 | $($body);* 76 | } 77 | )*) 78 | } 79 | -------------------------------------------------------------------------------- /patches/Magisk/0003-base-files-disable-BLKGETSIZE-for-non-Linux.patch: -------------------------------------------------------------------------------- 1 | From 350222e64d496615ece40de309b6c9ba9e6b7740 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Mon, 20 Mar 2023 01:42:32 +0800 4 | Subject: [PATCH 2/6] base: files: disable BLKGETSIZE for non-Linux 5 | 6 | - not actually useful to us 7 | 8 | Signed-off-by: Ookiineko 9 | --- 10 | native/src/base/files.hpp | 7 +++++++ 11 | native/src/base/files.rs | 12 ++++++++++++ 12 | 2 file changed, 26 insertions(+) 13 | 14 | diff --git a/native/src/base/files.rs b/native/src/base/files.rs 15 | index f107c34..465d63a 100644 16 | --- a/native/src/base/files.rs 17 | +++ b/native/src/base/files.rs 18 | @@ -483,20 +485,32 @@ 19 | 20 | // We mark the returned slice static because it is valid until explicitly unmapped 21 | pub(crate) fn map_file(path: &Utf8CStr, rw: bool) -> io::Result<&'static mut [u8]> { 22 | + cfg_if::cfg_if! { 23 | + if #[cfg(any(target_os = "linux", target_os = "android"))] { 24 | #[cfg(target_pointer_width = "64")] 25 | const BLKGETSIZE64: u32 = 0x80081272; 26 | 27 | #[cfg(target_pointer_width = "32")] 28 | const BLKGETSIZE64: u32 = 0x80041272; 29 | + } else { 30 | + // no-op 31 | + } 32 | + } 33 | 34 | let flag = if rw { O_RDWR } else { O_RDONLY }; 35 | let f = File::from(open_fd!(path, flag | O_CLOEXEC)?); 36 | 37 | let attr = FsPath::from(path).get_attr()?; 38 | let sz = if attr.is_block_device() { 39 | + cfg_if::cfg_if! { 40 | + if #[cfg(any(target_os = "linux", target_os = "android"))] { 41 | let mut sz = 0_u64; 42 | unsafe { ioctl(f.as_raw_fd(), BLKGETSIZE64, &mut sz) }.as_os_err()?; 43 | sz 44 | + } else { 45 | + panic!("Unreachable code"); 46 | + } 47 | + } 48 | } else { 49 | attr.st.st_size as u64 50 | };-- 51 | diff --git a/native/src/base/files.hpp b/native/src/base/files.hpp 52 | index 0d8d11c..3fda87d 100644 53 | --- a/native/src/base/files.hpp 54 | +++ b/native/src/base/files.hpp 55 | @@ -43,8 +43,10 @@ struct mount_info { 56 | }; 57 | 58 | struct mmap_data : public byte_data { 59 | +#ifdef __linux__ 60 | static_assert((sizeof(void *) == 8 && BLKGETSIZE64 == 0x80081272) || 61 | (sizeof(void *) == 4 && BLKGETSIZE64 == 0x80041272)); 62 | +#endif 63 | ALLOW_MOVE_ONLY(mmap_data) 64 | 65 | explicit mmap_data(const char *name, bool rw = false); 66 | -- 67 | 2.41.0 68 | -------------------------------------------------------------------------------- /src/libc-compat/libbsd/str.c: -------------------------------------------------------------------------------- 1 | /* From OpenBSD libc: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ 2 | 3 | /* 4 | * Copyright (c) 1998 Todd C. Miller 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. The name of the author may not be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 19 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 20 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | 32 | #include "../include/libbsd/str_compat.h" 33 | 34 | /* 35 | * Copy src to string dst of size siz. At most siz-1 characters 36 | * will be copied. Always NUL terminates (unless siz == 0). 37 | * Returns strlen(src); if retval >= siz, truncation occurred. 38 | */ 39 | size_t strlcpy(char *dst, const char *src, size_t siz) { 40 | register char *d = dst; 41 | register const char *s = src; 42 | register size_t n = siz; 43 | 44 | /* Copy as many bytes as will fit */ 45 | if (n != 0 && --n != 0) { 46 | do { 47 | if ((*d++ = *s++) == 0) 48 | break; 49 | } while (--n != 0); 50 | } 51 | 52 | /* Not enough room in dst, add NUL and traverse rest of src */ 53 | if (n == 0) { 54 | if (siz != 0) 55 | *d = '\0'; /* NUL-terminate dst */ 56 | while (*s++) 57 | ; 58 | } 59 | 60 | return(s - src - 1); /* count does not include NUL */ 61 | } 62 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/uio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * from QEMU: 3 | * https://github.com/qemu/qemu/blob/802341823f1720511dd5cf53ae40285f7978c61b/util/osdep.c#L560 4 | * 5 | * Copyright (c) 2003 Fabrice Bellard 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "../include/winsup/uio_compat.h" 30 | 31 | static inline ssize_t __uio_impl(int fd, const struct iovec *iov, int iov_cnt, bool do_write) { 32 | unsigned i = 0; 33 | ssize_t ret = 0; 34 | ssize_t off = 0; 35 | while (i < iov_cnt) { 36 | ssize_t r = do_write 37 | ? write(fd, iov[i].iov_base + off, iov[i].iov_len - off) 38 | : read(fd, iov[i].iov_base + off, iov[i].iov_len - off); 39 | if (r > 0) { 40 | ret += r; 41 | off += r; 42 | if (off < iov[i].iov_len) { 43 | continue; 44 | } 45 | } else if (!r) { 46 | break; 47 | } else if (errno == EINTR) { 48 | continue; 49 | } else { 50 | /* else it is some "other" error, 51 | * only return if there was no data processed. */ 52 | if (ret == 0) { 53 | ret = -1; 54 | } 55 | break; 56 | } 57 | off = 0; 58 | i++; 59 | } 60 | return ret; 61 | } 62 | 63 | ssize_t readv(int fd, const struct iovec *iov, int iov_cnt) { 64 | return __uio_impl(fd, iov, iov_cnt, false); 65 | } 66 | 67 | ssize_t writev(int fd, const struct iovec *iov, int iov_cnt) { 68 | return __uio_impl(fd, iov, iov_cnt, true); 69 | } 70 | -------------------------------------------------------------------------------- /patches-contrib/Magisk/0029-workaround-support-building-with-libstdcxx.patch: -------------------------------------------------------------------------------- 1 | From 03220a4a97225457eb88e25ceb1d11abcc80f84c Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Tue, 12 Dec 2023 03:07:40 +0000 4 | Subject: [PATCH] workaround: support building with libstdc++ 5 | 6 | * may be useful for some really old distros 7 | 8 | Signed-off-by: Ookiineko 9 | --- 10 | native/src/base/files.cpp | 3 +++ 11 | native/src/base/files.hpp | 3 +++ 12 | native/src/base/misc.cpp | 3 +++ 13 | native/src/base/misc.hpp | 3 +++ 14 | native/src/base/stream.cpp | 3 +++ 15 | native/src/boot/format.hpp | 3 +++ 16 | 6 files changed, 18 insertions(+) 17 | 18 | diff --git a/native/src/base/files.cpp b/native/src/base/files.cpp 19 | index 050bda6..c05cf18 100644 20 | --- a/native/src/base/files.cpp 21 | +++ b/native/src/base/files.cpp 22 | @@ -32,6 +32,9 @@ 23 | #define dirent _dirent_stub 24 | #define getline msvc_getline 25 | #endif 26 | +#ifndef _LIBCPP_VERSION 27 | +#include 28 | +#endif 29 | 30 | #include 31 | 32 | diff --git a/native/src/base/files.hpp b/native/src/base/files.hpp 33 | index 9c2d890..19c2dd6 100644 34 | --- a/native/src/base/files.hpp 35 | +++ b/native/src/base/files.hpp 36 | @@ -5,6 +5,10 @@ 37 | #include 38 | #include 39 | #include 40 | +#ifndef _LIBCPP_VERSION 41 | +#include 42 | +#include 43 | +#endif 44 | 45 | #ifdef __linux__ 46 | #include 47 | diff --git a/native/src/base/misc.cpp b/native/src/base/misc.cpp 48 | index 249b698..4e3c342 100644 49 | --- a/native/src/base/misc.cpp 50 | +++ b/native/src/base/misc.cpp 51 | @@ -28,6 +28,9 @@ 52 | #ifdef _WIN32 53 | #include 54 | #endif 55 | +#ifndef _LIBCPP_VERSION 56 | +#include 57 | +#endif 58 | 59 | #include 60 | 61 | diff --git a/native/src/base/misc.hpp b/native/src/base/misc.hpp 62 | index 7ced155..3e9869f 100644 63 | --- a/native/src/base/misc.hpp 64 | +++ b/native/src/base/misc.hpp 65 | @@ -6,6 +6,10 @@ 66 | #include 67 | #include 68 | #include 69 | +#ifndef _LIBCPP_VERSION 70 | +#include 71 | +#include 72 | +#endif 73 | #include 74 | 75 | #include "xwrap.hpp" 76 | diff --git a/native/src/base/stream.cpp b/native/src/base/stream.cpp 77 | index 271cad2..850beb0 100644 78 | --- a/native/src/base/stream.cpp 79 | +++ b/native/src/base/stream.cpp 80 | @@ -1,5 +1,8 @@ 81 | #include 82 | #include 83 | +#ifndef _LIBCPP_VERSION 84 | +#include 85 | +#endif 86 | 87 | #include 88 | #include 89 | diff --git a/native/src/boot/format.hpp b/native/src/boot/format.hpp 90 | index e0634ba..c9e3773 100644 91 | --- a/native/src/boot/format.hpp 92 | +++ b/native/src/boot/format.hpp 93 | @@ -1,6 +1,9 @@ 94 | #pragma once 95 | 96 | #include 97 | +#ifndef _LIBCPP_VERSION 98 | +#include 99 | +#endif 100 | 101 | typedef enum { 102 | UNKNOWN, 103 | -- 104 | 2.41.0 105 | 106 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | debug_release: 6 | type: boolean 7 | description: "Whether if we are creating a debug release" 8 | ci_run_id: 9 | description: "Run ID of the desired CI run to download artifacts from" 10 | required: true 11 | 12 | permissions: 13 | contents: write 14 | 15 | jobs: 16 | release: 17 | name: Release 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | - name: Download artifacts 23 | id: download-artifact 24 | uses: dawidd6/action-download-artifact@v3 25 | with: 26 | workflow: ci.yaml 27 | workflow_conclusion: success 28 | run_id: ${{ github.event.inputs.ci_run_id }} 29 | path: artifacts 30 | skip_unpack: true 31 | 32 | - name: Extract source package 33 | run: | 34 | cd artifacts 35 | unzip -j srcpkg.zip 'magiskboot_*-src.tar.xz' 36 | file magiskboot_*-src.tar.xz 37 | rm -f srcpkg.zip 38 | 39 | - name: Clean up old releases (Debug) 40 | if: github.event.inputs.debug_release == 'true' 41 | uses: dev-drprasad/delete-older-releases@v0.3.2 42 | with: 43 | keep_latest: 0 44 | delete_tags: true 45 | delete_tag_pattern: last-debug-ci 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | 49 | - name: Clean up old releases (Release) 50 | if: github.event.inputs.debug_release != 'true' 51 | uses: dev-drprasad/delete-older-releases@v0.3.2 52 | with: 53 | keep_latest: 0 54 | delete_tags: true 55 | delete_tag_pattern: last-ci 56 | env: 57 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 58 | 59 | - name: Wait for 3s 60 | run: | 61 | # prevent github to think our release already exists and create us a draft 62 | sleep 3 63 | 64 | - name: Create release (Debug) 65 | if: github.event.inputs.debug_release == 'true' 66 | uses: softprops/action-gh-release@v1 67 | with: 68 | name: Last debug CI build 69 | target_commitish: dev 70 | tag_name: last-debug-ci 71 | body_path: ${{ github.workspace }}/.github/__debug_release_template.md 72 | draft: false 73 | prerelease: true 74 | fail_on_unmatched_files: true 75 | files: | 76 | artifacts/magiskboot_*-src.tar.xz 77 | artifacts/*.zip 78 | 79 | - name: Create release (Release) 80 | if: github.event.inputs.debug_release != 'true' 81 | uses: softprops/action-gh-release@v1 82 | with: 83 | name: Last CI build 84 | target_commitish: dev 85 | tag_name: last-ci 86 | body_path: ${{ github.workspace }}/.github/__release_template.md 87 | draft: false 88 | prerelease: false 89 | fail_on_unmatched_files: true 90 | files: | 91 | artifacts/magiskboot_*-src.tar.xz 92 | artifacts/*.zip 93 | -------------------------------------------------------------------------------- /patches/msvc_getline/0001-adapt-to-MinGW.patch: -------------------------------------------------------------------------------- 1 | From ec3c9a9b3a977e8fa26029f2a39a79ffbc8d21e3 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Wed, 22 Mar 2023 09:24:04 +0800 4 | Subject: [PATCH] adapt to MinGW 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | getline.c | 10 ++++++++++ 9 | getline.h | 6 ++++++ 10 | 2 files changed, 16 insertions(+) 11 | 12 | diff --git a/getline.c b/getline.c 13 | index 6c3f699..5d7f4b6 100644 14 | --- a/getline.c 15 | +++ b/getline.c 16 | @@ -3,9 +3,48 @@ 17 | #include 18 | #include 19 | 20 | -// MSVC specific implementation 21 | +#ifdef _UCRT 22 | +# ifndef WIN32_LEAN_AND_MEAN 23 | +# define WIN32_LEAN_AND_MEAN 24 | +#endif 25 | +#include 26 | + 27 | +#ifndef _IOERROR 28 | +# define _IOERROR (0x0010) 29 | +#endif 30 | + 31 | +struct __crt_stdio_stream_data 32 | +{ 33 | + union 34 | + { 35 | + FILE _public_file; 36 | + char* _ptr; 37 | + }; 38 | + 39 | + char* _base; 40 | + int _cnt; 41 | + long _flags; 42 | + long _file; 43 | + int _charbuf; 44 | + int _bufsiz; 45 | + char* _tmpfname; 46 | + CRITICAL_SECTION _lock; 47 | +}; 48 | +#endif 49 | + 50 | static void fseterr(FILE *fp) 51 | { 52 | +#ifdef _UCRT 53 | + // UCRT specific implementation 54 | + _lock_file(fp); 55 | + _InterlockedOr(&(((struct __crt_stdio_stream_data *)fp)->_flags), _IOERROR); 56 | + _unlock_file(fp); 57 | +#else 58 | +# ifdef __MINGW32__ 59 | + // MinGW specific implementation 60 | + ((struct _iobuf *)fp)->_flag |= _IOERR; 61 | +# else 62 | + // MSVC specific implementation 63 | struct file { // Undocumented implementation detail 64 | unsigned char *_ptr; 65 | unsigned char *_base; 66 | @@ -18,6 +56,8 @@ static void fseterr(FILE *fp) 67 | #define _IOERR 0x10 68 | 69 | ((struct file *)fp)->_flag |= _IOERR; 70 | +# endif 71 | +#endif 72 | } 73 | 74 | ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delim, FILE *restrict stream) 75 | @@ -66,7 +106,11 @@ ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delim, FILE *r 76 | return nread; 77 | } 78 | 79 | +#ifdef __MINGW32__ 80 | +ssize_t msvc_getline(char **restrict lineptr, size_t *restrict n, FILE *restrict stream) 81 | +#else 82 | ssize_t getline(char **restrict lineptr, size_t *restrict n, FILE *restrict stream) 83 | +#endif 84 | { 85 | return getdelim(lineptr, n, '\n', stream); 86 | } 87 | diff --git a/getline.h b/getline.h 88 | index ffbb699..b7bab62 100644 89 | --- a/getline.h 90 | +++ b/getline.h 91 | @@ -4,9 +4,15 @@ 92 | #include 93 | 94 | #define restrict __restrict 95 | +#ifndef __MINGW32__ 96 | typedef long long ssize_t; 97 | +#endif 98 | 99 | +#ifdef __MINGW32__ 100 | +ssize_t msvc_getline(char **restrict lineptr, size_t *restrict n, FILE *restrict stream); 101 | +#else 102 | ssize_t getline(char **restrict lineptr, size_t *restrict n, FILE *restrict stream); 103 | +#endif 104 | ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delim, FILE *restrict stream); 105 | 106 | /* 107 | -- 108 | 2.40.0.windows.1 109 | 110 | -------------------------------------------------------------------------------- /src/winsup-rs/fd.rs: -------------------------------------------------------------------------------- 1 | pub use std::os::windows::io::{OwnedHandle as OwnedFd, BorrowedHandle as BorrowedFd}; 2 | pub use libc::c_int as RawFd; 3 | 4 | use std::fs::File; 5 | use std::os::windows::io::{RawHandle, FromRawHandle, AsHandle, AsRawHandle, IntoRawHandle}; 6 | use libc::{get_osfhandle, c_void, open_osfhandle, c_int, O_BINARY}; 7 | 8 | pub trait FromRawFd { 9 | unsafe fn from_raw_fd(fd: RawFd) -> Self; 10 | } 11 | 12 | pub trait AsFd { 13 | fn as_fd(&self) -> BorrowedFd<'_>; 14 | } 15 | 16 | pub trait AsRawFd { 17 | fn as_raw_fd(&self) -> RawFd; 18 | } 19 | 20 | pub trait IntoRawFd { 21 | fn into_raw_fd(self) -> RawFd; 22 | } 23 | 24 | impl FromRawFd for File { 25 | #[inline] 26 | unsafe fn from_raw_fd(fd: RawFd) -> File { 27 | Self::from_raw_handle(get_osfhandle(fd) as *mut c_void) 28 | } 29 | } 30 | 31 | impl FromRawFd for OwnedFd { 32 | #[inline] 33 | unsafe fn from_raw_fd(fd: RawFd) -> Self { 34 | Self::from_raw_handle(get_osfhandle(fd) as *mut c_void) 35 | } 36 | } 37 | 38 | impl AsFd for &T { 39 | #[inline] 40 | fn as_fd(&self) -> BorrowedFd<'_> { 41 | self.as_handle() 42 | } 43 | } 44 | 45 | impl AsFd for &mut T { 46 | #[inline] 47 | fn as_fd(&self) -> BorrowedFd<'_> { 48 | self.as_handle() 49 | } 50 | } 51 | 52 | impl AsFd for Box { 53 | #[inline] 54 | fn as_fd(&self) -> BorrowedFd<'_> { 55 | self.as_handle() 56 | } 57 | } 58 | 59 | impl AsFd for BorrowedFd<'_> { 60 | #[inline] 61 | fn as_fd(&self) -> BorrowedFd<'_> { 62 | self.as_handle() 63 | } 64 | } 65 | 66 | impl AsFd for OwnedFd { 67 | #[inline] 68 | fn as_fd(&self) -> BorrowedFd<'_> { 69 | self.as_handle() 70 | } 71 | } 72 | 73 | impl AsFd for File { 74 | #[inline] 75 | fn as_fd(&self) -> BorrowedFd<'_> { 76 | self.as_handle() 77 | } 78 | } 79 | 80 | extern "C" { 81 | #[link_name = "__get_osfhandle_oflag"] 82 | fn get_oflag(h: RawHandle) -> c_int; 83 | } 84 | 85 | impl AsRawFd for File { 86 | #[inline] 87 | fn as_raw_fd(&self) -> RawFd { 88 | let h = self.as_raw_handle(); 89 | unsafe { open_osfhandle(h as isize, get_oflag(h) | O_BINARY) } 90 | } 91 | } 92 | 93 | impl AsRawFd for BorrowedFd<'_> { 94 | #[inline] 95 | fn as_raw_fd(&self) -> RawFd { 96 | let h = self.as_raw_handle(); 97 | unsafe { open_osfhandle(h as isize, get_oflag(h) | O_BINARY) } 98 | } 99 | } 100 | 101 | impl AsRawFd for OwnedFd { 102 | #[inline] 103 | fn as_raw_fd(&self) -> RawFd { 104 | let h = self.as_raw_handle(); 105 | unsafe { open_osfhandle(h as isize, get_oflag(h) | O_BINARY) } 106 | } 107 | } 108 | 109 | impl IntoRawFd for File { 110 | #[inline] 111 | fn into_raw_fd(self) -> RawFd { 112 | let h = self.into_raw_handle(); 113 | unsafe { open_osfhandle(h as isize, get_oflag(h) | O_BINARY) } 114 | } 115 | } 116 | 117 | impl IntoRawFd for OwnedFd { 118 | #[inline] 119 | fn into_raw_fd(self) -> RawFd { 120 | let h = self.into_raw_handle(); 121 | unsafe { open_osfhandle(h as isize, get_oflag(h) | O_BINARY) } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /patches/Magisk/0005-base-rust-add-fd_path-impl-for-other-OS.patch: -------------------------------------------------------------------------------- 1 | From 18d027606fe53bbb25fc3faa9cd4c5593af4427d Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Mon, 20 Mar 2023 03:51:40 +0800 4 | Subject: [PATCH] base: rust: add fd_path impl for other OS 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | native/src/base/files.rs | 17 +++++++++++++++++ 9 | native/src/base/Cargo.toml | 3 +++ 10 | 2 file changed, 20 insertions(+) 11 | 12 | diff --git a/native/src/base/files.rs b/native/src/base/files.rs 13 | index 892d375..25ed2e7 100644 14 | --- a/native/src/base/files.rs 15 | +++ b/native/src/base/files.rs 16 | @@ -45,12 +45,58 @@ pub fn readlink(path: &Utf8CStr, data: &mut [u8]) -> io::Result { 17 | }; 18 | } 19 | 20 | +#[cfg(any(target_os = "android", target_os = "linux", 21 | + target_os = "cygwin", target_os = "emscripten"))] 22 | pub fn fd_path(fd: RawFd, buf: &mut dyn Utf8CStrBuf) -> io::Result<()> { 23 | let mut arr = Utf8CStrBufArr::<40>::new(); 24 | let path = FsPathBuf::new(&mut arr).join("/proc/self/fd").join_fmt(fd); 25 | path.read_link(buf) 26 | } 27 | 28 | +#[cfg(target_vendor = "apple")] 29 | +pub fn fd_path(fd: RawFd, utf8_buf: &mut dyn Utf8CStrBuf) -> io::Result<()> { 30 | + unsafe { 31 | + let buf = utf8_buf.as_str_mut().as_bytes_mut(); 32 | + let mut path_buf: [u8; libc::PATH_MAX as usize] = [0; libc::PATH_MAX as usize]; 33 | + let ret: isize = libc::fcntl(fd, libc::F_GETPATH, path_buf.as_mut_ptr()) as isize; 34 | + if ret < 0 { 35 | + return Err(io::Error::last_os_error()) 36 | + } 37 | + let len = path_buf.iter().position(|&x| x == 0).unwrap(); 38 | + let copy_len: usize = len.min(buf.len().saturating_sub(1)); 39 | + buf[..copy_len].copy_from_slice(&path_buf[..copy_len]); 40 | + buf.get_mut(copy_len).map(|b| *b = 0); 41 | + Ok(()) 42 | + } 43 | +} 44 | + 45 | +#[cfg(target_os = "windows")] 46 | +use filepath::FilePath; 47 | + 48 | +#[cfg(target_os = "windows")] 49 | +pub fn fd_path(fd: RawFd, utf8_buf: &mut dyn Utf8CStrBuf) -> io::Result<()> { 50 | + unsafe { 51 | + let buf = utf8_buf.as_str_mut().as_bytes_mut(); 52 | + let file = File::from_raw_fd(fd); 53 | + let path = match file.path() { 54 | + Ok(p) => p, 55 | + Err(_) => { 56 | + return Err(io::Error::last_os_error()) 57 | + } 58 | + }; 59 | + let path_str = match path.to_str() { 60 | + Some(s) => s.as_bytes(), 61 | + None => { 62 | + return Err(io::Error::last_os_error()) 63 | + } 64 | + }; 65 | + let bytes_to_copy = path_str.len().min(buf.len().saturating_sub(1)); 66 | + buf[..bytes_to_copy].copy_from_slice(&path_str[..bytes_to_copy]); 67 | + buf.get_mut(bytes_to_copy).map(|b| *b = 0); 68 | + Ok(()) 69 | + } 70 | +} 71 | + 72 | pub trait ReadExt { 73 | fn skip(&mut self, len: usize) -> io::Result<()>; 74 | fn read_pod(&mut self, data: &mut F) -> io::Result<()>; 75 | diff --git a/native/src/base/Cargo.toml b/native/src/base/Cargo.toml 76 | index bfb8e57..f89abca 100644 77 | --- a/native/src/base/Cargo.toml 78 | +++ b/native/src/base/Cargo.toml 79 | @@ -15,3 +15,6 @@ bytemuck = { workspace = true } 80 | num-traits = { workspace = true } 81 | num-derive = { workspace = true } 82 | const_format = { workspace = true } 83 | + 84 | +[target.'cfg(target_os = "windows")'.dependencies] 85 | +filepath = "0.1.2" 86 | -- 87 | 2.40.0 88 | 89 | -------------------------------------------------------------------------------- /patches/mman-win32/0001-set-winerr-via-winsup.patch: -------------------------------------------------------------------------------- 1 | From 7b13afa5bf72cac57118029ec8529b8f07d721f9 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Fri, 17 Nov 2023 16:01:37 +0800 4 | Subject: [PATCH] set winerr via winsup 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | mman.c | 33 +++++++++++++++++++++++++++++++++ 9 | 1 file changed, 33 insertions(+) 10 | 11 | diff --git a/mman.c b/mman.c 12 | index e71666c..97b0408 100644 13 | --- a/mman.c 14 | +++ b/mman.c 15 | @@ -9,6 +9,10 @@ 16 | #define FILE_MAP_EXECUTE 0x0020 17 | #endif /* FILE_MAP_EXECUTE */ 18 | 19 | +#ifdef WITH_WINSUP 20 | +// this function is defined in src/libc-compat/winsup/internal/errno.c 21 | +extern void __set_errno_via_winerr(DWORD winerr); 22 | +#else 23 | static int __map_mman_error(const DWORD err, const int deferr) 24 | { 25 | if (err == 0) 26 | @@ -16,6 +20,7 @@ static int __map_mman_error(const DWORD err, const int deferr) 27 | //TODO: implement 28 | return err; 29 | } 30 | +#endif 31 | 32 | static DWORD __map_mmap_prot_page(const int prot) 33 | { 34 | @@ -107,7 +112,11 @@ void* mmap(void *addr, size_t len, int prot, int flags, int fildes, OffsetType o 35 | 36 | if (fm == NULL) 37 | { 38 | +#ifdef WITH_WINSUP 39 | + __set_errno_via_winerr(GetLastError()); 40 | +#else 41 | errno = __map_mman_error(GetLastError(), EPERM); 42 | +#endif 43 | return MAP_FAILED; 44 | } 45 | 46 | @@ -124,7 +133,11 @@ void* mmap(void *addr, size_t len, int prot, int flags, int fildes, OffsetType o 47 | 48 | if (map == NULL) 49 | { 50 | +#ifdef WITH_WINSUP 51 | + __set_errno_via_winerr(GetLastError()); 52 | +#else 53 | errno = __map_mman_error(GetLastError(), EPERM); 54 | +#endif 55 | return MAP_FAILED; 56 | } 57 | 58 | @@ -136,7 +149,11 @@ int munmap(void *addr, size_t len) 59 | if (UnmapViewOfFile(addr)) 60 | return 0; 61 | 62 | +#ifdef WITH_WINSUP 63 | + __set_errno_via_winerr(GetLastError()); 64 | +#else 65 | errno = __map_mman_error(GetLastError(), EPERM); 66 | +#endif 67 | 68 | return -1; 69 | } 70 | @@ -149,7 +166,11 @@ int _mprotect(void *addr, size_t len, int prot) 71 | if (VirtualProtect(addr, len, newProtect, &oldProtect)) 72 | return 0; 73 | 74 | +#ifdef WITH_WINSUP 75 | + __set_errno_via_winerr(GetLastError()); 76 | +#else 77 | errno = __map_mman_error(GetLastError(), EPERM); 78 | +#endif 79 | 80 | return -1; 81 | } 82 | @@ -159,7 +180,11 @@ int msync(void *addr, size_t len, int flags) 83 | if (FlushViewOfFile(addr, len)) 84 | return 0; 85 | 86 | +#ifdef WITH_WINSUP 87 | + __set_errno_via_winerr(GetLastError()); 88 | +#else 89 | errno = __map_mman_error(GetLastError(), EPERM); 90 | +#endif 91 | 92 | return -1; 93 | } 94 | @@ -169,7 +194,11 @@ int mlock(const void *addr, size_t len) 95 | if (VirtualLock((LPVOID)addr, len)) 96 | return 0; 97 | 98 | +#ifdef WITH_WINSUP 99 | + __set_errno_via_winerr(GetLastError()); 100 | +#else 101 | errno = __map_mman_error(GetLastError(), EPERM); 102 | +#endif 103 | 104 | return -1; 105 | } 106 | @@ -179,7 +208,11 @@ int munlock(const void *addr, size_t len) 107 | if (VirtualUnlock((LPVOID)addr, len)) 108 | return 0; 109 | 110 | +#ifdef WITH_WINSUP 111 | + __set_errno_via_winerr(GetLastError()); 112 | +#else 113 | errno = __map_mman_error(GetLastError(), EPERM); 114 | +#endif 115 | 116 | return -1; 117 | } 118 | -- 119 | 2.42.0 120 | 121 | -------------------------------------------------------------------------------- /CMakeLists.patch.txt: -------------------------------------------------------------------------------- 1 | # XXX: Consider using https://cmake.org/cmake/help/v3.0/module/ExternalProject.html 2 | if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/.mbb_patched AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/patches") 3 | find_program(PATCH_EXECUTABLE patch REQUIRED) 4 | message(STATUS "Found patch: ${PATCH_EXECUTABLE}") 5 | 6 | find_package(Git REQUIRED) 7 | 8 | if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows|MSYS") 9 | # for searching "find" program, not the win32 one 10 | find_program(cygpath_EXECUTABLE cygpath REQUIRED) 11 | message(STATUS "Found cygpath: ${cygpath_EXECUTABLE}") 12 | 13 | execute_process( 14 | COMMAND ${cygpath_EXECUTABLE} -m /bin 15 | OUTPUT_VARIABLE "FIND_FIND_PATH" 16 | COMMAND_ERROR_IS_FATAL ANY 17 | OUTPUT_STRIP_TRAILING_WHITESPACE 18 | ) 19 | 20 | # for the below quirk 21 | find_program(find_EXECUTABLE find REQUIRED PATHS ${FIND_FIND_PATH}) 22 | message(STATUS "Found find: ${find_EXECUTABLE}") 23 | endif() 24 | 25 | set(vendored_dirs 26 | Magisk 27 | android_logging 28 | android_libbase 29 | android_core 30 | android_fmtlib 31 | mman-win32 32 | msvc_getline 33 | corrosion) 34 | 35 | if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows|MSYS") 36 | execute_process(COMMAND ${GIT_EXECUTABLE} submodule foreach --recursive ${GIT_EXECUTABLE} config core.symlinks true 37 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 38 | endif() 39 | 40 | execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --force --recursive 41 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 42 | execute_process(COMMAND ${GIT_EXECUTABLE} submodule foreach --recursive ${GIT_EXECUTABLE} clean -fd 43 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 44 | 45 | if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Windows|MSYS") 46 | # HACK: On Windows, symlinks have two different types: file and directory, 47 | # if the target path doesn't exist when the symlink is created, 48 | # Cygwin will fallback to create a non-native link, which makes the 49 | # symlink unusable to pure Win32 apps (e.g. our compilers) later. 50 | # 51 | # Since the target path may not exist at the time of creation, we can fix 52 | # this by deleting all the symlinks after the first checkout and 53 | # letting Git to re-create them for us. 54 | execute_process(COMMAND ${find_EXECUTABLE} -type l -exec rm -f {} + 55 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 56 | execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --force --recursive 57 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 58 | endif() 59 | 60 | foreach(vendored_dir ${vendored_dirs}) 61 | file(GLOB patches ${CMAKE_CURRENT_SOURCE_DIR}/patches/${vendored_dir}/*.patch) 62 | if(patches) 63 | foreach(patch_filename ${patches}) 64 | message(STATUS "Applying ${patch_filename} for: ${vendored_dir}") 65 | execute_process(COMMAND ${PATCH_EXECUTABLE} -p1 -i ${patch_filename} --no-backup-if-mismatch 66 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/${vendored_dir} 67 | RESULT_VARIABLE ret) 68 | 69 | if(NOT ret STREQUAL "0") 70 | message(FATAL_ERROR "Couldn't apply ${patch_filename} for ${vendored_dir}") 71 | endif() 72 | endforeach() 73 | endif() 74 | endforeach() 75 | 76 | file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/.mbb_patched "") 77 | endif() 78 | -------------------------------------------------------------------------------- /CMakeLists.magiskboot.txt: -------------------------------------------------------------------------------- 1 | # partially copied from Magisk 2 | 3 | corrosion_import_crate(MANIFEST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/Magisk/native/src/Cargo.toml 4 | CRATES magiskboot) 5 | if (RUSTFLAGS) 6 | corrosion_add_target_rustflags(magiskboot ${RUSTFLAGS}) 7 | endif() 8 | if (CARGO_FLAGS) 9 | corrosion_set_cargo_flags(magiskboot ${CARGO_FLAGS}) 10 | endif() 11 | corrosion_set_env_vars(magiskboot 12 | CXXBRIDGE_GEN_TARGET_OS=${CXXBRIDGE_GEN_TARGET_OS} 13 | RUSTC_BOOTSTRAP=${RUSTC_BOOTSTRAP}) 14 | 15 | add_custom_target(workspace_cleanup 16 | COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_CURRENT_SOURCE_DIR}/src/Magisk/native/src/.cargo/config.toml 17 | COMMENT "Cleaning up workspace") 18 | add_dependencies(_cargo-build_magiskboot workspace_cleanup) 19 | 20 | add_library(libbase STATIC 21 | src/Magisk/native/src/base/files.cpp 22 | src/Magisk/native/src/base/misc.cpp 23 | src/Magisk/native/src/base/logging.cpp 24 | src/Magisk/native/src/base/stream.cpp 25 | src/Magisk/native/src/external/cxx-rs/src/cxx.cc 26 | src/magiskbase-rs-wrapper.cc) 27 | add_dependencies(libbase magiskboot-static) 28 | target_compile_definitions(libbase PRIVATE -DRUST_CXX_NO_EXCEPTIONS) 29 | add_dependencies(libbase prepared_generated_directory) 30 | target_include_directories(libbase PRIVATE 31 | src/Magisk/native/src/base 32 | src/Magisk/native/src/external/cxx-rs/include 33 | ${CMAKE_CURRENT_BINARY_DIR}/generated) 34 | target_include_directories(libbase PUBLIC 35 | src/Magisk/native/src/include 36 | src/Magisk/native/src/base/include) 37 | if (CMAKE_SYSTEM_NAME MATCHES "Android") 38 | message(STATUS "Native liblog enabled") 39 | target_link_libraries(libbase log) 40 | else() 41 | target_compile_options(libbase PUBLIC --include=${CMAKE_CURRENT_SOURCE_DIR}/include-android/fortify_stub.h) 42 | 43 | include(CheckSymbolExists) 44 | check_symbol_exists("__printflike" "sys/cdefs.h" HAVE_PRINTFLIKE) 45 | if (NOT HAVE_PRINTFLIKE) 46 | target_compile_options(libbase PUBLIC --include=${CMAKE_CURRENT_SOURCE_DIR}/include-android/libbsd_stub.h) 47 | endif() 48 | 49 | message(STATUS "Using bundled liblog") 50 | target_link_libraries(libbase android_liblog) 51 | endif() 52 | 53 | add_library(libzopfli STATIC 54 | src/Magisk/native/src/external/zopfli/src/zopfli/blocksplitter.c 55 | src/Magisk/native/src/external/zopfli/src/zopfli/cache.c 56 | src/Magisk/native/src/external/zopfli/src/zopfli/deflate.c 57 | src/Magisk/native/src/external/zopfli/src/zopfli/gzip_container.c 58 | src/Magisk/native/src/external/zopfli/src/zopfli/hash.c 59 | src/Magisk/native/src/external/zopfli/src/zopfli/katajainen.c 60 | src/Magisk/native/src/external/zopfli/src/zopfli/lz77.c 61 | src/Magisk/native/src/external/zopfli/src/zopfli/squeeze.c 62 | src/Magisk/native/src/external/zopfli/src/zopfli/tree.c 63 | src/Magisk/native/src/external/zopfli/src/zopfli/util.c 64 | src/Magisk/native/src/external/zopfli/src/zopfli/zlib_container.c 65 | src/Magisk/native/src/external/zopfli/src/zopfli/zopfli_lib.c) 66 | target_include_directories(libzopfli PUBLIC 67 | src/Magisk/native/src/external/zopfli/src) 68 | target_compile_options(libzopfli PRIVATE 69 | -Werror -Wno-unused -Wno-unused-parameter) 70 | 71 | add_executable(magiskboot_exe 72 | src/Magisk/native/src/boot/main.cpp 73 | src/Magisk/native/src/boot/bootimg.cpp 74 | src/Magisk/native/src/boot/compress.cpp 75 | src/Magisk/native/src/boot/format.cpp 76 | src/magiskboot-rs-wrapper.cc) 77 | add_dependencies(magiskboot_exe magiskboot-static) 78 | target_include_directories(magiskboot_exe PRIVATE 79 | src/Magisk/native/src/external/cxx-rs/include) 80 | target_link_libraries(magiskboot_exe 81 | libbase 82 | magiskboot-static 83 | LibLZMA::LibLZMA 84 | PkgConfig::liblz4 85 | BZip2::BZip2 86 | ZLIB::ZLIB 87 | libzopfli 88 | Threads::Threads) 89 | 90 | include(GNUInstallDirs) 91 | install(TARGETS magiskboot_exe DESTINATION ${CMAKE_INSTALL_BINDIR}) 92 | -------------------------------------------------------------------------------- /CMakeLists.magisk.txt: -------------------------------------------------------------------------------- 1 | if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include/flags.h) 2 | find_package(Git REQUIRED) 3 | if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/Magisk/.git) 4 | execute_process( 5 | COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD 6 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/Magisk" 7 | OUTPUT_VARIABLE "MAGISK_VERSION" 8 | COMMAND_ERROR_IS_FATAL ANY 9 | OUTPUT_STRIP_TRAILING_WHITESPACE 10 | ) 11 | else() 12 | message(FATAL_ERROR "Cannot find Magisk") 13 | endif() 14 | 15 | # fallback version 16 | set(MAGISK_VER_CODE 1000000) 17 | 18 | if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/Magisk/gradle.properties) 19 | file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/src/Magisk/gradle.properties MAGISK_CONFIG_CONTENTS) 20 | foreach (MAGISK_CONFIG_LINE ${MAGISK_CONFIG_CONTENTS}) 21 | string(REGEX REPLACE "^[ ]+" "" MAGISK_CONFIG_LINE ${MAGISK_CONFIG_LINE}) 22 | if (MAGISK_CONFIG_LINE STREQUAL "" OR MAGISK_CONFIG_LINE MATCHES "^#") 23 | continue() 24 | else() 25 | string(REGEX MATCH "^[^=]+=[^=#]+" MAGISK_CONFIG_KV ${MAGISK_CONFIG_LINE}) 26 | if (MAGISK_CONFIG_KV STREQUAL "") 27 | continue() 28 | else() 29 | if (MAGISK_CONFIG_KV MATCHES "^magisk\\.") 30 | string(REGEX REPLACE "^magisk\\." "" MAGISK_CONFIG_KV ${MAGISK_CONFIG_KV}) 31 | string(REGEX MATCH "^[^=]+" MAGISK_CONFIG_KEY ${MAGISK_CONFIG_KV}) 32 | string(REGEX REPLACE "^${MAGISK_CONFIG_KEY}=" "" MAGISK_CONFIG_VALUE ${MAGISK_CONFIG_KV}) 33 | if (MAGISK_CONFIG_KEY STREQUAL "versionCode") 34 | set(MAGISK_VER_CODE "${MAGISK_CONFIG_VALUE}") 35 | else() 36 | continue() 37 | endif() 38 | else() 39 | continue() 40 | endif() 41 | endif() 42 | endif() 43 | endforeach() 44 | endif() 45 | message(STATUS "Magisk version: ${MAGISK_VERSION} (version code \"${MAGISK_VER_CODE}\")") 46 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/flags.h.in ${CMAKE_CURRENT_SOURCE_DIR}/include/flags.h @ONLY) 47 | endif() 48 | 49 | if (CMAKE_BUILD_TYPE MATCHES "Debug") 50 | set(MAGISK_DEBUG "1") 51 | else() 52 | set(MAGISK_DEBUG "0") 53 | endif() 54 | find_program(sed_EXECUTABLE sed REQUIRED) 55 | message(STATUS "Found sed: ${sed_EXECUTABLE}") 56 | 57 | # https://unix.stackexchange.com/questions/715352/using-sed-with-i-option-creates-strangely-named-new-file-while-leaving-the 58 | if (APPLE) 59 | # need a space 60 | set(sed_REPLACE_COMMAND ${sed_EXECUTABLE} -i '') 61 | else() 62 | # need no space 63 | set(sed_REPLACE_COMMAND ${sed_EXECUTABLE} -i'') 64 | endif() 65 | 66 | add_custom_target(generate_flags_h_in 67 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/include/flags.h 68 | BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/generated/flags.h.in 69 | COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/generated 70 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/include/flags.h ${CMAKE_CURRENT_BINARY_DIR}/generated/flags.h.in 71 | COMMAND ${sed_REPLACE_COMMAND} "s/!MAGISK_DEBUG!/${MAGISK_DEBUG}/g" ${CMAKE_CURRENT_BINARY_DIR}/generated/flags.h.in 72 | COMMENT "Generating C header flags.h.in") 73 | add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated/flags.h 74 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/generated/flags.h.in 75 | COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/generated/flags.h.in ${CMAKE_CURRENT_BINARY_DIR}/generated/flags.h 76 | COMMENT "Preparing C header flags.h") 77 | add_custom_target(prepared_generated_directory 78 | DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/generated/flags.h) 79 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #ifndef O_CLOEXEC 9 | # define O_CLOEXEC O_NOINHERIT 10 | #endif 11 | 12 | // Origin: https://github.com/wine-mirror/wine/blob/0170cd3a4c67bd99291234dd8e0d638a824d7715/dlls/msvcrt/file.c#L2629 13 | #define CREAT_OFLAGS (O_CREAT | O_TRUNC | O_RDWR) 14 | 15 | // From musl: 16 | // https://github.com/bminor/musl/blob/f314e133929b6379eccc632bef32eaebb66a7335/src/stdio/__fmodeflags.c 17 | // https://github.com/bminor/musl/blob/f314e133929b6379eccc632bef32eaebb66a7335/src/stdio/fopen.c#L12-L16 18 | static int __fmodeflags(const char *mode) 19 | { 20 | if (!strchr("rwa", *mode)) 21 | // check if mode is valid 22 | return -1; 23 | 24 | int flags; 25 | 26 | if (strchr(mode, '+')) flags = O_RDWR; 27 | else if (*mode == 'r') flags = O_RDONLY; 28 | else flags = O_WRONLY; 29 | 30 | if (strchr(mode, 'x')) flags |= O_EXCL; 31 | if (strchr(mode, 'e') || strchr(mode, 'N')) flags |= O_CLOEXEC; 32 | if (*mode != 'r') flags |= O_CREAT; 33 | if (*mode == 'w') flags |= O_TRUNC; 34 | if (*mode == 'a') flags |= O_APPEND; 35 | 36 | flags |= O_BINARY; 37 | 38 | return flags; 39 | } 40 | 41 | static int __fixup_fmode(const char *old_mode, char *mode) { 42 | int flags = __fmodeflags(old_mode); 43 | 44 | if (flags < 0) 45 | return -1; 46 | 47 | bool plus = false; 48 | int ptr = 0; 49 | 50 | if (flags & O_RDWR) { 51 | plus = true; 52 | 53 | if (flags & O_APPEND) 54 | mode[ptr] = 'a'; 55 | else if (flags & O_TRUNC) 56 | mode[ptr] = 'w'; 57 | else if (!(flags & O_CREAT)) 58 | mode[ptr] = 'r'; 59 | else 60 | return -1; 61 | } else if (flags & O_WRONLY) { 62 | if (flags & O_TRUNC) 63 | mode[ptr] = 'w'; 64 | else if (flags & O_APPEND) 65 | mode[ptr] = 'a'; 66 | else 67 | return -1; 68 | } else // O_RDONLY 69 | mode[ptr] = 'r'; 70 | 71 | ptr++; 72 | 73 | if (mode[0] != 'r' && !(flags & O_CREAT)) 74 | return -1; 75 | 76 | if (plus) { 77 | mode[ptr] = '+'; 78 | ptr++; 79 | } 80 | 81 | mode[ptr] = 'b'; 82 | ptr++; 83 | 84 | // fd already opened, ignore nonsense O_EXCL and O_CLOEXEC 85 | 86 | mode[ptr] = '\0'; 87 | 88 | return 0; 89 | } 90 | 91 | FILE *__cdecl __real_fdopen(int fd, const char *mode); 92 | 93 | FILE *__cdecl __wrap_fdopen(int fd, const char *mode) { 94 | char new_mode[16]; 95 | 96 | if (__fixup_fmode(mode, new_mode) < 0) { 97 | errno = EINVAL; 98 | return NULL; 99 | } 100 | 101 | return __real_fdopen(fd, new_mode); 102 | } 103 | 104 | FILE *__cdecl __wrap_fopen(const char *__restrict pathname, const char *__restrict mode) { 105 | int flags = __fmodeflags(mode); 106 | 107 | if (flags < 0) { 108 | errno = EINVAL; 109 | return NULL; 110 | } 111 | 112 | int fd; 113 | 114 | if (flags & O_CREAT) 115 | fd = open(pathname, flags, 0666); 116 | else 117 | fd = open(pathname, flags); 118 | 119 | if (fd < 0) 120 | return NULL; 121 | 122 | return fdopen(fd, mode); 123 | } 124 | 125 | int __cdecl __wrap_creat(const char *path, int mode) { 126 | // HACK: for msvcrt behavior on UCRT 127 | // msvcrt ignores unsupported modes 128 | // but UCRT will give EINVAL 129 | 130 | int fixed_mode = 0; 131 | 132 | if (mode & (S_IRUSR | S_IRGRP | S_IROTH)) 133 | fixed_mode |= S_IREAD; 134 | 135 | if (mode & (S_IWUSR | S_IWGRP | S_IWOTH)) 136 | fixed_mode |= S_IWRITE; 137 | 138 | return open(path, CREAT_OFLAGS, fixed_mode); 139 | } 140 | 141 | // for Rust 142 | 143 | FILE *__cdecl __wrap__fdopen(int fd, const char *mode) { 144 | return fdopen(fd, mode); 145 | } 146 | 147 | int __cdecl __wrap__creat(const char *path, int mode) { 148 | return creat(path, mode); 149 | } 150 | -------------------------------------------------------------------------------- /patches/Magisk/0006-disable-libc-funcs-not-used-by-magiskboot.patch: -------------------------------------------------------------------------------- 1 | --- a/native/src/base/xwrap.rs 2 | +++ b/native/src/base/xwrap.rs 3 | @@ -237,6 +237,7 @@ extern "C" fn xlseek64(fd: RawFd, offset: i64, whence: i32) -> i64 { 4 | } 5 | } 6 | 7 | +#[cfg(any(target_os = "linux", target_os = "android"))] 8 | pub(crate) fn xpipe2(fds: &mut [i32; 2], flags: i32) -> i32 { 9 | unsafe { 10 | let r = libc::pipe2(fds.as_mut_ptr(), flags); 11 | @@ -249,6 +249,7 @@ pub(crate) fn xpipe2(fds: &mut [i32; 2], flags: i32) -> i32 { 12 | } 13 | 14 | #[no_mangle] 15 | +#[cfg(any(target_os = "linux", target_os = "android"))] 16 | extern "C" fn xsetns(fd: RawFd, nstype: i32) -> i32 { 17 | unsafe { 18 | let r = libc::setns(fd, nstype); 19 | @@ -260,6 +261,7 @@ extern "C" fn xsetns(fd: RawFd, nstype: i32) -> i32 { 20 | } 21 | 22 | #[no_mangle] 23 | +#[cfg(any(target_os = "linux", target_os = "android"))] 24 | extern "C" fn xunshare(flags: i32) -> i32 { 25 | unsafe { 26 | let r = libc::unshare(flags); 27 | @@ -353,6 +355,7 @@ extern "C" fn xlisten(socket: i32, backlog: i32) -> i32 { 28 | } 29 | 30 | #[no_mangle] 31 | +#[cfg(any(target_os = "linux", target_os = "android"))] 32 | unsafe extern "C" fn xaccept4( 33 | sockfd: RawFd, 34 | addr: *mut sockaddr, 35 | @@ -461,6 +464,7 @@ extern "C" fn xdup2(oldfd: RawFd, newfd: RawFd) -> RawFd { 36 | } 37 | 38 | #[no_mangle] 39 | +#[cfg(any(target_os = "linux", target_os = "android"))] 40 | extern "C" fn xdup3(oldfd: RawFd, newfd: RawFd, flags: i32) -> RawFd { 41 | unsafe { 42 | let fd = libc::syscall(SYS_dup3, oldfd, newfd, flags) as RawFd; 43 | @@ -524,6 +527,7 @@ unsafe extern "C" fn xlinkat( 44 | } 45 | 46 | #[no_mangle] 47 | +#[cfg(any(target_os = "linux", target_os = "android"))] 48 | unsafe extern "C" fn xmount( 49 | src: *const c_char, 50 | target: *const c_char, 51 | @@ -539,6 +543,7 @@ unsafe extern "C" fn xmount( 52 | } 53 | 54 | #[no_mangle] 55 | +#[cfg(any(target_os = "linux", target_os = "android"))] 56 | unsafe extern "C" fn xumount(target: *const c_char) -> i32 { 57 | let r = libc::umount(target); 58 | if r < 0 { 59 | @@ -548,6 +553,7 @@ unsafe extern "C" fn xumount(target: *const c_char) -> i32 { 60 | } 61 | 62 | #[no_mangle] 63 | +#[cfg(any(target_os = "linux", target_os = "android"))] 64 | unsafe extern "C" fn xumount2(target: *const c_char, flags: i32) -> i32 { 65 | let r = libc::umount2(target, flags); 66 | if r < 0 { 67 | --- a/native/src/base/lib.rs 68 | +++ b/native/src/base/lib.rs 69 | @@ -41,7 +41,9 @@ pub mod ffi { 70 | 71 | #[namespace = "rust"] 72 | extern "Rust" { 73 | + #[cfg(any(target_os = "linux", target_os = "android"))] 74 | fn xpipe2(fds: &mut [i32; 2], flags: i32) -> i32; 75 | + 76 | #[cxx_name = "fd_path"] 77 | fn fd_path(fd: i32, buf: &mut [u8]) -> isize; 78 | #[cxx_name = "map_file" 79 | --- a/native/src/base/misc.cpp 80 | +++ b/native/src/base/misc.cpp 81 | @@ -99,11 +99,20 @@ int gen_rand_str(char *buf, int len, bool varlen) { 82 | } 83 | 84 | int exec_command(exec_t &exec) { 85 | +#ifdef __linux__ 86 | auto pipefd = array{-1, -1}; 87 | +#else 88 | + int pipefd[2] = {-1, -1}; 89 | +#endif 90 | + 91 | int outfd = -1; 92 | 93 | if (exec.fd == -1) { 94 | +#ifdef __linux__ 95 | if (xpipe2(pipefd, O_CLOEXEC) == -1) 96 | +#else 97 | + if (pipe(pipefd) == -1) 98 | +#endif 99 | return -1; 100 | outfd = pipefd[1]; 101 | } else if (exec.fd >= 0) { 102 | @@ -175,7 +175,9 @@ void init_argv0(int argc, char **argv) { 103 | void set_nice_name(const char *name) { 104 | memset(argv0, 0, name_len); 105 | strscpy(argv0, name, name_len); 106 | +#if 0 107 | prctl(PR_SET_NAME, name); 108 | +#endif 109 | } 110 | 111 | /* 112 | --- a/native/src/base/include/base.hpp 113 | +++ b/native/src/base/include/base.hpp 114 | @@ -9,5 +9,7 @@ 115 | #endif 116 | #include "../base-rs.hpp" 117 | 118 | +#ifdef __linux__ 119 | using rust::xpipe2; 120 | +#endif 121 | using rust::fd_path; 122 | \ No newline at end of file 123 | -------------------------------------------------------------------------------- /patches/android_libbase/0006-remove-usage-of-__builtin_available.patch: -------------------------------------------------------------------------------- 1 | From eeed6a8ba037863cf96323ecc57b1368eeaddac3 Mon Sep 17 00:00:00 2001 2 | From: John Zimmermann 3 | Date: Thu, 18 Mar 2021 15:27:47 +0100 4 | Subject: [PATCH] remove usage of __builtin_available 5 | 6 | s/__builtin_available([^\)]*)/false/g 7 | --- 8 | logging.cpp | 18 +++++++++--------- 9 | 1 file changed, 9 insertions(+), 9 deletions(-) 10 | 11 | diff --git a/logging.cpp b/logging.cpp 12 | index d71a261..d07b2fb 100644 13 | --- a/logging.cpp 14 | +++ b/logging.cpp 15 | @@ -213,7 +213,7 @@ static std::recursive_mutex& TagLock() { 16 | static std::string* gDefaultTag; 17 | 18 | void SetDefaultTag(const std::string& tag) { 19 | - if (__builtin_available(android 30, *)) { 20 | + if (false) { 21 | __android_log_set_default_tag(tag.c_str()); 22 | } else { 23 | std::lock_guard lock(TagLock()); 24 | @@ -316,7 +316,7 @@ static void LogdLogChunk(LogId id, LogSeverity severity, const char* tag, const 25 | int32_t lg_id = LogIdTolog_id_t(id); 26 | int32_t priority = LogSeverityToPriority(severity); 27 | 28 | - if (__builtin_available(android 30, *)) { 29 | + if (false) { 30 | __android_log_message log_message = {sizeof(__android_log_message), lg_id, priority, tag, 31 | static_cast(nullptr), 0, message}; 32 | __android_log_logd_logger(&log_message); 33 | @@ -398,7 +398,7 @@ LogFunction SetLogger(LogFunction&& logger) { 34 | LogFunction old_logger = std::move(Logger()); 35 | Logger() = std::move(logger); 36 | 37 | - if (__builtin_available(android 30, *)) { 38 | + if (false) { 39 | __android_log_set_logger([](const struct __android_log_message* log_message) { 40 | auto log_id = log_id_tToLogId(log_message->buffer_id); 41 | auto severity = PriorityToLogSeverity(log_message->priority); 42 | @@ -414,7 +414,7 @@ AbortFunction SetAborter(AbortFunction&& aborter) { 43 | AbortFunction old_aborter = std::move(Aborter()); 44 | Aborter() = std::move(aborter); 45 | 46 | - if (__builtin_available(android 30, *)) { 47 | + if (false) { 48 | __android_log_set_aborter([](const char* abort_message) { Aborter()(abort_message); }); 49 | } 50 | return old_aborter; 51 | @@ -502,7 +502,7 @@ LogMessage::~LogMessage() { 52 | 53 | // Abort if necessary. 54 | if (data_->GetSeverity() == FATAL) { 55 | - if (__builtin_available(android 30, *)) { 56 | + if (false) { 57 | __android_log_call_aborter(msg.c_str()); 58 | } else { 59 | Aborter()(msg.c_str()); 60 | @@ -517,7 +517,7 @@ std::ostream& LogMessage::stream() { 61 | void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severity, const char* tag, 62 | const char* message) { 63 | int32_t priority = LogSeverityToPriority(severity); 64 | - if (__builtin_available(android 30, *)) { 65 | + if (false) { 66 | __android_log_message log_message = { 67 | sizeof(__android_log_message), LOG_ID_DEFAULT, priority, tag, file, line, message}; 68 | __android_log_write_log_message(&log_message); 69 | @@ -536,7 +536,7 @@ void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity severi 70 | } 71 | 72 | LogSeverity GetMinimumLogSeverity() { 73 | - if (__builtin_available(android 30, *)) { 74 | + if (false) { 75 | return PriorityToLogSeverity(__android_log_get_minimum_priority()); 76 | } else { 77 | return gMinimumLogSeverity; 78 | @@ -547,7 +547,7 @@ bool ShouldLog(LogSeverity severity, const char* tag) { 79 | // Even though we're not using the R liblog functions in this function, if we're running on Q, 80 | // we need to fall back to using gMinimumLogSeverity, since __android_log_is_loggable() will not 81 | // take into consideration the value from SetMinimumLogSeverity(). 82 | - if (__builtin_available(android 30, *)) { 83 | + if (false) { 84 | int32_t priority = LogSeverityToPriority(severity); 85 | return __android_log_is_loggable(priority, tag, ANDROID_LOG_INFO); 86 | } else { 87 | @@ -556,7 +556,7 @@ bool ShouldLog(LogSeverity severity, const char* tag) { 88 | } 89 | 90 | LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) { 91 | - if (__builtin_available(android 30, *)) { 92 | + if (false) { 93 | int32_t priority = LogSeverityToPriority(new_severity); 94 | return PriorityToLogSeverity(__android_log_set_minimum_priority(priority)); 95 | } else { 96 | -------------------------------------------------------------------------------- /CMakeLists.compat.txt: -------------------------------------------------------------------------------- 1 | string(TOLOWER "${CMAKE_SYSTEM_NAME}" CXXBRIDGE_GEN_TARGET_OS) 2 | 3 | if (CMAKE_SYSTEM_NAME STREQUAL "Linux") 4 | # no-op 5 | elseif (CMAKE_SYSTEM_NAME STREQUAL "Android") 6 | # no-op 7 | elseif (APPLE) 8 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DARWIN_C_SOURCE -D__DARWIN_C_LEVEL=__DARWIN_C_FULL") 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_DARWIN_C_SOURCE -D__DARWIN_C_LEVEL=__DARWIN_C_FULL") 10 | 11 | if (CMAKE_CROSSCOMPILING) 12 | message(STATUS "Homebrew is disabled due to cross-compiling") 13 | else() 14 | find_program(HOMEBREW_EXECUTABLE brew REQUIRED) 15 | execute_process( 16 | COMMAND ${HOMEBREW_EXECUTABLE} --prefix 17 | OUTPUT_VARIABLE "HOMEBREW_PREFIX" 18 | ERROR_QUIET 19 | OUTPUT_STRIP_TRAILING_WHITESPACE 20 | ) 21 | execute_process( 22 | COMMAND ${HOMEBREW_EXECUTABLE} --version 23 | OUTPUT_VARIABLE "HOMEBREW_VERSION" 24 | ERROR_QUIET 25 | OUTPUT_STRIP_TRAILING_WHITESPACE 26 | ) 27 | if (HOMEBREW_VERSION MATCHES "^Homebrew[ \t]+") 28 | string(REGEX MATCH "^Homebrew[ \t]+[^\n]+" HOMEBREW_VERSION ${HOMEBREW_VERSION}) 29 | string(REGEX REPLACE "^Homebrew[ \t]+" "" HOMEBREW_VERSION ${HOMEBREW_VERSION}) 30 | else() 31 | set(HOMEBREW_VERSION "unknown") 32 | endif() 33 | if (EXISTS ${HOMEBREW_PREFIX}) 34 | message(STATUS "Found Homebrew: ${HOMEBREW_EXECUTABLE} (version ${HOMEBREW_VERSION})") 35 | else() 36 | message(WARNING "Cannot find Homebrew") 37 | endif() 38 | list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${HOMEBREW_PREFIX}) 39 | endif() 40 | elseif (WIN32) 41 | # force struct stat to use 64-bit time_t (to match Rust's libc crate) 42 | add_compile_definitions(__MINGW_USE_VC2005_COMPAT) 43 | 44 | # handled in CMakeLists.stub.txt 45 | elseif (CYGWIN) 46 | add_compile_definitions(__USE_LINUX_IOCTL_DEFS) 47 | elseif (EMSCRIPTEN) 48 | # exists in musl but not in rust libc crate 49 | list(APPEND RUSTFLAGS --cfg mbb_stubs_SYS_dup3) 50 | else() 51 | message(WARNING " 52 | New platform: ${CMAKE_SYSTEM_NAME} 53 | 54 | You can file an Issue about this platform at https://github.com/ookiineko/magiskboot_build/issues if the build fails") 55 | endif() 56 | 57 | include(CheckSymbolExists) 58 | check_symbol_exists(_GNU_SOURCE "features.h" HAVE__GNU_SOURCE) 59 | if(NOT HAVE__GNU_SOURCE) 60 | add_compile_definitions(_GNU_SOURCE) 61 | set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_GNU_SOURCE") 62 | endif() 63 | 64 | add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE64_SOURCE) 65 | set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE") 66 | 67 | list(APPEND CMAKE_REQUIRED_INCLUDES "sys/types.h") 68 | include(CheckTypeSize) 69 | check_type_size(off64_t SIZEOF_off64_t) 70 | if(NOT HAVE_off64_t) 71 | add_compile_definitions(off64_t=off_t) 72 | endif() 73 | 74 | include(CheckSymbolExists) 75 | check_symbol_exists(lseek64 "unistd.h" LSEEK64_EXISTS) 76 | if(NOT LSEEK64_EXISTS) 77 | add_compile_definitions(lseek64=lseek) 78 | 79 | list(APPEND RUSTFLAGS --cfg mbb_stubs_lseek64) 80 | endif() 81 | 82 | check_symbol_exists(lseek64 "unistd.h" FTRUNCATE64_EXISTS) 83 | if(NOT FTRUNCATE64_EXISTS) 84 | add_compile_definitions(ftruncate64=ftruncate) 85 | endif() 86 | 87 | check_symbol_exists(O_PATH "fcntl.h" HAVE_O_PATH) 88 | if(NOT HAVE_O_PATH) 89 | list(APPEND RUSTFLAGS --cfg mbb_stubs_O_PATH) 90 | endif() 91 | 92 | check_symbol_exists(SYS_dup3 "sys/syscall.h" HAVE_SYS_dup3) 93 | if(NOT HAVE_SYS_dup3) 94 | list(APPEND RUSTFLAGS --cfg mbb_stubs_SYS_dup3) 95 | endif() 96 | 97 | if (CMAKE_SYSTEM_NAME MATCHES "Android") 98 | message(STATUS "Fortify enabled") 99 | add_compile_options(-D_FORTIFY_SOURCE=2) 100 | else() 101 | message(STATUS "Fortify disabled") 102 | # Couldn't bypass fortify, so disable it 103 | # see also: include-android/fortify_stub.h 104 | add_compile_options(-U_FORTIFY_SOURCE) 105 | 106 | include(CMakeLists.android.txt) 107 | endif() 108 | 109 | check_symbol_exists(sendfile "sys/sendfile.h" HAVE_sendfile) 110 | if (NOT HAVE_sendfile) 111 | list(APPEND RUSTFLAGS --cfg mbb_stubs_sendfile) 112 | endif() 113 | 114 | check_symbol_exists(__errno "errno.h" HAVE___errno) 115 | if(NOT HAVE___errno) 116 | list(APPEND RUSTFLAGS --cfg mbb_stubs___errno) 117 | endif() 118 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define WIN32_LEAN_AND_MEAN 11 | #include 12 | 13 | #include "internal/assert.h" 14 | #include "internal/errno.h" 15 | #include "internal/fd.h" 16 | 17 | #define LOG_TAG "open_compat" 18 | 19 | int __cdecl __real_open(const char *path, int oflag, ... ); 20 | 21 | static int open_impl(const char *path, int oflag, va_list ap) { 22 | oflag |= O_BINARY; 23 | 24 | struct stat buf; 25 | 26 | if (oflag & O_CREAT) { 27 | // creating file, cannot be a directory 28 | 29 | int ret = __real_open(path, oflag, (mode_t) va_arg(ap, int)); 30 | 31 | return ret; 32 | } 33 | 34 | // otherwise the 3rd argument `mode' is unused 35 | 36 | if (stat(path, &buf) < 0) 37 | // doesn't exist, cannot be a directory 38 | goto use_mingw; 39 | 40 | if (S_ISDIR(buf.st_mode)) { 41 | DWORD access = 0, share_mode = 0; 42 | 43 | switch (oflag & O_ACCMODE) { 44 | case O_RDONLY: // this is the default 45 | access = GENERIC_READ; 46 | share_mode = FILE_SHARE_VALID_FLAGS; 47 | break; 48 | case O_WRONLY: 49 | case O_RDWR: 50 | // writing to directory fd is nonsense 51 | errno = EISDIR; 52 | return -1; 53 | default: 54 | #ifndef NDEBUG 55 | LOG_ERR("invalid access mode"); 56 | #endif 57 | errno = EINVAL; 58 | return -1; 59 | } 60 | 61 | // ignoring other oflags according to POSIX 62 | 63 | int fd = __open_dir_fd(path, access, share_mode, oflag); 64 | 65 | if (fd < 0) { 66 | __set_errno_via_winerr(GetLastError()); 67 | 68 | return -1; 69 | } 70 | 71 | return fd; 72 | } 73 | 74 | use_mingw: 75 | return __real_open(path, oflag); // not a directory, mingw impl is good 76 | } 77 | 78 | int __cdecl __wrap_open(const char *path, int oflag, ... ) { 79 | va_list ap; 80 | va_start(ap, oflag); 81 | 82 | int fd = open_impl(path, oflag, ap); 83 | 84 | va_end(ap); 85 | 86 | if (!(fd < 0)) 87 | __fd_cache_oflag(fd, oflag); 88 | 89 | return fd; 90 | } 91 | 92 | // for Rust 93 | 94 | int __cdecl __wrap__open(const char *path, int oflag, ... ) { 95 | va_list ap; 96 | int res; 97 | 98 | va_start(ap, oflag); 99 | if (oflag & O_CREAT) 100 | res = open(path, oflag, (mode_t) va_arg(ap, int)); 101 | else 102 | res = open(path, oflag); 103 | va_end(ap); 104 | 105 | return res; 106 | } 107 | 108 | HANDLE WINAPI __real_CreateFileW(const wchar_t *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, 109 | SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, 110 | DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 111 | 112 | HANDLE WINAPI __wrap_CreateFileW(const wchar_t *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, 113 | SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, 114 | DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { 115 | if (!lpFileName || !lpFileName[0]) 116 | goto skip; // bad arguments 117 | 118 | switch (dwCreationDisposition) { 119 | case CREATE_ALWAYS: 120 | case CREATE_NEW: 121 | case OPEN_ALWAYS: 122 | // these flags might ask to create a new file 123 | break; 124 | case OPEN_EXISTING: 125 | case TRUNCATE_EXISTING: 126 | // these flags will always open an existing file 127 | goto skip; 128 | default: 129 | LOG_ERR("FIXME: unhandled dwCreationDisposition %ld", dwCreationDisposition); 130 | break; 131 | } 132 | 133 | char path[PATH_MAX + 1]; 134 | 135 | if (!WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, 136 | lpFileName, -1, path, sizeof(path), NULL, NULL)) { 137 | LOG_ERR("WideCharToMultiByte failed: %s", win_strerror(GetLastError())); 138 | 139 | abort(); 140 | } 141 | 142 | skip: 143 | return __real_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, 144 | dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); 145 | } 146 | -------------------------------------------------------------------------------- /patches/mman-win32/0002-implement-MAP_PRIVATE-using-copy-on-write-protection.patch: -------------------------------------------------------------------------------- 1 | From b7679531f5dfd3132ff79095fb6edda862ab0939 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Fri, 17 Nov 2023 17:17:43 +0800 4 | Subject: [PATCH] implement MAP_PRIVATE using copy on write protection 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | mman.c | 35 ++++++++++++++++++++++------------- 9 | mman.h | 2 +- 10 | 2 files changed, 23 insertions(+), 14 deletions(-) 11 | 12 | diff --git a/mman.c b/mman.c 13 | index 97b0408..6e7f5d6 100644 14 | --- a/mman.c 15 | +++ b/mman.c 16 | @@ -2,6 +2,7 @@ 17 | #include 18 | #include 19 | #include 20 | +#include 21 | 22 | #include "mman.h" 23 | 24 | @@ -22,7 +23,7 @@ static int __map_mman_error(const DWORD err, const int deferr) 25 | } 26 | #endif 27 | 28 | -static DWORD __map_mmap_prot_page(const int prot) 29 | +static DWORD __map_mmap_prot_page(const int prot, const int flags) 30 | { 31 | DWORD protect = 0; 32 | 33 | @@ -32,29 +33,36 @@ static DWORD __map_mmap_prot_page(const int prot) 34 | if ((prot & PROT_EXEC) != 0) 35 | { 36 | protect = ((prot & PROT_WRITE) != 0) ? 37 | - PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; 38 | + (((flags & MAP_PRIVATE) != 0) ? PAGE_EXECUTE_WRITECOPY : PAGE_EXECUTE_READWRITE) : PAGE_EXECUTE_READ; 39 | } 40 | else 41 | { 42 | protect = ((prot & PROT_WRITE) != 0) ? 43 | - PAGE_READWRITE : PAGE_READONLY; 44 | + (((flags & MAP_PRIVATE) != 0) ? PAGE_WRITECOPY : PAGE_READWRITE) : PAGE_READONLY; 45 | } 46 | 47 | return protect; 48 | } 49 | 50 | -static DWORD __map_mmap_prot_file(const int prot) 51 | +static DWORD __map_mmap_prot_file(const int prot, const int flags) 52 | { 53 | DWORD desiredAccess = 0; 54 | 55 | if (prot == PROT_NONE) 56 | return desiredAccess; 57 | - 58 | - if ((prot & PROT_READ) != 0) 59 | + 60 | + bool map_read = (prot & PROT_READ) != 0; 61 | + bool map_write = (prot & PROT_WRITE) != 0; 62 | + bool map_exec = (prot & PROT_EXEC) != 0; 63 | + bool map_private = (flags & MAP_PRIVATE) != 0; 64 | + bool map_copy = map_write && map_private; 65 | + 66 | + // ref: https://stackoverflow.com/questions/55018806/copy-on-write-file-mapping-on-windows 67 | + if (map_read && !map_copy) 68 | desiredAccess |= FILE_MAP_READ; 69 | - if ((prot & PROT_WRITE) != 0) 70 | - desiredAccess |= FILE_MAP_WRITE; 71 | - if ((prot & PROT_EXEC) != 0) 72 | + if (map_write) 73 | + desiredAccess |= map_private ? FILE_MAP_COPY : FILE_MAP_WRITE; 74 | + if (map_exec) 75 | desiredAccess |= FILE_MAP_EXECUTE; 76 | 77 | return desiredAccess; 78 | @@ -75,8 +83,8 @@ void* mmap(void *addr, size_t len, int prot, int flags, int fildes, OffsetType o 79 | (DWORD)off : (DWORD)(off & 0xFFFFFFFFL); 80 | const DWORD dwFileOffsetHigh = (sizeof(OffsetType) <= sizeof(DWORD)) ? 81 | (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL); 82 | - const DWORD protect = __map_mmap_prot_page(prot); 83 | - const DWORD desiredAccess = __map_mmap_prot_file(prot); 84 | + const DWORD protect = __map_mmap_prot_page(prot, flags); 85 | + const DWORD desiredAccess = __map_mmap_prot_file(prot, flags); 86 | 87 | const OffsetType maxSize = off + (OffsetType)len; 88 | 89 | @@ -158,9 +166,10 @@ int munmap(void *addr, size_t len) 90 | return -1; 91 | } 92 | 93 | -int _mprotect(void *addr, size_t len, int prot) 94 | +// TODO: not portable, use VirtualQuery to get old protection instead 95 | +int _mprotect_np(void *addr, size_t len, int prot, int map_flags) 96 | { 97 | - DWORD newProtect = __map_mmap_prot_page(prot); 98 | + DWORD newProtect = __map_mmap_prot_page(prot, map_flags); 99 | DWORD oldProtect = 0; 100 | 101 | if (VirtualProtect(addr, len, newProtect, &oldProtect)) 102 | diff --git a/mman.h b/mman.h 103 | index 047d3a0..ac0ce2b 100644 104 | --- a/mman.h 105 | +++ b/mman.h 106 | @@ -64,7 +64,7 @@ extern "C" { 107 | 108 | MMANSHARED_EXPORT void* mmap(void *addr, size_t len, int prot, int flags, int fildes, OffsetType off); 109 | MMANSHARED_EXPORT int munmap(void *addr, size_t len); 110 | -MMANSHARED_EXPORT int _mprotect(void *addr, size_t len, int prot); 111 | +MMANSHARED_EXPORT int _mprotect_np(void *addr, size_t len, int prot, int map_flags); 112 | MMANSHARED_EXPORT int msync(void *addr, size_t len, int flags); 113 | MMANSHARED_EXPORT int mlock(const void *addr, size_t len); 114 | MMANSHARED_EXPORT int munlock(const void *addr, size_t len); 115 | -- 116 | 2.42.0 117 | 118 | -------------------------------------------------------------------------------- /CMakeLists.stub.txt: -------------------------------------------------------------------------------- 1 | include(CheckSymbolExists) 2 | check_symbol_exists( 3 | "strlcpy" 4 | "string.h" 5 | HAVE_STRLCPY) 6 | if (HAVE_STRLCPY) 7 | target_compile_definitions(libbase PRIVATE 8 | -DHAVE_STRLCPY) 9 | endif() 10 | 11 | add_library(platform_stubs STATIC 12 | src/libc-compat/placeholder.c) 13 | target_include_directories(platform_stubs PUBLIC src/libc-compat/include) 14 | 15 | if (NOT HAVE_sendfile) 16 | message(STATUS "Using generic sendfile replacement") 17 | target_sources(platform_stubs PRIVATE 18 | src/libc-compat/non-linux/sendfile_fallback.c) 19 | endif() 20 | 21 | if (NOT HAVE_STRLCPY) 22 | message(STATUS "Using bundled libbsd strlcpy implementation") 23 | target_sources(platform_stubs PRIVATE 24 | src/libc-compat/libbsd/str.c) 25 | endif() 26 | 27 | if(NOT HAVE___errno) 28 | target_sources(platform_stubs PRIVATE 29 | src/libc-compat/common/__errno.c) 30 | 31 | # e.g Linux and Emscripten 32 | check_symbol_exists(__errno_location "errno.h" HAVE___errno_location) 33 | if (HAVE___errno_location) 34 | set_source_files_properties(src/libc-compat/common/__errno.c PROPERTIES 35 | COMPILE_FLAGS -DHAVE___errno_location) 36 | else() 37 | # e.g macOS 38 | check_symbol_exists(__error "errno.h" HAVE___error) 39 | if (HAVE___error) 40 | set_source_files_properties(src/libc-compat/common/__errno.c PROPERTIES 41 | COMPILE_FLAGS -DHAVE___error) 42 | else() 43 | # e.g MinGW 44 | check_symbol_exists(_errno "errno.h" HAVE__errno) 45 | if (HAVE__errno) 46 | set_source_files_properties(src/libc-compat/common/__errno.c PROPERTIES 47 | COMPILE_FLAGS -DHAVE__errno) 48 | else() 49 | message(FATAL_ERROR "Don't know errno implementation on this platform") 50 | endif() 51 | endif() 52 | endif() 53 | 54 | message(STATUS "Using __errno alias") 55 | endif() 56 | 57 | if (WIN32) 58 | message(STATUS "Using win32 libc-compat") 59 | 60 | target_sources(platform_stubs PRIVATE 61 | src/libc-compat/winsup/acl.c 62 | src/libc-compat/winsup/at.c 63 | src/libc-compat/winsup/dirent.c 64 | src/libc-compat/winsup/file.c 65 | src/libc-compat/winsup/io.c 66 | src/libc-compat/winsup/link.c 67 | src/libc-compat/winsup/mkdir.c 68 | src/libc-compat/winsup/mknod_stub.c 69 | src/libc-compat/winsup/open.c 70 | src/libc-compat/winsup/stat.c 71 | src/libc-compat/winsup/str.c 72 | src/libc-compat/winsup/uio.c 73 | src/libc-compat/winsup/internal/assert.c 74 | src/libc-compat/winsup/internal/errno.c 75 | src/libc-compat/winsup/internal/fd.c) 76 | target_link_libraries(platform_stubs INTERFACE shlwapi) 77 | 78 | # these source files contains symbols that must not be excluded from the final executable 79 | target_sources(magiskboot_exe PRIVATE 80 | src/libc-compat/winsup/crt_flags.c) 81 | 82 | add_library(libmman STATIC 83 | src/mman-win32/mman.c) 84 | target_compile_definitions(libmman PRIVATE -DWITH_WINSUP) 85 | target_include_directories(libmman PUBLIC src/mman-win32) 86 | target_link_libraries(platform_stubs INTERFACE libmman) 87 | 88 | add_library(libgetline STATIC 89 | src/msvc_getline/getline.c) 90 | target_include_directories(libgetline PUBLIC src/msvc_getline) 91 | target_link_libraries(platform_stubs INTERFACE libgetline) 92 | 93 | target_include_directories(android_libbase PRIVATE src/libc-compat/include) 94 | 95 | # libc-compat overrides 96 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--wrap=creat -Wl,--wrap=open -Wl,--wrap=fopen") 97 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--wrap=fdopen -Wl,--wrap=fstat -Wl,--wrap=CreateFileW") 98 | 99 | # Rust STD is directly using these 100 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--wrap=_creat -Wl,--wrap=_open -Wl,--wrap=_fdopen -Wl,--wrap=_fstat64") 101 | 102 | # llvm-mingw uses a different mangling 103 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--wrap=CreateFileW@28") 104 | endif() 105 | 106 | if (EMSCRIPTEN) 107 | message(STATUS "Using Emscripten mmap stubs") 108 | 109 | target_sources(platform_stubs PRIVATE 110 | src/libc-compat/emsup/mmap_hack.c) 111 | 112 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sALLOW_MEMORY_GROWTH -Wl,-u,ntohs -Wl,-u,htons -Wl,-u,htonl") 113 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--wrap=close -Wl,--wrap=fclose") 114 | endif() 115 | 116 | target_link_libraries(libbase platform_stubs) 117 | target_link_libraries(magiskboot_exe platform_stubs) 118 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/link.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #ifndef NDEBUG 11 | # include 12 | #endif 13 | 14 | #define WIN32_LEAN_AND_MEAN 15 | #include 16 | #include 17 | #include 18 | 19 | #include "internal/assert.h" 20 | #include "internal/errno.h" 21 | #include "internal/fd.h" 22 | 23 | #include "../include/winsup/link_compat.h" 24 | 25 | #define LOG_TAG "link_compat" 26 | 27 | #ifndef MIN 28 | # define MIN(a, b) (((a) < (b)) ? (a) : (b)) 29 | #endif 30 | 31 | ssize_t readlink (const char *__restrict path, 32 | char *__restrict buf, size_t len) { 33 | if (!(len > 0)) { 34 | errno = EINVAL; 35 | return -1; 36 | } 37 | 38 | int fd; 39 | 40 | if ((fd = __open_symlink_fd(path, GENERIC_READ, FILE_SHARE_VALID_FLAGS, 0)) < 0) { 41 | __set_errno_via_winerr(GetLastError()); 42 | 43 | return -1; 44 | } 45 | 46 | HANDLE h; 47 | 48 | if ((h = (HANDLE) _get_osfhandle(fd)) == INVALID_HANDLE_VALUE) { 49 | // errno is already set to EBADF by _get_osfhandle 50 | 51 | close(fd); // ownership not transferred 52 | 53 | return -1; 54 | } 55 | 56 | ssize_t ret = -1; 57 | 58 | REPARSE_DATA_BUFFER *buff = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); 59 | 60 | if (!buff) 61 | goto error; 62 | 63 | DWORD bytes; 64 | 65 | if (!DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, buff, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bytes, NULL)) { 66 | __set_errno_via_winerr(GetLastError()); 67 | 68 | #ifndef NDEBUG 69 | perror("DeviceIoControl"); 70 | #endif 71 | 72 | goto error; 73 | } 74 | 75 | if (buff->ReparseTag != IO_REPARSE_TAG_SYMLINK) { 76 | // not a symlink 77 | errno = EINVAL; 78 | goto error; 79 | } 80 | 81 | WCHAR *ws_ptr; 82 | size_t ws_len; 83 | 84 | // From windows-libc: 85 | // https://github.com/SibiSiddharthan/windows-libc/blob/dcb7a2a5889d5bd54e6241dbf6d469114e8a3302/src/unistd/readlink.c#L76-L98 86 | if (buff->SymbolicLinkReparseBuffer.PrintNameLength != 0) { 87 | ws_ptr = (WCHAR *) ((CHAR *) (buff->SymbolicLinkReparseBuffer.PathBuffer) + buff->SymbolicLinkReparseBuffer.PrintNameOffset); 88 | ws_len = buff->SymbolicLinkReparseBuffer.PrintNameLength; 89 | } else if (buff->SymbolicLinkReparseBuffer.SubstituteNameLength != 0) { 90 | ws_ptr = (WCHAR *) ((CHAR *) (buff->SymbolicLinkReparseBuffer.PathBuffer) + buff->SymbolicLinkReparseBuffer.SubstituteNameOffset); 91 | ws_len = buff->SymbolicLinkReparseBuffer.SubstituteNameLength; 92 | } else { 93 | // this should not happen 94 | assert(0); 95 | return -1; // never reached 96 | } 97 | 98 | int chars; 99 | chars = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, 100 | ws_ptr, ws_len + 1, buf, len, NULL, NULL); 101 | if (!chars) { 102 | LOG_ERR("WideCharToMultiByte failed: %s", win_strerror(GetLastError())); 103 | 104 | abort(); 105 | } 106 | 107 | ret = chars - 1; // not including the terminating NULL 108 | 109 | error: 110 | if (h != INVALID_HANDLE_VALUE) 111 | CloseHandle(h); // no need to close fd since handle already owns it 112 | 113 | if (buff) 114 | free(buff); 115 | 116 | return ret; 117 | } 118 | 119 | int link(const char *path1, const char *path2) { 120 | struct stat buf; 121 | 122 | if (stat(path1, &buf) < 0) 123 | return -1; 124 | 125 | if (S_ISDIR(buf.st_mode)) { 126 | errno = EPERM; // not supported 127 | 128 | return -1; 129 | } 130 | 131 | if (!CreateHardLink(path2, path1, NULL)) { 132 | __set_errno_via_winerr(GetLastError()); 133 | 134 | return -1; 135 | } 136 | 137 | return 0; 138 | } 139 | 140 | int symlink (const char *name1, const char *name2) { 141 | /* 142 | * this is not perfect 143 | * 144 | * this doesn't map well to Windows API, 145 | * because it depend on the link type. 146 | * 147 | * a wrong type can make the symlink unusable 148 | * this also applies when the target doesn't exist 149 | * or changes its type after calling symlink 150 | * 151 | * for now we just ignore these 152 | */ 153 | 154 | struct stat buf; 155 | // prefer non-privileged access when possible 156 | DWORD flags = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; 157 | 158 | if (stat(name1, &buf) < 0) 159 | goto not_directory; 160 | 161 | if (S_ISDIR(buf.st_mode)) 162 | flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; 163 | 164 | not_directory: 165 | if (!CreateSymbolicLink(name2, name1, flags)) { 166 | __set_errno_via_winerr(GetLastError()); 167 | 168 | return -1; 169 | } 170 | 171 | return 0; 172 | } 173 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/stat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef NDEBUG 10 | # include 11 | #endif 12 | 13 | #define WIN32_LEAN_AND_MEAN 14 | #include 15 | #include 16 | 17 | #include "../include/winsup/link_compat.h" 18 | #include "../include/winsup/stat_compat.h" 19 | 20 | #include "internal/errno.h" 21 | #include "internal/fd.h" 22 | 23 | #define EXE_SUFFIX (('e' << 2) | ('x' << 1) | 'e') 24 | #define BAT_SUFFIX (('b' << 2) | ('a' << 1) | 't') 25 | #define CMD_SUFFIX (('c' << 2) | ('m' << 1) | 'd') 26 | #define COM_SUFFIX (('c' << 2) | ('o' << 1) | 'm') 27 | 28 | _Static_assert(sizeof(struct stat) == sizeof(struct _stat64), "struct stat is not 64-bit"); 29 | 30 | int __cdecl __wrap_fstat(int fd, struct _stat64 *buf) { 31 | return _fstat64(fd, buf); 32 | } 33 | 34 | int __cdecl __wrap__fstat64(int fd, struct _stat64 *buf) { 35 | // ref: https://github.com/reactos/reactos/blob/455f33077599729c27f1f1347ad2f6329d50d1f3/sdk/lib/crt/stdio/stat64.c 36 | HANDLE h = (HANDLE) _get_osfhandle(fd); 37 | 38 | if (h == INVALID_HANDLE_VALUE) 39 | return -1; // errno is already set to EBADF by _get_osfhandle 40 | 41 | BY_HANDLE_FILE_INFORMATION hfi; 42 | 43 | memset(&hfi, 0, sizeof(hfi)); 44 | 45 | if (!GetFileInformationByHandle(h, &hfi)) { 46 | __set_errno_via_winerr(GetLastError()); 47 | 48 | #ifndef NDEBUG 49 | perror("GetFileInformationByHandle"); 50 | #endif 51 | 52 | return -1; 53 | } 54 | 55 | memset(buf, 0, sizeof(struct stat)); 56 | 57 | char *path = __fd_get_path(fd); 58 | 59 | int ret = -1; 60 | 61 | DWORD type = GetFileType(h); 62 | 63 | if (type == FILE_TYPE_UNKNOWN) { 64 | DWORD winerr = GetLastError(); 65 | 66 | if (winerr == NO_ERROR) { 67 | // IDK if this is the correct way to error handle 68 | errno = ENOENT; 69 | goto error; 70 | } else { 71 | // GetFileType failed 72 | __set_errno_via_winerr(winerr); 73 | 74 | #ifndef NDEBUG 75 | perror("GetFileType"); 76 | #endif 77 | 78 | goto error; 79 | } 80 | } else if (type == FILE_TYPE_CHAR) { 81 | buf->st_mode |= S_IFCHR; 82 | buf->st_dev = buf->st_rdev = fd; 83 | buf->st_nlink = 1; 84 | } else if (type == FILE_TYPE_PIPE) { 85 | buf->st_mode |= S_IFIFO; 86 | buf->st_dev = buf->st_rdev = fd; 87 | buf->st_nlink = 1; 88 | } else { // type == FILE_TYPE_DISK 89 | buf->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH); 90 | 91 | if (hfi.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) 92 | buf->st_mode |= S_IFLNK; 93 | else if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 94 | buf->st_mode |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH); 95 | else { 96 | buf->st_mode |= S_IFREG; 97 | 98 | if (path) { 99 | ssize_t path_len = strlen(path); 100 | 101 | if (path_len >= 4 && path[path_len - 4] == '.') { 102 | int ext = (tolower(path[path_len - 3]) << 2) | (tolower(path[path_len - 2]) << 1) | tolower(path[path_len - 1]); 103 | 104 | if (ext == EXE_SUFFIX || ext == BAT_SUFFIX || ext == CMD_SUFFIX || ext == COM_SUFFIX) 105 | buf->st_mode |= (S_IXUSR | S_IXGRP | S_IXOTH); 106 | } 107 | } 108 | } 109 | 110 | buf->st_nlink = hfi.nNumberOfLinks; 111 | } 112 | 113 | if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) 114 | buf->st_mode |= (S_IWUSR | S_IWGRP | S_IWOTH); 115 | 116 | if (hfi.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { 117 | if (path) { 118 | char path_buf[PATH_MAX]; 119 | ssize_t len = readlink(path, path_buf, PATH_MAX); 120 | 121 | if (len > 0) 122 | buf->st_size = len; 123 | } 124 | } else 125 | buf->st_size = ((__int64) hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow; 126 | 127 | DWORD dw = 0; 128 | 129 | RtlTimeToSecondsSince1970((LARGE_INTEGER *) &hfi.ftLastAccessTime, &dw); 130 | buf->st_atime = dw; 131 | 132 | dw = 0; 133 | 134 | RtlTimeToSecondsSince1970((LARGE_INTEGER *) &hfi.ftLastWriteTime, &dw); 135 | buf->st_mtime = buf->st_ctime = dw; 136 | 137 | // should not close fd or handle after stat 138 | 139 | ret = 0; 140 | 141 | error: 142 | if (path) 143 | free(path); 144 | 145 | return ret; 146 | } 147 | 148 | int lstat (const char *__restrict path, struct stat *__restrict buf) { 149 | int fd = __open_symlink_fd(path, GENERIC_READ, FILE_SHARE_VALID_FLAGS, 0); 150 | 151 | if (fd < 0) { 152 | __set_errno_via_winerr(GetLastError()); 153 | 154 | return -1; 155 | } 156 | 157 | int ret = fstat(fd, buf); 158 | 159 | close(fd); 160 | 161 | return ret; 162 | } 163 | -------------------------------------------------------------------------------- /src/libc-compat/emsup/mmap_hack.c: -------------------------------------------------------------------------------- 1 | // See: 2 | // https://github.com/emscripten-core/emscripten/issues/20459 3 | // 4 | // shared read/write file mapping on Emscripten currently 5 | // requires keeping the original fd open before a call to 6 | // munmap() to sync the changes to the filesystem 7 | // 8 | // so here we wrap around some related functions to delay 9 | // the close() to where munmap() is called 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | struct map_entry { 22 | void *ptr; 23 | size_t len; 24 | int fd; 25 | FILE *fp; 26 | bool have_fp; 27 | bool want_close; 28 | struct map_entry *next; 29 | }; 30 | 31 | // TODO: not thread-safe, add a lock if needed 32 | // (currently magiskboot is a single-threaded program) 33 | static struct map_entry *maps = NULL; 34 | 35 | #define filter_map_by_key_or(_name, _key, _handler, _else) \ 36 | { \ 37 | __attribute__((unused)) struct map_entry *i; \ 38 | __attribute__((unused)) struct map_entry *prev = NULL; \ 39 | bool flag = false; \ 40 | for (i = maps; i; i = i->next) { \ 41 | if (i->_name == _key) { \ 42 | flag = true; \ 43 | _handler; \ 44 | } \ 45 | prev = i; \ 46 | } \ 47 | if (!flag) \ 48 | _else; \ 49 | } 50 | 51 | void *_mmap_stub_impl(void *addr, size_t len, int prot, 52 | int flags, int fildes, off_t off) { 53 | void *ptr = mmap(addr, len, prot, flags, fildes, off); 54 | 55 | if (ptr == MAP_FAILED) 56 | return ptr; 57 | 58 | if (!(fildes < 0) && 59 | (prot & PROT_WRITE) && (flags & MAP_SHARED)) { 60 | // this is the map we are interested in 61 | 62 | struct map_entry *map = malloc(sizeof(struct map_entry)); 63 | 64 | assert(map); 65 | 66 | map->ptr = ptr; 67 | map->len = len; 68 | map->fd = fildes; 69 | map->have_fp = false; // we wouldn't know yet until a call to fclose() 70 | map->want_close = false; 71 | 72 | // add to linked list 73 | map->next = maps; 74 | maps = map; 75 | } 76 | 77 | return ptr; 78 | } 79 | 80 | // close() stub is using ld's --wrap feature 81 | // bcs we must also override its usage in Rust STD 82 | 83 | int __real_close(int fildes); 84 | 85 | int __wrap_close(int fildes) { 86 | if (fcntl(fildes, F_GETFD) < 0) 87 | return -1; // invalid fd 88 | 89 | filter_map_by_key_or(fd, fildes, { 90 | // mark all matches as todo for munmap 91 | i->want_close = true; 92 | }, { 93 | // no match, closing as-is 94 | return __real_close(fildes); 95 | }); 96 | 97 | return 0; 98 | } 99 | 100 | // fclose() is in libc, 101 | // we don't know if it calls close() internally, 102 | // so better way is we also handle it 103 | 104 | int __real_fclose(FILE *stream); 105 | 106 | int __wrap_fclose(FILE *stream) { 107 | int fildes; 108 | 109 | if (!stream) { 110 | // invalid fp 111 | errno = EBADF; 112 | return EOF; 113 | } 114 | 115 | if ((fildes = fileno(stream)) < 0) { 116 | // probably opened by funopen or sth 117 | // not interested 118 | return __real_fclose(stream); 119 | } 120 | 121 | filter_map_by_key_or(fd, fildes, { 122 | // mark all matches as todo for munmap 123 | i->want_close = true; 124 | i->fp = stream; 125 | i->have_fp = true; 126 | }, { 127 | // no match, closing as-is 128 | return __real_fclose(stream); 129 | }); 130 | 131 | // we couldn't close yet, 132 | // but we could try to flush it now 133 | fflush(stream); 134 | 135 | return 0; 136 | } 137 | 138 | static inline void post_munmap_hook(struct map_entry *map, size_t len) { 139 | // we dont support partial munmapping 140 | assert(map->len == len); 141 | 142 | filter_map_by_key_or(fd, map->fd, { 143 | // delay the close until the last file mapping 144 | // associcated with this fd is munmapped 145 | assert(i->want_close); 146 | 147 | break; 148 | }, { 149 | // perform the delayed close 150 | if (map->have_fp) 151 | assert(!__real_fclose(map->fp)); 152 | else 153 | assert(!__real_close(map->fd)); 154 | }); 155 | } 156 | 157 | int _munmap_stub_impl(void *addr, size_t len) { 158 | int res = munmap(addr, len); 159 | 160 | if (res < 0) 161 | return res; 162 | 163 | filter_map_by_key_or(ptr, addr, { 164 | // remove from linked list 165 | if (prev) 166 | prev->next = i->next; 167 | else 168 | maps = i->next; 169 | 170 | if (i->want_close) 171 | post_munmap_hook(i, len); 172 | 173 | free(i); 174 | 175 | break; 176 | }, { 177 | // no match, no action needed 178 | }); 179 | 180 | return res; 181 | } 182 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/dirent.c: -------------------------------------------------------------------------------- 1 | // only used in magiskboot, not including its dependencies 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define WIN32_LEAN_AND_MEAN 14 | #include 15 | 16 | #include "../include/libbsd/str_compat.h" 17 | 18 | #include "../include/winsup/at_compat.h" 19 | #include "../include/winsup/dirent_compat.h" 20 | #include "../include/winsup/stat_compat.h" 21 | 22 | #include "internal/errno.h" 23 | #include "internal/fd.h" 24 | 25 | #ifndef O_PATH 26 | # define O_PATH 0 27 | #endif 28 | 29 | #ifndef MIN 30 | # define MIN(a, b) (((a) < (b)) ? (a) : (b)) 31 | #endif 32 | 33 | _DIR_stub *_opendir_stub (const char *path) { 34 | _DIR_stub *res = NULL; 35 | DIR *real_dirp; 36 | int fd = open(path, O_PATH); 37 | 38 | if (fd < 0) 39 | goto error; 40 | 41 | // no need to check if path is a dir, 42 | // since the real opendir will check it 43 | 44 | if (!(res = malloc(sizeof(_DIR_stub)))) 45 | goto error; 46 | 47 | if (!(real_dirp = opendir(path))) 48 | goto error; 49 | 50 | res->dirp = real_dirp; 51 | res->fd = fd; 52 | 53 | return res; 54 | 55 | error: 56 | if (!(fd < 0)) 57 | close(fd); 58 | 59 | if (res) 60 | free(res); 61 | 62 | // if real_dirp was opened, we shouldn't reach here 63 | 64 | return NULL; 65 | } 66 | 67 | _DIR_stub *fdopendir(int fd) { 68 | _DIR_stub *res = NULL; 69 | DIR *real_dirp; 70 | char *path = NULL; 71 | 72 | if (!__is_dirfd(fd)) 73 | goto error; // errno is already set by this call 74 | 75 | if (!(path = __fd_get_path(fd))) { 76 | __set_errno_via_winerr(GetLastError()); 77 | 78 | goto error; 79 | } 80 | 81 | if (!(res = malloc(sizeof(_DIR_stub)))) 82 | goto error; 83 | 84 | if (!(real_dirp = opendir(path))) 85 | goto error; 86 | 87 | free(path); 88 | 89 | res->dirp = real_dirp; 90 | res->fd = fd; 91 | 92 | return res; 93 | 94 | error: 95 | // real_dirp was not opened 96 | // so the ownership is not transferred 97 | // not closing the fd 98 | 99 | if (path) 100 | free(path); 101 | 102 | if (res) 103 | free(res); 104 | 105 | return NULL; 106 | } 107 | 108 | struct _dirent_stub* _readdir_stub (_DIR_stub* dirp) { 109 | struct dirent *d; 110 | static struct _dirent_stub res; // not thread-safe 111 | struct stat buf; 112 | unsigned char type = DT_UNKNOWN; 113 | 114 | if (!dirp || !dirp->dirp || dirp->fd < 0) { 115 | errno = EBADF; 116 | 117 | return NULL; 118 | } 119 | 120 | if (!(d = readdir(dirp->dirp))) 121 | return NULL; 122 | 123 | // fstatat should not fail 124 | assert(!(fstatat(dirp->fd, d->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0)); 125 | 126 | if (S_ISREG(buf.st_mode)) 127 | type = DT_REG; 128 | else if (S_ISLNK(buf.st_mode)) 129 | type = DT_LNK; 130 | else if (S_ISDIR(buf.st_mode)) 131 | type = DT_DIR; 132 | else if (S_ISFIFO(buf.st_mode)) 133 | type = DT_FIFO; 134 | else if (S_ISSOCK(buf.st_mode)) 135 | type = DT_SOCK; 136 | else if (S_ISBLK(buf.st_mode)) 137 | type = DT_BLK; 138 | else if(S_ISCHR(buf.st_mode)) 139 | type = DT_CHR; 140 | 141 | // clone data 142 | res.d_ino = d->d_ino; 143 | res.d_reclen = d->d_reclen; 144 | res.d_namlen = strlcpy(res.d_name, d->d_name, MIN(sizeof(res.d_name), d->d_namlen)); 145 | res.d_type = type; 146 | 147 | // Windows doesn't care this 148 | // just for emulation 149 | // in case any one try to do sth with it 150 | assert(!lseek(dirp->fd, 1, SEEK_CUR)); 151 | 152 | return &res; 153 | } 154 | 155 | int _closedir_stub (_DIR_stub *dirp) { 156 | // try to free maximum resources 157 | 158 | if (!dirp) { 159 | errno = EBADF; 160 | 161 | return -1; 162 | } 163 | 164 | if (dirp->dirp) 165 | closedir(dirp->dirp); 166 | 167 | if (!(dirp->fd < 0)) 168 | close(dirp->fd); 169 | 170 | free(dirp); 171 | 172 | return 0; 173 | } 174 | 175 | void _rewinddir_stub (_DIR_stub *dirp) { 176 | if (!dirp) // POSIX didn't say to set errno 177 | return; 178 | 179 | if (dirp->dirp) 180 | rewinddir(dirp->dirp); 181 | 182 | if (!(dirp->fd < 0)) 183 | assert(!lseek(dirp->fd, 0, SEEK_SET)); 184 | 185 | return; 186 | } 187 | 188 | long _telldir_stub (_DIR_stub *dirp) { 189 | if (!dirp || !dirp->dirp) { 190 | errno = EBADF; 191 | 192 | return -1; 193 | } 194 | 195 | return telldir(dirp->dirp); 196 | } 197 | 198 | void _seekdir_stub (_DIR_stub *dirp, long loc) { 199 | if (!dirp) // POSIX didn't say to set errno 200 | return; 201 | 202 | if (dirp->dirp) 203 | seekdir(dirp->dirp, loc); 204 | 205 | if (!(dirp->fd < 0)) 206 | assert(!lseek(dirp->fd, loc, SEEK_SET)); 207 | 208 | return; 209 | } 210 | 211 | int dirfd (_DIR_stub* dirp) { 212 | if (!dirp) { 213 | errno = EINVAL; 214 | 215 | return -1; 216 | } 217 | 218 | return dirp->fd; 219 | } 220 | -------------------------------------------------------------------------------- /patches/Magisk/0001-native-fix-header-includes.patch: -------------------------------------------------------------------------------- 1 | From 84df261f5b5cfd5cda74bb02df99495fc873fe81 Mon Sep 17 00:00:00 2001 2 | From: Ookiineko 3 | Date: Thu, 9 Mar 2023 23:29:40 +0800 4 | Subject: [PATCH] native: fix header includes 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | native/src/Cargo.toml | 1 + 9 | native/src/base/files.cpp | 8 ++++++++ 10 | native/src/base/files.hpp | 6 ++++++ 11 | native/src/base/logging.hpp | 4 ++++ 12 | native/src/base/misc.cpp | 17 +++++++++++++++++ 13 | native/src/base/stream.cpp | 3 +++ 14 | native/src/base/xwrap.hpp | 5 +++++ 15 | 7 files changed, 44 insertions(+) 16 | 17 | diff --git a/native/src/Cargo.toml b/native/src/Cargo.toml 18 | index 114b55c..0b6e3c0 100644 19 | --- a/native/src/Cargo.toml 20 | +++ b/native/src/Cargo.toml 21 | @@ -1,12 +1,12 @@ 22 | [workspace] 23 | exclude = ["external"] 24 | -members = ["base", "boot", "core", "init", "sepolicy"] 25 | +members = ["base", "boot"] 26 | resolver = "2" 27 | 28 | [workspace.dependencies] 29 | cxx = { path = "external/cxx-rs" } 30 | cxx-gen = { path = "external/cxx-rs/gen/lib" } 31 | -libc = "0.2" 32 | +libc = { path = "../../../../src/libc-compat/rs" } 33 | cfg-if = "1.0" 34 | num-traits = "0.2" 35 | num-derive = "0.4" 36 | @@ -38,13 +38,5 @@ git = "https://github.com/tafia/quick-protobuf.git" 37 | rev = "2f37d5a65504de7d716b5b28fd82219501a901a9" 38 | 39 | -[profile.dev] 40 | -opt-level = "z" 41 | -lto = true 42 | -codegen-units = 1 43 | -panic = "abort" 44 | 45 | [profile.release] 46 | -opt-level = "z" 47 | -lto = true 48 | codegen-units = 1 49 | -panic = "abort" 50 | 51 | diff --git a/native/src/base/files.cpp b/native/src/base/files.cpp 52 | index 6829de2..8aef651 100644 53 | --- a/native/src/base/files.cpp 54 | +++ b/native/src/base/files.cpp 55 | @@ -1,10 +1,39 @@ 56 | +#ifdef _WIN32 57 | +# include 58 | +#else 59 | #include 60 | +#endif 61 | +#ifdef __linux__ 62 | #include 63 | #include 64 | #include 65 | +#else 66 | +# include 67 | +# if defined(__APPLE__) 68 | +# include 69 | +# endif 70 | +#endif 71 | +#ifndef _WIN32 72 | +# include 73 | +#endif 74 | #include 75 | #include 76 | #include 77 | +#ifdef _WIN32 78 | +# define O_CLOEXEC O_NOINHERIT 79 | + 80 | +# include 81 | +# include 82 | +# include 83 | +# include 84 | +# include 85 | +# include 86 | + 87 | +# define dirent _dirent_stub 88 | +# define getline msvc_getline 89 | +#elif defined(__EMSCRIPTEN__) 90 | +# include 91 | +#endif 92 | 93 | #include 94 | #include 95 | diff --git a/native/src/base/files.hpp b/native/src/base/files.hpp 96 | index 0d8d11c..c4bb952 100644 97 | --- a/native/src/base/files.hpp 98 | +++ b/native/src/base/files.hpp 99 | @@ -6,7 +6,19 @@ 100 | #include 101 | #include 102 | 103 | +#ifdef __linux__ 104 | #include 105 | +#elif defined(__APPLE__) 106 | +# include 107 | +#elif defined(__CYGWIN__) 108 | +# include 109 | +#elif defined(_WIN32) 110 | +# include 111 | + 112 | +# define closedir _closedir_stub 113 | +# define DIR _DIR_stub 114 | +# define opendir _opendir_stub 115 | +#endif 116 | #include "misc.hpp" 117 | 118 | template 119 | diff --git a/native/src/base/misc.cpp b/native/src/base/misc.cpp 120 | index 313d136..f0188b5 100644 121 | --- a/native/src/base/misc.cpp 122 | +++ b/native/src/base/misc.cpp 123 | @@ -1,13 +1,40 @@ 124 | #include 125 | +#ifndef _WIN32 126 | #include 127 | +#endif 128 | +#ifdef __linux__ 129 | #include 130 | #include 131 | +#else 132 | +# include 133 | +#endif 134 | #include 135 | +#ifndef _WIN32 136 | #include 137 | +#endif 138 | #include 139 | +#ifdef __APPLE__ 140 | +# define environ (*_NSGetEnviron()) 141 | + 142 | +# include 143 | +# include 144 | +#endif 145 | +#ifdef __linux__ 146 | #include 147 | +#else 148 | +# include 149 | +# ifndef _WIN32 150 | +# include 151 | +# endif 152 | +#endif 153 | #include 154 | #include 155 | +#ifdef _WIN32 156 | +# include 157 | +#endif 158 | +#ifndef HAVE_STRLCPY 159 | +# include 160 | +#endif 161 | 162 | #include 163 | 164 | diff --git a/native/src/base/xwrap.hpp b/native/src/base/xwrap.hpp 165 | index ce7a6dd..b4ba2c0 100644 166 | --- a/native/src/base/xwrap.hpp 167 | +++ b/native/src/base/xwrap.hpp 168 | @@ -2,8 +2,23 @@ 169 | 170 | #include 171 | #include 172 | +#include // bionic quirks? 173 | +#ifdef _WIN32 174 | +typedef int socklen_t; 175 | +struct msghdr; 176 | +typedef unsigned long int nfds_t; 177 | +struct pollfd; 178 | +#else 179 | +#include // same as above 180 | #include 181 | +#endif 182 | #include 183 | +#ifdef _WIN32 184 | +# include 185 | + 186 | +# define dirent _dirent_stub 187 | +# define DIR _DIR_stub 188 | +#endif 189 | 190 | extern "C" { 191 | 192 | -- 193 | 2.41.0 194 | 195 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.22) 2 | project(magiskboot_build LANGUAGES C) 3 | 4 | # Build-related options 5 | option(WITHOUT_BUILD "Turn this on if you are creating source tarball only" OFF) 6 | 7 | option(TRY_USE_LLD "Prefer LLD for linking when available" ON) 8 | 9 | # Option to enable or disable building static linked version of magiskboot. 10 | # If enabled, the build result will be a standalone binary which you can run 11 | # on any device with the same operating system and architecture. 12 | # This requires installing depended static libraries on the host. 13 | option(PREFER_STATIC_LINKING "Prefer static libraries when linking" OFF) 14 | 15 | # C++ related options 16 | option(WITH_LIBCXX "Link libcxx instead of libstdc++" ON) 17 | 18 | # Rust related options 19 | option(FULL_RUST_LTO "Keep LLVM bitcode in Rust libraries for LTO (requires LLD)" OFF) 20 | set(RUSTFLAGS "" CACHE STRING "extra flags passed to rustc") 21 | set(CARGO_FLAGS "" CACHE STRING "extra flags passed to cargo") 22 | set(RUSTC_BOOTSTRAP "winsup,base,magiskboot" CACHE STRING "") 23 | 24 | # useful for cross-compiling 25 | option(RUST_BUILD_STD "Build Rust standard library" OFF) 26 | 27 | if (NOT WITHOUT_BUILD) 28 | enable_language(CXX) 29 | 30 | set(CMAKE_C_STANDARD 11) 31 | set(CMAKE_C_EXTENSIONS ON) 32 | set(CMAKE_C_STANDARD_REQUIRED ON) 33 | set(CMAKE_CXX_STANDARD 20) 34 | set(CMAKE_CXX_EXTENSIONS ON) 35 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 36 | 37 | include(CheckCXXSourceCompiles) 38 | check_cxx_source_compiles(" 39 | int main () { 40 | struct { int x; } __attribute__ ((packed)) foo = { 1337 }; 41 | [] (int &a) { (void) a; } (foo.x); 42 | } 43 | " CXX_COMPILER_BIND_PACKED_FIELD_WORKS) 44 | 45 | if (NOT CXX_COMPILER_BIND_PACKED_FIELD_WORKS) 46 | message(FATAL_ERROR "Your C++ compiler is not capable of building magiskboot, please check FAQ in README for more details.") 47 | endif() 48 | 49 | if (WITH_LIBCXX) 50 | message(STATUS "Libc++ is enabled") 51 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") 52 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++") 53 | else() 54 | message(STATUS "Libc++ is disabled") 55 | endif() 56 | endif() 57 | 58 | include(CMakeLists.magisk.txt) 59 | include(CMakeLists.patch.txt) 60 | 61 | if (NOT WITHOUT_BUILD) 62 | include(CheckLinkerFlag) 63 | if (TRY_USE_LLD) 64 | check_linker_flag(CXX -fuse-ld=lld FUSE_LD_EQ_LLD_WORKS) 65 | 66 | # prefer LLD when it is available 67 | if (FUSE_LD_EQ_LLD_WORKS) 68 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld") 69 | set(CMAKE_REQUIRED_LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS} -fuse-ld=lld) 70 | endif() 71 | endif() 72 | 73 | include(CMakeLists.compat.txt) 74 | 75 | find_package(PkgConfig REQUIRED) 76 | if (PREFER_STATIC_LINKING) 77 | message(STATUS "Static/standalone build") 78 | list(INSERT CMAKE_FIND_LIBRARY_PREFIXES 0 ${CMAKE_STATIC_LIBRARY_PREFIX}) 79 | list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 ${CMAKE_STATIC_LIBRARY_SUFFIX}) 80 | list(APPEND PKG_CONFIG_EXECUTABLE "--static") 81 | include(CheckLinkerFlag) 82 | check_linker_flag(CXX -static STATIC_LINK_WORKS) 83 | if (STATIC_LINK_WORKS) 84 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") 85 | endif() 86 | check_linker_flag(CXX -static-libgcc STATIC_LIBGCC_LINK_WORKS) 87 | if (STATIC_LIBGCC_LINK_WORKS) 88 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc") 89 | endif() 90 | check_linker_flag(CXX -static-libstdc++ STATIC_LIBSTDCXX_LINK_WORKS) 91 | if (STATIC_LIBSTDCXX_LINK_WORKS) 92 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++") 93 | endif() 94 | else() 95 | message(STATUS "Dynamic build") 96 | endif() 97 | 98 | set(THREADS_PREFER_PTHREAD_FLAG ON) 99 | find_package(Threads REQUIRED) 100 | find_package(LibLZMA REQUIRED) 101 | pkg_check_modules(liblz4 REQUIRED IMPORTED_TARGET liblz4) 102 | find_package(BZip2 REQUIRED) 103 | find_package(ZLIB REQUIRED) 104 | 105 | add_compile_options(-Wall) 106 | 107 | include(CMakeLists.rust.txt) 108 | include(CMakeLists.magiskboot.txt) 109 | 110 | if (CMAKE_BUILD_TYPE MATCHES "Debug") 111 | set_target_properties(magiskboot_exe PROPERTIES OUTPUT_NAME "magiskboot_debug") 112 | message(STATUS "Debug (unoptimized) build") 113 | else() 114 | set_target_properties(magiskboot_exe PROPERTIES OUTPUT_NAME "magiskboot") 115 | message(STATUS "Release (optimized) build") 116 | endif() 117 | 118 | include(CMakeLists.stub.txt) 119 | endif() 120 | 121 | # CPack configuration for creating source tarballs which already include 122 | # patched versions of the vendored dependencies. 123 | set(CPACK_SOURCE_GENERATOR "TXZ") 124 | set(CPACK_SOURCE_PACKAGE_FILE_NAME "magiskboot_${MAGISK_VERSION}_${MAGISK_VER_CODE}-src") 125 | set(CPACK_SOURCE_IGNORE_FILES "/patches/" "/build/" "/.git/" "/src/Magisk/app/" 126 | "/src/Magisk/buildSrc/" "/src/Magisk/docs/" "/src/Magisk/gradle/" 127 | "/src/Magisk/scripts/" "/src/Magisk/stub/" "/src/Magisk/tools/ndk-bins" 128 | "\\\\.so$" "\\\\.dll$" "\\\\.zip$" "\\\\.orig" "\\\\.rej" "\\\\.tar$" 129 | "\\\\.tar\\\\..*$" "\\\\.tgz$" "\\\\.data$" "aes_128_gcm.txt" "aes_256_gcm.txt") 130 | include(CPack) 131 | -------------------------------------------------------------------------------- /patches/android_logging/0003-fix-__INTRODUCED_IN-attributes-for-Termux.patch: -------------------------------------------------------------------------------- 1 | From 198d805d596fe0aa61e556690cbfa692bb7db812 Mon Sep 17 00:00:00 2001 2 | From: Ian Hu 3 | Date: Fri, 29 Oct 2021 14:52:25 +0800 4 | Subject: [PATCH] fix __INTRODUCED_IN attributes for Termux 5 | 6 | Signed-off-by: Ookiineko 7 | --- 8 | liblog/include/android/log.h | 24 ++++++++++++------------ 9 | 1 file changed, 12 insertions(+), 12 deletions(-) 10 | 11 | diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h 12 | index 12de595..6742aa9 100644 13 | --- a/liblog/include/android/log.h 14 | +++ b/liblog/include/android/log.h 15 | @@ -229,7 +229,7 @@ typedef void (*__android_aborter_function)(const char* abort_message); 16 | * 17 | * Available since API level 30. 18 | */ 19 | -void __android_log_write_log_message(struct __android_log_message* log_message) __INTRODUCED_IN(30); 20 | +void __android_log_write_log_message(struct __android_log_message* log_message) __INTRODUCED_IN(24); 21 | 22 | /** 23 | * Sets a user defined logger function. All log messages sent to liblog will be set to the 24 | @@ -241,7 +241,7 @@ void __android_log_write_log_message(struct __android_log_message* log_message) 25 | * 26 | * Available since API level 30. 27 | */ 28 | -void __android_log_set_logger(__android_logger_function logger) __INTRODUCED_IN(30); 29 | +void __android_log_set_logger(__android_logger_function logger) __INTRODUCED_IN(24); 30 | 31 | /** 32 | * Writes the log message to logd. This is an __android_logger_function and can be provided to 33 | @@ -251,7 +251,7 @@ void __android_log_set_logger(__android_logger_function logger) __INTRODUCED_IN( 34 | * 35 | * Available since API level 30. 36 | */ 37 | -void __android_log_logd_logger(const struct __android_log_message* log_message) __INTRODUCED_IN(30); 38 | +void __android_log_logd_logger(const struct __android_log_message* log_message) __INTRODUCED_IN(24); 39 | 40 | /** 41 | * Writes the log message to stderr. This is an __android_logger_function and can be provided to 42 | @@ -262,7 +262,7 @@ void __android_log_logd_logger(const struct __android_log_message* log_message) 43 | * Available since API level 30. 44 | */ 45 | void __android_log_stderr_logger(const struct __android_log_message* log_message) 46 | - __INTRODUCED_IN(30); 47 | + __INTRODUCED_IN(24); 48 | 49 | /** 50 | * Sets a user defined aborter function that is called for __android_log_assert() failures. This 51 | @@ -273,7 +273,7 @@ void __android_log_stderr_logger(const struct __android_log_message* log_message 52 | * 53 | * Available since API level 30. 54 | */ 55 | -void __android_log_set_aborter(__android_aborter_function aborter) __INTRODUCED_IN(30); 56 | +void __android_log_set_aborter(__android_aborter_function aborter) __INTRODUCED_IN(24); 57 | 58 | /** 59 | * Calls the stored aborter function. This allows for other logging libraries to use the same 60 | @@ -284,7 +284,7 @@ void __android_log_set_aborter(__android_aborter_function aborter) __INTRODUCED_ 61 | * 62 | * Available since API level 30. 63 | */ 64 | -void __android_log_call_aborter(const char* abort_message) __INTRODUCED_IN(30); 65 | +void __android_log_call_aborter(const char* abort_message) __INTRODUCED_IN(24); 66 | 67 | /** 68 | * Sets android_set_abort_message() on device then aborts(). This is the default aborter. 69 | @@ -295,7 +295,7 @@ void __android_log_call_aborter(const char* abort_message) __INTRODUCED_IN(30); 70 | * Available since API level 30. 71 | */ 72 | void __android_log_default_aborter(const char* abort_message) __attribute__((noreturn)) 73 | -__INTRODUCED_IN(30); 74 | +__INTRODUCED_IN(24); 75 | 76 | /** 77 | * Use the per-tag properties "log.tag." along with the minimum priority from 78 | @@ -314,7 +314,7 @@ __INTRODUCED_IN(30); 79 | * 80 | * Available since API level 30. 81 | */ 82 | -int __android_log_is_loggable(int prio, const char* tag, int default_prio) __INTRODUCED_IN(30); 83 | +int __android_log_is_loggable(int prio, const char* tag, int default_prio) __INTRODUCED_IN(24); 84 | 85 | /** 86 | * Use the per-tag properties "log.tag." along with the minimum priority from 87 | @@ -335,7 +335,7 @@ int __android_log_is_loggable(int prio, const char* tag, int default_prio) __INT 88 | * Available since API level 30. 89 | */ 90 | int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio) 91 | - __INTRODUCED_IN(30); 92 | + __INTRODUCED_IN(24); 93 | 94 | /** 95 | * Sets the minimum priority that will be logged for this process. 96 | @@ -346,7 +346,7 @@ int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int def 97 | * 98 | * Available since API level 30. 99 | */ 100 | -int32_t __android_log_set_minimum_priority(int32_t priority) __INTRODUCED_IN(30); 101 | +int32_t __android_log_set_minimum_priority(int32_t priority) __INTRODUCED_IN(24); 102 | 103 | /** 104 | * Gets the minimum priority that will be logged for this process. If none has been set by a 105 | @@ -357,7 +357,7 @@ int32_t __android_log_set_minimum_priority(int32_t priority) __INTRODUCED_IN(30) 106 | * 107 | * Available since API level 30. 108 | */ 109 | -int32_t __android_log_get_minimum_priority(void) __INTRODUCED_IN(30); 110 | +int32_t __android_log_get_minimum_priority(void) __INTRODUCED_IN(24); 111 | 112 | /** 113 | * Sets the default tag if no tag is provided when writing a log message. Defaults to 114 | @@ -368,7 +368,7 @@ int32_t __android_log_get_minimum_priority(void) __INTRODUCED_IN(30); 115 | * 116 | * Available since API level 30. 117 | */ 118 | -void __android_log_set_default_tag(const char* tag) __INTRODUCED_IN(30); 119 | +void __android_log_set_default_tag(const char* tag) __INTRODUCED_IN(24); 120 | 121 | #ifdef __cplusplus 122 | } 123 | -- 124 | 2.39.2 125 | 126 | -------------------------------------------------------------------------------- /patches/android_logging/0001-Don-t-use-the-internal-glibc-header-sys-cdefs.h.patch: -------------------------------------------------------------------------------- 1 | From 71ea766e0a45c4082e49962009342958b2c764e1 Mon Sep 17 00:00:00 2001 2 | From: John Zimmermann 3 | Date: Thu, 18 Mar 2021 15:08:33 +0100 4 | Subject: [PATCH] Don't use the internal glibc header sys/cdefs.h 5 | 6 | --- 7 | liblog/include/android/log.h | 1 - 8 | liblog/include/log/log_main.h | 9 ++++++--- 9 | liblog/logd_reader.h | 9 ++++++--- 10 | liblog/logger.h | 9 ++++++--- 11 | liblog/pmsg_reader.h | 9 ++++++--- 12 | logcat/logcat.cpp | 1 - 13 | logcat/tests/logcat_test.cpp | 1 - 14 | logd/ChattyLogBuffer.cpp | 1 - 15 | logd/LogListener.cpp | 1 - 16 | logd/LogUtils.h | 1 - 17 | logd/libaudit.h | 9 ++++++--- 18 | 11 files changed, 30 insertions(+), 21 deletions(-) 19 | 20 | diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h 21 | index 5dc365a4..12de5958 100644 22 | --- a/liblog/include/android/log.h 23 | +++ b/liblog/include/android/log.h 24 | @@ -57,7 +57,6 @@ 25 | #include 26 | #include 27 | #include 28 | -#include 29 | 30 | #if !defined(__BIONIC__) && !defined(__INTRODUCED_IN) 31 | #define __INTRODUCED_IN(x) 32 | diff --git a/liblog/include/log/log_main.h b/liblog/include/log/log_main.h 33 | index 1bd1c8ae..c71bbdd4 100644 34 | --- a/liblog/include/log/log_main.h 35 | +++ b/liblog/include/log/log_main.h 36 | @@ -17,12 +17,13 @@ 37 | #pragma once 38 | 39 | #include 40 | -#include 41 | #include 42 | 43 | #include 44 | 45 | -__BEGIN_DECLS 46 | +#ifdef __cplusplus 47 | +extern "C" { 48 | +#endif 49 | 50 | /* 51 | * Normally we strip the effects of ALOGV (VERBOSE messages), 52 | @@ -377,4 +378,6 @@ int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int def 53 | #pragma clang diagnostic pop 54 | #endif 55 | 56 | -__END_DECLS 57 | +#ifdef __cplusplus 58 | +} 59 | +#endif 60 | diff --git a/liblog/logd_reader.h b/liblog/logd_reader.h 61 | index 68eef027..64e400ff 100644 62 | --- a/liblog/logd_reader.h 63 | +++ b/liblog/logd_reader.h 64 | @@ -16,16 +16,19 @@ 65 | 66 | #pragma once 67 | 68 | -#include 69 | #include 70 | 71 | #include "log/log_read.h" 72 | 73 | -__BEGIN_DECLS 74 | +#ifdef __cplusplus 75 | +extern "C" { 76 | +#endif 77 | 78 | int LogdRead(struct logger_list* logger_list, struct log_msg* log_msg); 79 | void LogdClose(struct logger_list* logger_list); 80 | 81 | ssize_t SendLogdControlMessage(char* buf, size_t buf_size); 82 | 83 | -__END_DECLS 84 | +#ifdef __cplusplus 85 | +} 86 | +#endif 87 | diff --git a/liblog/logger.h b/liblog/logger.h 88 | index ddff19dd..263859db 100644 89 | --- a/liblog/logger.h 90 | +++ b/liblog/logger.h 91 | @@ -17,13 +17,14 @@ 92 | #pragma once 93 | 94 | #include 95 | -#include 96 | 97 | #include 98 | 99 | #include "uio.h" 100 | 101 | -__BEGIN_DECLS 102 | +#ifdef __cplusplus 103 | +extern "C" { 104 | +#endif 105 | 106 | struct logger_list { 107 | atomic_int fd; 108 | @@ -48,4 +49,6 @@ inline bool android_logger_is_logd(struct logger* logger) { 109 | return reinterpret_cast(logger) & LOGGER_LOGD; 110 | } 111 | 112 | -__END_DECLS 113 | +#ifdef __cplusplus 114 | +} 115 | +#endif 116 | diff --git a/liblog/pmsg_reader.h b/liblog/pmsg_reader.h 117 | index b784f9ff..88aeec9c 100644 118 | --- a/liblog/pmsg_reader.h 119 | +++ b/liblog/pmsg_reader.h 120 | @@ -16,14 +16,17 @@ 121 | 122 | #pragma once 123 | 124 | -#include 125 | #include 126 | 127 | #include "log/log_read.h" 128 | 129 | -__BEGIN_DECLS 130 | +#ifdef __cplusplus 131 | +extern "C" { 132 | +#endif 133 | 134 | int PmsgRead(struct logger_list* logger_list, struct log_msg* log_msg); 135 | void PmsgClose(struct logger_list* logger_list); 136 | 137 | -__END_DECLS 138 | +#ifdef __cplusplus 139 | +} 140 | +#endif 141 | diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp 142 | index 084003e7..9eecf737 100644 143 | --- a/logcat/logcat.cpp 144 | +++ b/logcat/logcat.cpp 145 | @@ -26,7 +26,6 @@ 146 | #include 147 | #include 148 | #include 149 | -#include 150 | #include 151 | #include 152 | #include 153 | diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp 154 | index b835bd5a..25cb94c5 100644 155 | --- a/logcat/tests/logcat_test.cpp 156 | +++ b/logcat/tests/logcat_test.cpp 157 | @@ -22,7 +22,6 @@ 158 | #include 159 | #include 160 | #include 161 | -#include 162 | #include 163 | #include 164 | #include 165 | diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp 166 | index a6ab50b8..641def0f 100644 167 | --- a/logd/LogListener.cpp 168 | +++ b/logd/LogListener.cpp 169 | @@ -15,7 +15,6 @@ 170 | */ 171 | 172 | #include 173 | -#include 174 | #include 175 | #include 176 | #include 177 | diff --git a/logd/LogUtils.h b/logd/LogUtils.h 178 | index c0f62d39..5c759793 100644 179 | --- a/logd/LogUtils.h 180 | +++ b/logd/LogUtils.h 181 | @@ -16,7 +16,6 @@ 182 | 183 | #pragma once 184 | 185 | -#include 186 | #include 187 | 188 | #include 189 | diff --git a/logd/libaudit.h b/logd/libaudit.h 190 | index 27b08669..872d6996 100644 191 | --- a/logd/libaudit.h 192 | +++ b/logd/libaudit.h 193 | @@ -20,14 +20,15 @@ 194 | #pragma once 195 | 196 | #include 197 | -#include 198 | #include 199 | #include 200 | 201 | #include 202 | #include 203 | 204 | -__BEGIN_DECLS 205 | +#ifdef __cplusplus 206 | +extern "C" { 207 | +#endif 208 | 209 | #define MAX_AUDIT_MESSAGE_LENGTH 8970 210 | 211 | @@ -100,4 +101,6 @@ extern int audit_setup(int fd, pid_t pid); 212 | */ 213 | extern int audit_rate_limit(int fd, uint32_t limit); 214 | 215 | -__END_DECLS 216 | +#ifdef __cplusplus 217 | +} 218 | +#endif 219 | -------------------------------------------------------------------------------- /src/libc-compat/winsup/internal/fd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define WIN32_LEAN_AND_MEAN 12 | #include 13 | #include 14 | 15 | #include "errno.h" 16 | 17 | #include "fd.h" 18 | 19 | #ifndef NDEBUG 20 | # include "assert.h" 21 | 22 | # define LOG_TAG "fd_internal" 23 | #endif 24 | 25 | #ifndef OPEN_MAX 26 | # ifndef _UCRT 27 | // this value can be found in Windows SDK source 28 | # define OPEN_MAX (8192) 29 | # else 30 | // Origin: https://github.com/reactos/reactos/blob/f889c29af691e0e956c8d3bae08f7b647c9ff643/sdk/lib/crt/stdio/file.c#L111-L112 31 | # define OPEN_MAX (2048) 32 | # endif 33 | #endif 34 | 35 | struct fd_cache_entry { 36 | int oflag; 37 | }; 38 | 39 | // TODO: not thread-safe, add a lock if needed 40 | // (currently magiskboot is a sinelg-threaded program) 41 | static struct fd_cache_entry fd_cache[OPEN_MAX]; 42 | 43 | static size_t fd_cache_max_size = 0; 44 | 45 | char *__fd_get_path(int fd) { 46 | HANDLE h = (HANDLE) _get_osfhandle(fd); 47 | 48 | if (h == INVALID_HANDLE_VALUE) { 49 | SetLastError(ERROR_INVALID_HANDLE); 50 | return NULL; 51 | } 52 | 53 | char *buf = malloc(PATH_MAX); 54 | 55 | if (!buf) 56 | return NULL; 57 | 58 | if (!GetFinalPathNameByHandle(h, buf, PATH_MAX, 0)) { 59 | #ifndef NDEBUG 60 | LOG_ERR("GetFinalPathNameByHandle failed: %s", win_strerror(GetLastError())); 61 | #endif 62 | free(buf); 63 | 64 | return NULL; 65 | } 66 | 67 | size_t buf_len = strlen(buf); 68 | size_t path_len; 69 | 70 | if (!strncmp(buf, "\\\\?\\UNC\\", 8)) { 71 | path_len = buf_len - 8; 72 | memmove(buf + 2, buf + 8, path_len); 73 | buf[path_len + 2] = '\0'; 74 | } else if (!strncmp(buf, "\\\\?\\", 4)) { 75 | path_len = buf_len - 4; 76 | memmove(buf, buf + 4, path_len); 77 | buf[path_len] = '\0'; 78 | } 79 | 80 | return buf; 81 | } 82 | 83 | int __open_dir_fd(const char *path, DWORD access, DWORD share_mode, int flags) { 84 | HANDLE h; 85 | int fd; 86 | 87 | if ((h = CreateFile(path, access, share_mode, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)) == INVALID_HANDLE_VALUE) 88 | return -1; 89 | 90 | if ((fd = _open_osfhandle((intptr_t) h, flags)) < 0) { 91 | #ifndef NDEBUG 92 | LOG_ERR("_open_osfhandle failed"); 93 | #endif 94 | SetLastError(ERROR_INVALID_PARAMETER); // EINVAL 95 | 96 | CloseHandle(h); 97 | 98 | return -1; 99 | } 100 | 101 | // don't close the original handle, the ownership is transferred to the fd 102 | 103 | return fd; 104 | } 105 | 106 | int __open_symlink_fd(const char *path, DWORD access, DWORD share_mode, int flags) { 107 | HANDLE h; 108 | int fd; 109 | 110 | if ((h = CreateFile(path, access, share_mode, NULL, OPEN_EXISTING, 111 | FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL)) == INVALID_HANDLE_VALUE) 112 | return -1; 113 | 114 | if ((fd = _open_osfhandle((intptr_t) h, flags)) < 0) { 115 | #ifndef NDEBUG 116 | LOG_ERR("_open_osfhandle failed"); 117 | #endif 118 | SetLastError(ERROR_INVALID_PARAMETER); // EINVAL 119 | 120 | CloseHandle(h); 121 | 122 | return -1; 123 | } 124 | 125 | // don't close the original handle, the ownership is transferred to the fd 126 | 127 | return fd; 128 | } 129 | 130 | bool __is_dirfd(int fd) { 131 | struct stat buf; 132 | 133 | if (fstat(fd, &buf) < 0) 134 | goto not; // errno is set by fstat 135 | 136 | if (S_ISDIR(buf.st_mode)) 137 | return true; 138 | 139 | not: 140 | errno = ENOTDIR; 141 | return false; 142 | } 143 | 144 | char *__get_path_at(int dirfd, const char *name) { 145 | if (!__is_dirfd(dirfd)) 146 | return NULL; // errno is set by this call 147 | 148 | char *parent = __fd_get_path(dirfd); 149 | 150 | if (!parent) { 151 | __set_errno_via_winerr(GetLastError()); 152 | 153 | return NULL; 154 | } 155 | 156 | char *buff = NULL; 157 | 158 | if ((strlen(parent) + 1 + strlen(name)) > PATH_MAX) { 159 | errno = ENAMETOOLONG; 160 | 161 | goto exit; 162 | } 163 | 164 | buff = malloc(PATH_MAX + 1); 165 | 166 | if (!buff) 167 | goto exit; 168 | 169 | snprintf(buff, PATH_MAX + 1, "%s/%s", parent, name); 170 | 171 | exit: 172 | if (parent) 173 | free(parent); 174 | 175 | return buff; 176 | } 177 | 178 | static int __get_osfhandle_oflag_fallback(HANDLE h) { 179 | OBJECT_BASIC_INFORMATION obi; 180 | 181 | NTSTATUS status = NtQueryObject(h, ObjectBasicInformation, &obi, sizeof(obi), NULL); 182 | 183 | if (!NT_SUCCESS(status)) { 184 | #ifndef NDEBUG 185 | LOG_ERR("NtQueryObject failed: %s", win_strerror(RtlNtStatusToDosError(status))); 186 | #endif 187 | 188 | return 0; 189 | } 190 | 191 | // Ref: https://github.com/rust-lang/rust/blob/32f5db98909de7bfb23cad3a48f740b99a19b01c/library/std/src/sys/windows/fs.rs#L245-L248 192 | 193 | if (obi.GrantedAccess & FILE_WRITE_DATA) 194 | return 0; // not append mode 195 | 196 | return (obi.GrantedAccess & FILE_APPEND_DATA) ? O_APPEND : 0; 197 | } 198 | 199 | int __get_osfhandle_oflag(HANDLE h) { 200 | int fd; 201 | int oflag; 202 | HANDLE other; 203 | 204 | if (h == INVALID_HANDLE_VALUE) 205 | return 0; 206 | 207 | for (fd = 0; fd < fd_cache_max_size; fd++) { 208 | if ((oflag = fd_cache[fd].oflag) < 0) 209 | continue; // not cached, check next one 210 | 211 | if ((other = (HANDLE) _get_osfhandle(fd)) == INVALID_HANDLE_VALUE) { 212 | // cache is outdated, fd is already closed 213 | 214 | fd_cache[fd].oflag = -1; 215 | 216 | if (fd == (fd_cache_max_size - 1)) 217 | fd_cache_max_size--; 218 | 219 | continue; 220 | } 221 | 222 | if (h == other) 223 | return oflag; 224 | } 225 | 226 | // not cached, maybe handle opened from Rust with no fd associcated 227 | 228 | return __get_osfhandle_oflag_fallback(h); 229 | } 230 | 231 | void __fd_cache_oflag(int fd, int oflag) { 232 | assert(!(fd < 0)); 233 | assert(fd < OPEN_MAX); 234 | 235 | fd_cache[fd].oflag = oflag & O_APPEND; // only O_APPEND is useful for opened handle 236 | 237 | if (fd_cache_max_size <= fd) 238 | fd_cache_max_size = fd + 1; 239 | } 240 | 241 | __attribute__((constructor)) static void __init_oflag_cache(void) { 242 | int fd; 243 | 244 | for (fd = 0; fd < OPEN_MAX; fd++) 245 | fd_cache[fd].oflag = -1; 246 | } 247 | -------------------------------------------------------------------------------- /src/libc-compat/rs/windows/stubs.rs: -------------------------------------------------------------------------------- 1 | use core::{clone::Clone, marker::Copy}; 2 | 3 | // dirent 4 | 5 | // there is an additional d_type field 6 | // compared to the original MinGW dirent 7 | 8 | s_no_extra_traits! { 9 | pub struct dirent { 10 | pub d_ino: crate::c_long, 11 | pub d_type: crate::c_uchar, 12 | pub d_reclen: crate::c_ushort, 13 | pub d_namlen: crate::c_ushort, 14 | pub d_name: [crate::c_char; 260], 15 | } 16 | } 17 | 18 | pub const DT_REG: u8 = 1; 19 | pub const DT_LNK: u8 = 2; 20 | pub const DT_DIR: u8 = 3; 21 | pub const DT_FIFO: u8 = 4; 22 | pub const DT_SOCK: u8 = 5; 23 | pub const DT_BLK: u8 = 6; 24 | pub const DT_CHR: u8 = 7; 25 | 26 | // replace the MinGW impls bcs we've modified dirent struct and added dir fd support 27 | 28 | pub enum DIR {} 29 | impl Copy for DIR {} 30 | impl Clone for DIR { 31 | fn clone(&self) -> DIR { 32 | *self 33 | } 34 | } 35 | 36 | extern "C" { 37 | #[link_name = "_opendir_stub"] 38 | pub fn opendir(dirname: *const crate::c_char) -> *mut DIR; 39 | 40 | #[link_name = "_readdir_stub"] 41 | pub fn readdir(dirp: *mut DIR) -> *mut crate::dirent; 42 | 43 | #[link_name = "_rewinddir_stub"] 44 | pub fn rewinddir(dirp: *mut DIR); 45 | 46 | #[link_name = "_closedir_stub"] 47 | pub fn closedir(dirp: *mut DIR) -> crate::c_int; 48 | } 49 | 50 | extern "C" { 51 | pub fn fdopendir(fd: crate::c_int) -> *mut DIR; 52 | pub fn dirfd(dirp: *mut DIR) -> crate::c_int; 53 | } 54 | 55 | // fcntl 56 | 57 | pub const O_CLOEXEC: crate::c_int = crate::O_NOINHERIT; 58 | 59 | // link 60 | 61 | extern "C" { 62 | pub fn link(src: *const crate::c_char, dst: *const crate::c_char) -> crate::c_int; 63 | pub fn readlink(path: *const crate::c_char, buf: *mut crate::c_char, bufsz: crate::size_t) -> crate::ssize_t; 64 | pub fn symlink(path1: *const crate::c_char, path2: *const crate::c_char) -> crate::c_int; 65 | } 66 | 67 | // at 68 | 69 | pub const AT_REMOVEDIR: crate::c_int = 1; 70 | pub const AT_SYMLINK_NOFOLLOW: crate::c_int = 2; 71 | 72 | extern "C" { 73 | pub fn readlinkat(dirfd: crate::c_int, 74 | pathname: *const crate::c_char, 75 | buf: *mut crate::c_char, 76 | bufsiz: crate::size_t) -> crate::ssize_t; 77 | pub fn symlinkat( 78 | target: *const crate::c_char, 79 | newdirfd: crate::c_int, 80 | linkpath: *const crate::c_char, 81 | ) -> crate::c_int; 82 | pub fn linkat( 83 | olddirfd: crate::c_int, 84 | oldpath: *const crate::c_char, 85 | newdirfd: crate::c_int, 86 | newpath: *const crate::c_char, 87 | flags: crate::c_int, 88 | ) -> crate::c_int; 89 | pub fn unlinkat(dirfd: crate::c_int, pathname: *const crate::c_char, flags: crate::c_int) -> crate::c_int; 90 | pub fn openat(dirfd: crate::c_int, pathname: *const crate::c_char, 91 | flags: crate::c_int, ...) -> crate::c_int; 92 | pub fn faccessat( 93 | dirfd: crate::c_int, 94 | pathname: *const crate::c_char, 95 | mode: crate::c_int, 96 | flags: crate::c_int, 97 | ) -> crate::c_int; 98 | pub fn fstatat( 99 | dirfd: crate::c_int, 100 | pathname: *const crate::c_char, 101 | buf: *mut crate::stat, 102 | flags: crate::c_int, 103 | ) -> crate::c_int; 104 | pub fn mkdirat(dirfd: crate::c_int, pathname: *const crate::c_char, 105 | mode: crate::mode_t) -> crate::c_int; 106 | pub fn renameat( 107 | olddirfd: crate::c_int, 108 | oldpath: *const crate::c_char, 109 | newdirfd: crate::c_int, 110 | newpath: *const crate::c_char, 111 | ) -> crate::c_int; 112 | } 113 | 114 | // mman 115 | 116 | extern "C" { 117 | #[link_name = "mmap"] 118 | fn real_mmap( 119 | addr: *mut crate::c_void, 120 | len: crate::size_t, 121 | prot: crate::c_int, 122 | flags: crate::c_int, 123 | fd: crate::c_int, 124 | offset: crate::c_longlong, 125 | ) -> *mut crate::c_void; 126 | pub fn munmap(addr: *mut crate::c_void, len: crate::size_t) -> crate::c_int; 127 | } 128 | 129 | pub fn mmap( 130 | addr: *mut crate::c_void, 131 | len: crate::size_t, 132 | prot: crate::c_int, 133 | flags: crate::c_int, 134 | fd: crate::c_int, 135 | offset: crate::off_t, 136 | ) -> *mut crate::c_void { 137 | unsafe { real_mmap(addr, len, prot, flags, fd, offset as crate::c_longlong) } 138 | } 139 | 140 | pub const MAP_SHARED: crate::c_int = 1; 141 | pub const MAP_PRIVATE: crate::c_int = 2; 142 | pub const MAP_FAILED: *mut crate::c_void = !0 as *mut crate::c_void; 143 | pub const PROT_READ: crate::c_int = 1; 144 | pub const PROT_WRITE: crate::c_int = 2; 145 | 146 | // mknod 147 | 148 | extern "C" { 149 | pub fn mknod(pathname: *const crate::c_char, mode: crate::mode_t, dev: crate::dev_t) -> crate::c_int; 150 | } 151 | 152 | f! { 153 | pub fn major(dev: crate::dev_t) -> crate::c_int { 154 | ((dev >> 16) & 0xffff) as crate::c_int 155 | } 156 | 157 | pub fn minor(dev: crate::dev_t) -> crate::c_int { 158 | (dev & 0xffff) as crate::c_int 159 | } 160 | } 161 | 162 | safe_f! { 163 | pub {const} fn makedev(ma: crate::c_int, mi: crate::c_int) -> crate::dev_t { 164 | let ma = ma as crate::dev_t; 165 | let mi = mi as crate::dev_t; 166 | (ma << 16) | (mi & 0xffff) 167 | } 168 | } 169 | 170 | // stat 171 | 172 | pub const S_IFBLK: crate::mode_t = 12288; 173 | pub const S_IFLNK: crate::mode_t = 24576; 174 | pub const S_IFSOCK: crate::mode_t = 49152; 175 | pub const S_IFIFO: crate::mode_t = 4096; 176 | 177 | extern "C" { 178 | pub fn lstat(path: *const crate::c_char, buf: *mut crate::stat) -> crate::c_int; 179 | } 180 | 181 | pub const S_IRGRP: crate::mode_t = 32; 182 | pub const S_IROTH: crate::mode_t = 4; 183 | pub const S_IRUSR: crate::mode_t = 256; 184 | pub const S_IWOTH: crate::mode_t = 2; 185 | pub const S_IWGRP: crate::mode_t = 16; 186 | pub const S_IWUSR: crate::mode_t = 128; 187 | pub const S_IXGRP: crate::mode_t = 8; 188 | pub const S_IXOTH: crate::mode_t = 1; 189 | pub const S_IXUSR: crate::mode_t = 64; 190 | 191 | // poll 192 | 193 | pub type nfds_t = crate::c_ulong; 194 | 195 | pub enum pollfd {} 196 | impl Copy for pollfd {} 197 | impl Clone for pollfd { 198 | fn clone(&self) -> pollfd { 199 | *self 200 | } 201 | } 202 | 203 | // winsock 204 | 205 | pub type socklen_t = crate::c_int; 206 | 207 | // acl 208 | 209 | extern "C" { 210 | pub fn lchown(path: *const crate::c_char, uid: crate::uid_t, gid: crate::gid_t) -> crate::c_int; 211 | pub fn fchmod(fd: crate::c_int, mode: crate::mode_t) -> crate::c_int; 212 | pub fn fchown(fd: crate::c_int, owner: crate::uid_t, group: crate::gid_t) -> crate::c_int; 213 | } 214 | 215 | // string 216 | 217 | extern "C" { 218 | pub fn memmem( 219 | haystack: *const crate::c_void, 220 | haystacklen: crate::size_t, 221 | needle: *const crate::c_void, 222 | needlelen: crate::size_t, 223 | ) -> *mut crate::c_void; 224 | } 225 | -------------------------------------------------------------------------------- /scripts/magiskboot_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # a very shitty bash script for testing basic functionalities of magiskboot 5 | # 6 | # dependencies: coreutils, file, wget, xxd 7 | # 8 | 9 | # fail fast 10 | set -e 11 | set -o pipefail 12 | 13 | if [ "$#" -ne 1 -o ! -f "$1" ]; then 14 | echo "Usage: $0 " 15 | exit 1 16 | fi 17 | 18 | if [[ "$1" == *.js ]]; then 19 | magiskboot="node $(realpath $1)" 20 | elif [[ ! -z "${EMULATOR}" ]]; then 21 | magiskboot="$EMULATOR $(realpath $1)" 22 | else 23 | magiskboot="$(realpath $1)" 24 | fi 25 | echo -e "\n### magiskboot binary: $1 ###\n" 26 | file $1 27 | 28 | __workspace="$(mktemp -d -t magiskboot_test.XXXXXXXXXX)" 29 | echo -e "\n### created temporary working directory: ${__workspace} ###\n" 30 | cd "${__workspace}" 31 | cleanup() { 32 | if [ -d "${__workspace}" ]; then 33 | cd ${TMPDIR:-/tmp} 34 | (rm -rf "${__workspace}" && echo -e "\n### removed working directory: ${__workspace} ###\n") || true 35 | fi 36 | } 37 | trap cleanup EXIT 38 | 39 | mkdir -pv tmp 40 | 41 | # prepare image files for test 42 | echo -e "\n### downloading test images ###\n" 43 | # TODO: add more image with different header version and update method 44 | set -x 45 | wget -nv https://github.com/dandelion64-Archives/redmi_dandelion_dump/raw/dandelion-user-11-RP1A.200720.011-V12.5.11.0.RCZMIXM-release-keys/boot.img.aa 46 | wget -nv https://github.com/dandelion64-Archives/redmi_dandelion_dump/raw/dandelion-user-11-RP1A.200720.011-V12.5.11.0.RCZMIXM-release-keys/boot.img.ab 47 | cat boot.img.aa boot.img.ab > boot.img 48 | set +x 49 | rm -vf boot.img.aa boot.img.ab 50 | file boot.img 51 | 52 | # check the downloaded image 53 | sha512sum -c - << EOF 54 | 3b3b47a3ff94344c2ad8423fe9f90d1f3df77a9e2bd0b945e8b8c28015290aeb717d53d9c82abd96e9ceeafc982ff26a0e131d6820e54a753b55a07ce1016f5b boot.img 55 | EOF 56 | 57 | # test: unpack 58 | echo -e "\n### testing unpack ###\n" 59 | set -x; $magiskboot unpack -n -h boot.img; set +x 60 | file dtb header kernel ramdisk.cpio 61 | 62 | # verify: unpack 63 | check_results() { 64 | sha512sum -c - << EOF 65 | 0cd76b98aa1f55558bebd2cf1b58cdda15bdc4daaad2031e8191e5df9c8283259a071c32adcbb3dda32cb51ee2071d3acf19a6f79421142568a88a4997655abe dtb 66 | 7aa1841bce0ff7ffba254f98c49dcbfefdbe6f3fe6ee86b1303fcee46234007c250ee8e3b36522f799fa3a1383398d2c6a04e7b6348c1788b58279ede823cf3a header 67 | f6bb3d1340accc23a6db7e74c311d81c6e0dd41da757ccd12c6095a20104314fb8413d3a0498bf141c1830bb9763c3897e4431379a6f88232dc283047e9c4a25 kernel 68 | 2bb406bf7665535cc8571205ea933113cdb7e7bf85e9f0773e2810c0ccc20e030729c82659d4b12564df70bf6c2dd46b4c30e833afbf4525ab60ad5b3dad50ea ramdisk.cpio 69 | EOF 70 | } 71 | check_results 72 | 73 | # test: repack 74 | echo -e "\n### testing repack ###\n" 75 | set -x; $magiskboot repack boot.img tmp/new.img; set +x 76 | file tmp/new.img 77 | 78 | # verify: repack 79 | pushd tmp 80 | set -x; $magiskboot unpack -n -h new.img 2> /dev/null; set +x 81 | check_results 82 | popd 83 | 84 | # test: compress & decompress 85 | if [[ "$OSTYPE" == "darwin"* ]]; then 86 | set -x; dd if=/dev/urandom of=kitten bs=1m count=8; set +x 87 | else 88 | set -x; dd if=/dev/urandom of=kitten bs=1M count=8; set +x 89 | fi 90 | __randfile_checksum="$(sha512sum kitten)" 91 | compress_kitten() { 92 | # compress and capture console output 93 | local __conout="$((set -x; $magiskboot compress=$1 kitten 2>&1; set +x) | tee >(cat >&2))" 94 | # find out the output archive name 95 | if grep -E -q 'Compressing to \[(.*)\]' <<< "${__conout}"; then 96 | # extract and return the output archive name 97 | sed -nE 's/Compressing to \[(.*)\]/\1/p' <<< "${__conout}" 98 | return 0 99 | fi 100 | 101 | # maybe some error occurred 102 | return 1 103 | } 104 | check_kitten() { 105 | file kitten 106 | sha512sum -c - <<< "${__randfile_checksum}" 107 | } 108 | check_kitten 109 | for __method in gzip zopfli xz lzma bzip2 lz4 lz4_legacy lz4_lg; do 110 | echo -e "\n### testing ${__method} compression & decompression ###\n" 111 | 112 | __out="$(compress_kitten ${__method})" 113 | file "${__out}" 114 | rm -vf kitten 115 | set -x; $magiskboot decompress "${__out}"; set +x 116 | rm -vf "${__out}" 117 | check_kitten 118 | done 119 | 120 | # test: cpio ls 121 | echo -e "\n### testing cpio ls ###\n" 122 | cat > expected_out.txt << EOF 123 | drwxr-xr-x 0 0 0 B 0:0 avb 124 | drwxr-xr-x 0 0 0 B 0:0 debug_ramdisk 125 | drwxr-xr-x 0 0 0 B 0:0 dev 126 | -rw-r----- 0 0 4.57 KB 0:0 fstab.mt6762 127 | -rw-r----- 0 0 4.57 KB 0:0 fstab.mt6765 128 | -rwxr-x--- 0 0 1.29 MB 0:0 init 129 | drwxr-xr-x 0 0 0 B 0:0 mnt 130 | drwxr-xr-x 0 0 0 B 0:0 proc 131 | drwxr-xr-x 0 0 0 B 0:0 sys 132 | -rw-r--r-- 0 0 524 B 0:0 verity_key 133 | EOF 134 | set -x 135 | $magiskboot cleanup 2> /dev/null 136 | $magiskboot unpack boot.img 2> /dev/null 137 | $magiskboot cpio ramdisk.cpio 'ls' | tee out.txt 138 | diff -u out.txt expected_out.txt 139 | set +x 140 | 141 | # test: cpio add 142 | echo -e "\n### testing cpio add ###\n" 143 | set -x 144 | echo 'Hello, world!' > foo 145 | $magiskboot cpio ramdisk.cpio 'add 644 bar foo' 146 | $magiskboot cpio ramdisk.cpio 'ls bar' | grep -E '\-rw-r--r--\s0\s0\s14 B\s0:0\sbar' 147 | set +x 148 | 149 | # TODO: add tests for more cpio sub-commands 150 | 151 | # test: cpio extract 152 | echo -e "\n### testing cpio extract ###\n" 153 | cat > expected.list << EOF 154 | ext 155 | ext/avb 156 | ext/avb/q-gsi.avbpubkey 157 | ext/avb/r-gsi.avbpubkey 158 | ext/avb/s-gsi.avbpubkey 159 | ext/debug_ramdisk 160 | ext/dev 161 | ext/fstab.mt6762 162 | ext/fstab.mt6765 163 | ext/init 164 | ext/mnt 165 | ext/proc 166 | ext/sys 167 | ext/verity_key 168 | EOF 169 | set -x 170 | $magiskboot cleanup 2> /dev/null 171 | $magiskboot unpack boot.img 2> /dev/null 172 | set +x 173 | mkdir -pv ext && pushd ext 174 | set -x; $magiskboot cpio ../ramdisk.cpio 'extract'; set +x 175 | popd 176 | set -x 177 | find ext | sort > list.txt 178 | diff -u list.txt expected.list 179 | set +x 180 | sha512sum -c - << EOF 181 | ad623b7c491250d8cd001b1c0c07eced9fb79d68e1f208c3556d4d476349e7354c1cef58a27e1ee31fab02cc4f1929b86d04c979b6ac02b61d3c4ca0d3005894 ext/avb/q-gsi.avbpubkey 182 | 060f8a0173b53a133499c46fc0237fa24938fd7bfb3aa39b658a18efe0da826e3f0c8cf16c2691ef8a29990a0ed0344ed72164f8acf556ef3598bb944ce4ca6f ext/avb/r-gsi.avbpubkey 183 | 1afb924f33cc62067166f2ab75a6345228fc448250b32f1fe34c2eec247301b1a3761cf1043c456b3979ad4b63df34232b133ae371b36046e5cd20136e1eab2a ext/avb/s-gsi.avbpubkey 184 | d070818df28c1f8614c8289c43b066fb9f630cb1e21628ca989980ab4838d3d45cc063a2461f1b6916ee2bdbe1d33f43297eaa9b60582b41d5f737c738f66b91 ext/fstab.mt6762 185 | d070818df28c1f8614c8289c43b066fb9f630cb1e21628ca989980ab4838d3d45cc063a2461f1b6916ee2bdbe1d33f43297eaa9b60582b41d5f737c738f66b91 ext/fstab.mt6765 186 | bc461ed94a3d1298d4d6ad310904d1b2e8ba705c2f3ad751d76454109cc7c69f951d33a72eff7f4f0e9e08e053c0fc9335dd6a87f06790098b752a0a3d42a321 ext/init 187 | 103c552f302d6d62d4b3973defc80f43eaf10d57dd32cb419f1f8384c4e805032d01aba32d7a2fe8d3e21ab0cd77818f6ecbdb3d0bc2e1d705c2a292d3021b20 ext/verity_key 188 | EOF 189 | 190 | # test: hexpatch 191 | echo -e "\n### testing hexpatch ###\n" 192 | set -x; echo -ne '\xb0\x00\xba\xca\xfe\xd0\x0d' > test.bin; set +x 193 | file test.bin 194 | xxd test.bin 195 | set -x; $magiskboot hexpatch test.bin cafe badd; set +x 196 | file test.bin 197 | xxd test.bin 198 | set -x 199 | echo -ne '\xb0\x00\xba\xba\xdd\xd0\x0d' > expected.bin 200 | diff test.bin expected.bin 201 | set +x 202 | 203 | # TODO: add test for payload.bin extraction 204 | 205 | # test: dtb 206 | echo -e "\n### testing dtb ###\n" 207 | set -x; $magiskboot dtb dtb test; set +x 208 | # TODO: add test for dtb patch 209 | 210 | # TODO: add test for AVB related functions 211 | 212 | # test: sha1 213 | echo -e "\n### testing sha1 ###\n" 214 | __randfile_sha1="$(sha1sum kitten | cut -d ' ' -f 1 | tee >(cat >&2))" 215 | set -x; ($magiskboot sha1 kitten | grep "${__randfile_sha1}"); set +x 216 | --------------------------------------------------------------------------------