mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-03 00:19:30 +02:00
Remove C++ I/O streams
This commit is contained in:
parent
78d1200608
commit
dc0acea47c
@ -18,7 +18,6 @@ LOCAL_SRC_FILES := \
|
||||
files.cpp \
|
||||
misc.cpp \
|
||||
logging.cpp \
|
||||
stream.cpp \
|
||||
base-rs.cpp \
|
||||
../external/cxx-rs/src/cxx.cc
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
@ -1,129 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <sys/uio.h>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
|
||||
#include "../files.hpp"
|
||||
|
||||
#define ENABLE_IOV 0
|
||||
|
||||
struct out_stream {
|
||||
virtual bool write(const void *buf, size_t len) = 0;
|
||||
#if ENABLE_IOV
|
||||
virtual ssize_t writev(const iovec *iov, int iovcnt);
|
||||
#endif
|
||||
virtual ~out_stream() = default;
|
||||
};
|
||||
|
||||
using out_strm_ptr = std::unique_ptr<out_stream>;
|
||||
|
||||
// Delegates all operations to base stream
|
||||
class filter_out_stream : public out_stream {
|
||||
public:
|
||||
filter_out_stream(out_strm_ptr &&base) : base(std::move(base)) {}
|
||||
bool write(const void *buf, size_t len) override;
|
||||
protected:
|
||||
out_strm_ptr base;
|
||||
};
|
||||
|
||||
// Buffered output stream, writing in chunks
|
||||
class chunk_out_stream : public filter_out_stream {
|
||||
public:
|
||||
chunk_out_stream(out_strm_ptr &&base, size_t buf_sz, size_t chunk_sz)
|
||||
: filter_out_stream(std::move(base)), chunk_sz(chunk_sz), data(buf_sz) {}
|
||||
|
||||
chunk_out_stream(out_strm_ptr &&base, size_t buf_sz = 4096)
|
||||
: chunk_out_stream(std::move(base), buf_sz, buf_sz) {}
|
||||
|
||||
bool write(const void *buf, size_t len) final;
|
||||
|
||||
protected:
|
||||
// Classes inheriting this class has to call finalize() in its destructor
|
||||
void finalize();
|
||||
virtual bool write_chunk(const void *buf, size_t len, bool final);
|
||||
|
||||
size_t chunk_sz;
|
||||
|
||||
private:
|
||||
size_t buf_off = 0;
|
||||
heap_data data;
|
||||
};
|
||||
|
||||
struct in_stream {
|
||||
virtual ssize_t read(void *buf, size_t len) = 0;
|
||||
ssize_t readFully(void *buf, size_t len);
|
||||
#if ENABLE_IOV
|
||||
virtual ssize_t readv(const iovec *iov, int iovcnt);
|
||||
#endif
|
||||
virtual ~in_stream() = default;
|
||||
};
|
||||
|
||||
// A stream is something that is writable and readable
|
||||
struct stream : public out_stream, public in_stream {};
|
||||
|
||||
using stream_ptr = std::unique_ptr<stream>;
|
||||
|
||||
// Byte stream that dynamically allocates memory
|
||||
class byte_stream : public stream {
|
||||
public:
|
||||
byte_stream(heap_data &data) : _data(data) {}
|
||||
|
||||
ssize_t read(void *buf, size_t len) override;
|
||||
bool write(const void *buf, size_t len) override;
|
||||
|
||||
private:
|
||||
heap_data &_data;
|
||||
size_t _pos = 0;
|
||||
size_t _cap = 0;
|
||||
|
||||
void resize(size_t new_sz, bool zero = false);
|
||||
};
|
||||
|
||||
class rust_vec_stream : public stream {
|
||||
public:
|
||||
rust_vec_stream(rust::Vec<uint8_t> &data) : _data(data) {}
|
||||
|
||||
ssize_t read(void *buf, size_t len) override;
|
||||
bool write(const void *buf, size_t len) override;
|
||||
|
||||
private:
|
||||
rust::Vec<uint8_t> &_data;
|
||||
size_t _pos = 0;
|
||||
|
||||
void ensure_size(size_t sz, bool zero = false);
|
||||
};
|
||||
|
||||
class file_stream : public stream {
|
||||
public:
|
||||
bool write(const void *buf, size_t len) final;
|
||||
protected:
|
||||
virtual ssize_t do_write(const void *buf, size_t len) = 0;
|
||||
};
|
||||
|
||||
// File stream but does not close the file descriptor at any time
|
||||
class fd_stream : public file_stream {
|
||||
public:
|
||||
fd_stream(int fd) : fd(fd) {}
|
||||
ssize_t read(void *buf, size_t len) override;
|
||||
#if ENABLE_IOV
|
||||
ssize_t readv(const iovec *iov, int iovcnt) override;
|
||||
ssize_t writev(const iovec *iov, int iovcnt) override;
|
||||
#endif
|
||||
protected:
|
||||
ssize_t do_write(const void *buf, size_t len) override;
|
||||
private:
|
||||
int fd;
|
||||
};
|
||||
|
||||
/* ****************************************
|
||||
* Bridge between stream class and C stdio
|
||||
* ****************************************/
|
||||
|
||||
// stream_ptr -> sFILE
|
||||
sFILE make_stream_fp(stream_ptr &&strm);
|
||||
|
||||
template <class T, class... Args>
|
||||
sFILE make_stream_fp(Args &&... args) {
|
||||
return make_stream_fp(stream_ptr(new T(std::forward<Args>(args)...)));
|
||||
}
|
@ -58,7 +58,6 @@ pub mod ffi {
|
||||
fn set_log_level_state_cxx(level: LogLevelCxx, enabled: bool);
|
||||
fn exit_on_error(b: bool);
|
||||
fn cmdline_logging();
|
||||
fn resize_vec(vec: &mut Vec<u8>, size: usize);
|
||||
}
|
||||
|
||||
#[namespace = "rust"]
|
||||
@ -80,12 +79,3 @@ fn set_log_level_state_cxx(level: ffi::LogLevelCxx, enabled: bool) {
|
||||
set_log_level_state(level, enabled)
|
||||
}
|
||||
}
|
||||
|
||||
fn resize_vec(vec: &mut Vec<u8>, size: usize) {
|
||||
if size > vec.len() {
|
||||
vec.reserve(size - vec.len());
|
||||
}
|
||||
unsafe {
|
||||
vec.set_len(size);
|
||||
}
|
||||
}
|
||||
|
@ -147,17 +147,12 @@ struct byte_data : public byte_view {
|
||||
rust::Vec<size_t> patch(byte_view from, byte_view to);
|
||||
};
|
||||
|
||||
class byte_stream;
|
||||
|
||||
struct heap_data : public byte_data {
|
||||
ALLOW_MOVE_ONLY(heap_data)
|
||||
|
||||
heap_data() = default;
|
||||
explicit heap_data(size_t sz) : byte_data(calloc(sz, 1), sz) {}
|
||||
~heap_data() { free(_buf); }
|
||||
|
||||
// byte_stream needs to reallocate the internal buffer
|
||||
friend byte_stream;
|
||||
};
|
||||
|
||||
struct owned_fd {
|
||||
|
@ -1,201 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <cstddef>
|
||||
|
||||
#include <base.hpp>
|
||||
#include <stream.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static int strm_read(void *v, char *buf, int len) {
|
||||
auto strm = static_cast<stream *>(v);
|
||||
return strm->read(buf, len);
|
||||
}
|
||||
|
||||
static int strm_write(void *v, const char *buf, int len) {
|
||||
auto strm = static_cast<stream *>(v);
|
||||
if (!strm->write(buf, len))
|
||||
return -1;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int strm_close(void *v) {
|
||||
auto strm = static_cast<stream *>(v);
|
||||
delete strm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sFILE make_stream_fp(stream_ptr &&strm) {
|
||||
auto fp = make_file(funopen(strm.release(), strm_read, strm_write, nullptr, strm_close));
|
||||
setbuf(fp.get(), nullptr);
|
||||
return fp;
|
||||
}
|
||||
|
||||
ssize_t in_stream::readFully(void *buf, size_t len) {
|
||||
size_t read_sz = 0;
|
||||
ssize_t ret;
|
||||
do {
|
||||
ret = read((byte *) buf + read_sz, len - read_sz);
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return ret;
|
||||
}
|
||||
read_sz += ret;
|
||||
} while (read_sz != len && ret != 0);
|
||||
return read_sz;
|
||||
}
|
||||
|
||||
bool filter_out_stream::write(const void *buf, size_t len) {
|
||||
return base->write(buf, len);
|
||||
}
|
||||
|
||||
bool chunk_out_stream::write(const void *_in, size_t len) {
|
||||
auto in = static_cast<const uint8_t *>(_in);
|
||||
while (len) {
|
||||
if (buf_off + len >= chunk_sz) {
|
||||
// Enough input for a chunk
|
||||
const uint8_t *src;
|
||||
if (buf_off) {
|
||||
src = data.buf();
|
||||
auto copy = chunk_sz - buf_off;
|
||||
memcpy(data.buf() + buf_off, in, copy);
|
||||
in += copy;
|
||||
len -= copy;
|
||||
buf_off = 0;
|
||||
} else {
|
||||
src = in;
|
||||
in += chunk_sz;
|
||||
len -= chunk_sz;
|
||||
}
|
||||
if (!write_chunk(src, chunk_sz, false))
|
||||
return false;
|
||||
} else {
|
||||
// Buffer internally
|
||||
memcpy(data.buf() + buf_off, in, len);
|
||||
buf_off += len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool chunk_out_stream::write_chunk(const void *buf, size_t len, bool) {
|
||||
return base->write(buf, len);
|
||||
}
|
||||
|
||||
void chunk_out_stream::finalize() {
|
||||
if (buf_off) {
|
||||
if (!write_chunk(data.buf(), buf_off, true)) {
|
||||
LOGE("Error in finalize, file truncated\n");
|
||||
}
|
||||
buf_off = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t byte_stream::read(void *buf, size_t len) {
|
||||
len = std::min((size_t) len, _data._sz- _pos);
|
||||
memcpy(buf, _data.buf() + _pos, len);
|
||||
_pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
bool byte_stream::write(const void *buf, size_t len) {
|
||||
resize(_pos + len);
|
||||
memcpy(_data.buf() + _pos, buf, len);
|
||||
_pos += len;
|
||||
_data._sz= std::max(_data.sz(), _pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
void byte_stream::resize(size_t new_sz, bool zero) {
|
||||
bool resize = false;
|
||||
size_t old_cap = _cap;
|
||||
while (new_sz > _cap) {
|
||||
_cap = _cap ? (_cap << 1) - (_cap >> 1) : 1 << 12;
|
||||
resize = true;
|
||||
}
|
||||
if (resize) {
|
||||
_data._buf = static_cast<uint8_t *>(::realloc(_data._buf, _cap));
|
||||
if (zero)
|
||||
memset(_data.buf() + old_cap, 0, _cap - old_cap);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t rust_vec_stream::read(void *buf, size_t len) {
|
||||
len = std::min<size_t>(len, _data.size() - _pos);
|
||||
memcpy(buf, _data.data() + _pos, len);
|
||||
_pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
bool rust_vec_stream::write(const void *buf, size_t len) {
|
||||
ensure_size(_pos + len);
|
||||
memcpy(_data.data() + _pos, buf, len);
|
||||
_pos += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
void rust_vec_stream::ensure_size(size_t sz, bool zero) {
|
||||
size_t old_sz = _data.size();
|
||||
if (sz > old_sz) {
|
||||
resize_vec(_data, sz);
|
||||
if (zero)
|
||||
memset(_data.data() + old_sz, 0, sz - old_sz);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t fd_stream::read(void *buf, size_t len) {
|
||||
return ::read(fd, buf, len);
|
||||
}
|
||||
|
||||
ssize_t fd_stream::do_write(const void *buf, size_t len) {
|
||||
return ::write(fd, buf, len);
|
||||
}
|
||||
|
||||
bool file_stream::write(const void *buf, size_t len) {
|
||||
size_t write_sz = 0;
|
||||
ssize_t ret;
|
||||
do {
|
||||
ret = do_write((byte *) buf + write_sz, len - write_sz);
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
write_sz += ret;
|
||||
} while (write_sz != len && ret != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if ENABLE_IOV
|
||||
|
||||
ssize_t in_stream::readv(const iovec *iov, int iovcnt) {
|
||||
size_t read_sz = 0;
|
||||
for (int i = 0; i < iovcnt; ++i) {
|
||||
auto ret = readFully(iov[i].iov_base, iov[i].iov_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
read_sz += ret;
|
||||
}
|
||||
return read_sz;
|
||||
}
|
||||
|
||||
ssize_t out_stream::writev(const iovec *iov, int iovcnt) {
|
||||
size_t write_sz = 0;
|
||||
for (int i = 0; i < iovcnt; ++i) {
|
||||
if (!write(iov[i].iov_base, iov[i].iov_len))
|
||||
return write_sz;
|
||||
write_sz += iov[i].iov_len;
|
||||
}
|
||||
return write_sz;
|
||||
}
|
||||
|
||||
ssize_t fd_stream::readv(const iovec *iov, int iovcnt) {
|
||||
return ::readv(fd, iov, iovcnt);
|
||||
}
|
||||
|
||||
ssize_t fd_stream::writev(const iovec *iov, int iovcnt) {
|
||||
return ::writev(fd, iov, iovcnt);
|
||||
}
|
||||
|
||||
#endif // ENABLE_IOV
|
@ -10,7 +10,6 @@
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <base.hpp>
|
||||
#include <stream.hpp>
|
||||
#include <sepolicy.hpp>
|
||||
|
||||
#include "init-rs.hpp"
|
||||
|
@ -17,7 +17,7 @@ static vector<string> rc_list;
|
||||
#define NEW_INITRC_DIR "/system/etc/init/hw"
|
||||
#define INIT_RC "init.rc"
|
||||
|
||||
static bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes) {
|
||||
static bool unxz(int fd, rust::Slice<const uint8_t> bytes) {
|
||||
uint8_t out[8192];
|
||||
xz_crc32_init();
|
||||
size_t size = bytes.size();
|
||||
@ -36,7 +36,7 @@ static bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes) {
|
||||
ret = xz_dec_run(dec, &b);
|
||||
if (ret != XZ_OK && ret != XZ_STREAM_END)
|
||||
return false;
|
||||
strm.write(out, b.out_pos);
|
||||
write(fd, out, b.out_pos);
|
||||
b.out_pos = 0;
|
||||
} while (b.in_pos != size);
|
||||
return true;
|
||||
@ -241,24 +241,21 @@ static void extract_files(bool sbin) {
|
||||
mmap_data magisk(magisk_xz);
|
||||
unlink(magisk_xz);
|
||||
int fd = xopen("magisk", O_WRONLY | O_CREAT, 0755);
|
||||
fd_stream ch(fd);
|
||||
unxz(ch, magisk);
|
||||
unxz(fd, magisk);
|
||||
close(fd);
|
||||
}
|
||||
if (access(stub_xz, F_OK) == 0) {
|
||||
mmap_data stub(stub_xz);
|
||||
unlink(stub_xz);
|
||||
int fd = xopen("stub.apk", O_WRONLY | O_CREAT, 0);
|
||||
fd_stream ch(fd);
|
||||
unxz(ch, stub);
|
||||
unxz(fd, stub);
|
||||
close(fd);
|
||||
}
|
||||
if (access(init_ld_xz, F_OK) == 0) {
|
||||
mmap_data init_ld(init_ld_xz);
|
||||
unlink(init_ld_xz);
|
||||
int fd = xopen("init-ld", O_WRONLY | O_CREAT, 0);
|
||||
fd_stream ch(fd);
|
||||
unxz(ch, init_ld);
|
||||
unxz(fd, init_ld);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
@ -407,8 +404,7 @@ int magisk_proxy_main(int, char *argv[]) {
|
||||
static void unxz_init(const char *init_xz, const char *init) {
|
||||
LOGD("unxz %s -> %s\n", init_xz, init);
|
||||
int fd = xopen(init, O_WRONLY | O_CREAT, 0777);
|
||||
fd_stream ch(fd);
|
||||
unxz(ch, mmap_data{init_xz});
|
||||
unxz(fd, mmap_data{init_xz});
|
||||
close(fd);
|
||||
clone_attr(init_xz, init);
|
||||
unlink(init_xz);
|
||||
|
@ -8,8 +8,8 @@
|
||||
#include <cil/cil.h>
|
||||
|
||||
#include <base.hpp>
|
||||
#include <stream.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define SHALEN 64
|
||||
static bool cmp_sha256(const char *a, const char *b) {
|
||||
@ -230,20 +230,29 @@ sepol_impl::~sepol_impl() {
|
||||
free(db);
|
||||
}
|
||||
|
||||
static int vec_write(void *v, const char *buf, int len) {
|
||||
auto vec = static_cast<vector<char> *>(v);
|
||||
vec->insert(vec->end(), buf, buf + len);
|
||||
return len;
|
||||
}
|
||||
|
||||
bool SePolicy::to_file(::rust::Utf8CStr file) const noexcept {
|
||||
// No partial writes are allowed to /sys/fs/selinux/load, thus the reason why we
|
||||
// first dump everything into memory, then directly call write system call
|
||||
heap_data data;
|
||||
auto fp = make_stream_fp<byte_stream>(data);
|
||||
vector<char> out;
|
||||
FILE *fp = funopen(&out, nullptr, vec_write, nullptr, nullptr);
|
||||
// Since we're directly writing to memory, disable buffering
|
||||
setbuf(fp, nullptr);
|
||||
|
||||
policy_file_t pf;
|
||||
policy_file_init(&pf);
|
||||
pf.type = PF_USE_STDIO;
|
||||
pf.fp = fp.get();
|
||||
pf.fp = fp;
|
||||
if (policydb_write(impl->db, &pf)) {
|
||||
LOGE("Fail to create policy image\n");
|
||||
return false;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
int fd = xopen(file.data(), O_WRONLY | O_CREAT | O_CLOEXEC, 0644);
|
||||
if (fd < 0)
|
||||
@ -251,7 +260,7 @@ bool SePolicy::to_file(::rust::Utf8CStr file) const noexcept {
|
||||
if (struct stat st{}; xfstat(fd, &st) == 0 && st.st_size > 0) {
|
||||
ftruncate(fd, 0);
|
||||
}
|
||||
xwrite(fd, data.buf(), data.sz());
|
||||
xwrite(fd, out.data(), out.size());
|
||||
|
||||
close(fd);
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user