mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-04 17:09:28 +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 \
|
files.cpp \
|
||||||
misc.cpp \
|
misc.cpp \
|
||||||
logging.cpp \
|
logging.cpp \
|
||||||
stream.cpp \
|
|
||||||
base-rs.cpp \
|
base-rs.cpp \
|
||||||
../external/cxx-rs/src/cxx.cc
|
../external/cxx-rs/src/cxx.cc
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
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 set_log_level_state_cxx(level: LogLevelCxx, enabled: bool);
|
||||||
fn exit_on_error(b: bool);
|
fn exit_on_error(b: bool);
|
||||||
fn cmdline_logging();
|
fn cmdline_logging();
|
||||||
fn resize_vec(vec: &mut Vec<u8>, size: usize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[namespace = "rust"]
|
#[namespace = "rust"]
|
||||||
@ -80,12 +79,3 @@ fn set_log_level_state_cxx(level: ffi::LogLevelCxx, enabled: bool) {
|
|||||||
set_log_level_state(level, enabled)
|
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);
|
rust::Vec<size_t> patch(byte_view from, byte_view to);
|
||||||
};
|
};
|
||||||
|
|
||||||
class byte_stream;
|
|
||||||
|
|
||||||
struct heap_data : public byte_data {
|
struct heap_data : public byte_data {
|
||||||
ALLOW_MOVE_ONLY(heap_data)
|
ALLOW_MOVE_ONLY(heap_data)
|
||||||
|
|
||||||
heap_data() = default;
|
heap_data() = default;
|
||||||
explicit heap_data(size_t sz) : byte_data(calloc(sz, 1), sz) {}
|
explicit heap_data(size_t sz) : byte_data(calloc(sz, 1), sz) {}
|
||||||
~heap_data() { free(_buf); }
|
~heap_data() { free(_buf); }
|
||||||
|
|
||||||
// byte_stream needs to reallocate the internal buffer
|
|
||||||
friend byte_stream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct owned_fd {
|
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
|
#ifdef __cplusplus
|
||||||
|
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
#include <stream.hpp>
|
|
||||||
#include <sepolicy.hpp>
|
#include <sepolicy.hpp>
|
||||||
|
|
||||||
#include "init-rs.hpp"
|
#include "init-rs.hpp"
|
||||||
|
@ -17,7 +17,7 @@ static vector<string> rc_list;
|
|||||||
#define NEW_INITRC_DIR "/system/etc/init/hw"
|
#define NEW_INITRC_DIR "/system/etc/init/hw"
|
||||||
#define INIT_RC "init.rc"
|
#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];
|
uint8_t out[8192];
|
||||||
xz_crc32_init();
|
xz_crc32_init();
|
||||||
size_t size = bytes.size();
|
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);
|
ret = xz_dec_run(dec, &b);
|
||||||
if (ret != XZ_OK && ret != XZ_STREAM_END)
|
if (ret != XZ_OK && ret != XZ_STREAM_END)
|
||||||
return false;
|
return false;
|
||||||
strm.write(out, b.out_pos);
|
write(fd, out, b.out_pos);
|
||||||
b.out_pos = 0;
|
b.out_pos = 0;
|
||||||
} while (b.in_pos != size);
|
} while (b.in_pos != size);
|
||||||
return true;
|
return true;
|
||||||
@ -241,24 +241,21 @@ static void extract_files(bool sbin) {
|
|||||||
mmap_data magisk(magisk_xz);
|
mmap_data magisk(magisk_xz);
|
||||||
unlink(magisk_xz);
|
unlink(magisk_xz);
|
||||||
int fd = xopen("magisk", O_WRONLY | O_CREAT, 0755);
|
int fd = xopen("magisk", O_WRONLY | O_CREAT, 0755);
|
||||||
fd_stream ch(fd);
|
unxz(fd, magisk);
|
||||||
unxz(ch, magisk);
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
if (access(stub_xz, F_OK) == 0) {
|
if (access(stub_xz, F_OK) == 0) {
|
||||||
mmap_data stub(stub_xz);
|
mmap_data stub(stub_xz);
|
||||||
unlink(stub_xz);
|
unlink(stub_xz);
|
||||||
int fd = xopen("stub.apk", O_WRONLY | O_CREAT, 0);
|
int fd = xopen("stub.apk", O_WRONLY | O_CREAT, 0);
|
||||||
fd_stream ch(fd);
|
unxz(fd, stub);
|
||||||
unxz(ch, stub);
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
if (access(init_ld_xz, F_OK) == 0) {
|
if (access(init_ld_xz, F_OK) == 0) {
|
||||||
mmap_data init_ld(init_ld_xz);
|
mmap_data init_ld(init_ld_xz);
|
||||||
unlink(init_ld_xz);
|
unlink(init_ld_xz);
|
||||||
int fd = xopen("init-ld", O_WRONLY | O_CREAT, 0);
|
int fd = xopen("init-ld", O_WRONLY | O_CREAT, 0);
|
||||||
fd_stream ch(fd);
|
unxz(fd, init_ld);
|
||||||
unxz(ch, init_ld);
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,8 +404,7 @@ int magisk_proxy_main(int, char *argv[]) {
|
|||||||
static void unxz_init(const char *init_xz, const char *init) {
|
static void unxz_init(const char *init_xz, const char *init) {
|
||||||
LOGD("unxz %s -> %s\n", init_xz, init);
|
LOGD("unxz %s -> %s\n", init_xz, init);
|
||||||
int fd = xopen(init, O_WRONLY | O_CREAT, 0777);
|
int fd = xopen(init, O_WRONLY | O_CREAT, 0777);
|
||||||
fd_stream ch(fd);
|
unxz(fd, mmap_data{init_xz});
|
||||||
unxz(ch, mmap_data{init_xz});
|
|
||||||
close(fd);
|
close(fd);
|
||||||
clone_attr(init_xz, init);
|
clone_attr(init_xz, init);
|
||||||
unlink(init_xz);
|
unlink(init_xz);
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
#include <cil/cil.h>
|
#include <cil/cil.h>
|
||||||
|
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
#include <stream.hpp>
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
#define SHALEN 64
|
#define SHALEN 64
|
||||||
static bool cmp_sha256(const char *a, const char *b) {
|
static bool cmp_sha256(const char *a, const char *b) {
|
||||||
@ -230,20 +230,29 @@ sepol_impl::~sepol_impl() {
|
|||||||
free(db);
|
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 {
|
bool SePolicy::to_file(::rust::Utf8CStr file) const noexcept {
|
||||||
// No partial writes are allowed to /sys/fs/selinux/load, thus the reason why we
|
// 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
|
// first dump everything into memory, then directly call write system call
|
||||||
heap_data data;
|
vector<char> out;
|
||||||
auto fp = make_stream_fp<byte_stream>(data);
|
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_t pf;
|
||||||
policy_file_init(&pf);
|
policy_file_init(&pf);
|
||||||
pf.type = PF_USE_STDIO;
|
pf.type = PF_USE_STDIO;
|
||||||
pf.fp = fp.get();
|
pf.fp = fp;
|
||||||
if (policydb_write(impl->db, &pf)) {
|
if (policydb_write(impl->db, &pf)) {
|
||||||
LOGE("Fail to create policy image\n");
|
LOGE("Fail to create policy image\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
int fd = xopen(file.data(), O_WRONLY | O_CREAT | O_CLOEXEC, 0644);
|
int fd = xopen(file.data(), O_WRONLY | O_CREAT | O_CLOEXEC, 0644);
|
||||||
if (fd < 0)
|
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) {
|
if (struct stat st{}; xfstat(fd, &st) == 0 && st.st_size > 0) {
|
||||||
ftruncate(fd, 0);
|
ftruncate(fd, 0);
|
||||||
}
|
}
|
||||||
xwrite(fd, data.buf(), data.sz());
|
xwrite(fd, out.data(), out.size());
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user