kernel: precise trigger timing of post-fs-data (#118)
* kernel: add report_event cmd * ksud: report event * kernel: trigger on_post_fs_data * ksud: comment unused code * [skip ci] run clang-format Signed-off-by: Ylarod <me@ylarod.cn> * ci: use custom key to sign official bootimgs * format ksud * reject non root * remove Signed-off-by: Ylarod <me@ylarod.cn>
This commit is contained in:
@@ -5,8 +5,9 @@
|
|||||||
#include "linux/printk.h"
|
#include "linux/printk.h"
|
||||||
#include "linux/slab.h"
|
#include "linux/slab.h"
|
||||||
|
|
||||||
#include "selinux/selinux.h"
|
|
||||||
#include "klog.h" // IWYU pragma: keep
|
#include "klog.h" // IWYU pragma: keep
|
||||||
|
#include "selinux/selinux.h"
|
||||||
|
|
||||||
#define FILE_MAGIC 0x7f4b5355 // ' KSU', u32
|
#define FILE_MAGIC 0x7f4b5355 // ' KSU', u32
|
||||||
#define FILE_FORMAT_VERSION 1 // u32
|
#define FILE_FORMAT_VERSION 1 // u32
|
||||||
|
|
||||||
@@ -27,7 +28,8 @@ static struct work_struct ksu_load_work;
|
|||||||
|
|
||||||
bool persistent_allow_list(void);
|
bool persistent_allow_list(void);
|
||||||
|
|
||||||
void ksu_show_allow_list(void){
|
void ksu_show_allow_list(void)
|
||||||
|
{
|
||||||
struct perm_data *p = NULL;
|
struct perm_data *p = NULL;
|
||||||
struct list_head *pos = NULL;
|
struct list_head *pos = NULL;
|
||||||
pr_info("ksu_show_allow_list");
|
pr_info("ksu_show_allow_list");
|
||||||
@@ -179,7 +181,8 @@ void do_load_allow_list(struct work_struct *work)
|
|||||||
#ifdef CONFIG_KSU_DEBUG
|
#ifdef CONFIG_KSU_DEBUG
|
||||||
int errno = PTR_ERR(fp);
|
int errno = PTR_ERR(fp);
|
||||||
if (errno == -ENOENT) {
|
if (errno == -ENOENT) {
|
||||||
ksu_allow_uid(2000, true, true); // allow adb shell by default
|
ksu_allow_uid(2000, true,
|
||||||
|
true); // allow adb shell by default
|
||||||
} else {
|
} else {
|
||||||
pr_err("load_allow_list open file failed: %d\n",
|
pr_err("load_allow_list open file failed: %d\n",
|
||||||
PTR_ERR(fp));
|
PTR_ERR(fp));
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "linux/kernel.h"
|
#include "linux/kernel.h"
|
||||||
#include "linux/kprobes.h"
|
#include "linux/kprobes.h"
|
||||||
#include "linux/lsm_hooks.h"
|
#include "linux/lsm_hooks.h"
|
||||||
|
#include "linux/printk.h"
|
||||||
#include "linux/uaccess.h"
|
#include "linux/uaccess.h"
|
||||||
#include "linux/uidgid.h"
|
#include "linux/uidgid.h"
|
||||||
#include "linux/version.h"
|
#include "linux/version.h"
|
||||||
@@ -15,11 +16,12 @@
|
|||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "core_hook.h"
|
#include "core_hook.h"
|
||||||
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "ksu.h"
|
#include "ksu.h"
|
||||||
|
#include "ksud.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "selinux/selinux.h"
|
#include "selinux/selinux.h"
|
||||||
#include "uid_observer.h"
|
#include "uid_observer.h"
|
||||||
#include "klog.h" // IWYU pragma: keep
|
|
||||||
|
|
||||||
static inline bool is_allow_su()
|
static inline bool is_allow_su()
|
||||||
{
|
{
|
||||||
@@ -200,6 +202,34 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg2 == CMD_REPORT_EVENT) {
|
||||||
|
if (0 != current_uid().val) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (arg3) {
|
||||||
|
case EVENT_POST_FS_DATA: {
|
||||||
|
static bool post_fs_data_lock = false;
|
||||||
|
if (!post_fs_data_lock) {
|
||||||
|
post_fs_data_lock = true;
|
||||||
|
pr_info("post-fs-data triggered");
|
||||||
|
on_post_fs_data();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EVENT_BOOT_COMPLETED: {
|
||||||
|
static bool boot_complete_lock = false;
|
||||||
|
if (!boot_complete_lock) {
|
||||||
|
boot_complete_lock = true;
|
||||||
|
pr_info("boot_complete triggered");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// all other cmds are for 'root manager'
|
// all other cmds are for 'root manager'
|
||||||
if (!is_manager()) {
|
if (!is_manager()) {
|
||||||
pr_info("Only manager can do cmd: %d\n", arg2);
|
pr_info("Only manager can do cmd: %d\n", arg2);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
|
#include "linux/fs.h"
|
||||||
#include "linux/module.h"
|
#include "linux/module.h"
|
||||||
#include "linux/workqueue.h"
|
#include "linux/workqueue.h"
|
||||||
#include "linux/fs.h"
|
|
||||||
|
|
||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "core_hook.h"
|
#include "core_hook.h"
|
||||||
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "ksu.h"
|
#include "ksu.h"
|
||||||
#include "uid_observer.h"
|
#include "uid_observer.h"
|
||||||
#include "klog.h" // IWYU pragma: keep
|
|
||||||
|
|
||||||
static struct workqueue_struct *ksu_workqueue;
|
static struct workqueue_struct *ksu_workqueue;
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,16 @@
|
|||||||
#define KERNEL_SU_OPTION 0xDEADBEEF
|
#define KERNEL_SU_OPTION 0xDEADBEEF
|
||||||
|
|
||||||
#define CMD_GRANT_ROOT 0
|
#define CMD_GRANT_ROOT 0
|
||||||
|
|
||||||
#define CMD_BECOME_MANAGER 1
|
#define CMD_BECOME_MANAGER 1
|
||||||
#define CMD_GET_VERSION 2
|
#define CMD_GET_VERSION 2
|
||||||
#define CMD_ALLOW_SU 3
|
#define CMD_ALLOW_SU 3
|
||||||
#define CMD_DENY_SU 4
|
#define CMD_DENY_SU 4
|
||||||
#define CMD_GET_ALLOW_LIST 5
|
#define CMD_GET_ALLOW_LIST 5
|
||||||
#define CMD_GET_DENY_LIST 6
|
#define CMD_GET_DENY_LIST 6
|
||||||
|
#define CMD_REPORT_EVENT 7
|
||||||
|
|
||||||
|
#define EVENT_POST_FS_DATA 1
|
||||||
|
#define EVENT_BOOT_COMPLETED 2
|
||||||
|
|
||||||
bool ksu_queue_work(struct work_struct *work);
|
bool ksu_queue_work(struct work_struct *work);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "linux/err.h"
|
#include "linux/err.h"
|
||||||
#include "linux/fs.h"
|
#include "linux/fs.h"
|
||||||
#include "linux/kprobes.h"
|
#include "linux/kprobes.h"
|
||||||
|
#include "linux/printk.h"
|
||||||
#include "linux/types.h"
|
#include "linux/types.h"
|
||||||
#include "linux/uaccess.h"
|
#include "linux/uaccess.h"
|
||||||
#include "linux/version.h"
|
#include "linux/version.h"
|
||||||
@@ -11,8 +12,8 @@
|
|||||||
|
|
||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "selinux/selinux.h"
|
|
||||||
#include "klog.h" // IWYU pragma: keep
|
#include "klog.h" // IWYU pragma: keep
|
||||||
|
#include "selinux/selinux.h"
|
||||||
|
|
||||||
static const char KERNEL_SU_RC[] =
|
static const char KERNEL_SU_RC[] =
|
||||||
"\n"
|
"\n"
|
||||||
@@ -47,6 +48,18 @@ static bool vfs_read_hook = true;
|
|||||||
static bool execveat_hook = true;
|
static bool execveat_hook = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void on_post_fs_data(void)
|
||||||
|
{
|
||||||
|
static bool done = false;
|
||||||
|
if (done) {
|
||||||
|
pr_info("on_post_fs_data already done");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
pr_info("ksu_load_allow_list");
|
||||||
|
ksu_load_allow_list();
|
||||||
|
}
|
||||||
|
|
||||||
int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
||||||
void *argv, void *envp, int *flags)
|
void *argv, void *envp, int *flags)
|
||||||
{
|
{
|
||||||
@@ -85,7 +98,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
|
|||||||
!memcmp(filename->name, app_process, sizeof(app_process) - 1)) {
|
!memcmp(filename->name, app_process, sizeof(app_process) - 1)) {
|
||||||
first_app_process = false;
|
first_app_process = false;
|
||||||
pr_info("exec app_process, /data prepared!\n");
|
pr_info("exec app_process, /data prepared!\n");
|
||||||
ksu_load_allow_list();
|
on_post_fs_data(); // we keep this for old ksud
|
||||||
stop_execve_hook();
|
stop_execve_hook();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
kernel/ksud.h
Normal file
6
kernel/ksud.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef __KSU_H_KSUD
|
||||||
|
#define __KSU_H_KSUD
|
||||||
|
|
||||||
|
void on_post_fs_data(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
#include "linux/rcupdate.h"
|
#include "linux/rcupdate.h"
|
||||||
|
|
||||||
#include "apk_sign.h"
|
#include "apk_sign.h"
|
||||||
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "ksu.h"
|
#include "ksu.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "klog.h" // IWYU pragma: keep
|
|
||||||
|
|
||||||
uid_t ksu_manager_uid = INVALID_UID;
|
uid_t ksu_manager_uid = INVALID_UID;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "linux/version.h"
|
#include "linux/version.h"
|
||||||
|
|
||||||
|
#include "../klog.h" // IWYU pragma: keep
|
||||||
#include "selinux.h"
|
#include "selinux.h"
|
||||||
#include "sepolicy.h"
|
#include "sepolicy.h"
|
||||||
#include "ss/services.h"
|
#include "ss/services.h"
|
||||||
#include "../klog.h" // IWYU pragma: keep
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
|
||||||
#define SELINUX_POLICY_INSTEAD_SELINUX_SS
|
#define SELINUX_POLICY_INSTEAD_SELINUX_SS
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "objsec.h"
|
|
||||||
#include "selinux.h"
|
#include "selinux.h"
|
||||||
|
#include "objsec.h"
|
||||||
|
|
||||||
#include "../klog.h" // IWYU pragma: keep
|
#include "../klog.h" // IWYU pragma: keep
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
#include "linux/workqueue.h"
|
#include "linux/workqueue.h"
|
||||||
|
|
||||||
#include "allowlist.h"
|
#include "allowlist.h"
|
||||||
|
#include "klog.h" // IWYU pragma: keep
|
||||||
#include "ksu.h"
|
#include "ksu.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "uid_observer.h"
|
#include "uid_observer.h"
|
||||||
#include "klog.h" // IWYU pragma: keep
|
|
||||||
|
|
||||||
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list"
|
#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list"
|
||||||
static struct work_struct ksu_update_uid_work;
|
static struct work_struct ksu_update_uid_work;
|
||||||
|
|||||||
1
userspace/ksud/Cargo.lock
generated
1
userspace/ksud/Cargo.lock
generated
@@ -445,6 +445,7 @@ dependencies = [
|
|||||||
"env_logger",
|
"env_logger",
|
||||||
"humansize",
|
"humansize",
|
||||||
"java-properties",
|
"java-properties",
|
||||||
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"regex",
|
"regex",
|
||||||
"retry",
|
"retry",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ regex = "1.5.4"
|
|||||||
encoding = "0.2.33"
|
encoding = "0.2.33"
|
||||||
retry = "2.0.0"
|
retry = "2.0.0"
|
||||||
humansize = "2.0.0"
|
humansize = "2.0.0"
|
||||||
|
libc = "0.2"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true
|
strip = true
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use anyhow::Result;
|
use anyhow::{Ok, Result};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
use crate::{event, module, debug, apk_sign};
|
use crate::{apk_sign, debug, event, module};
|
||||||
|
|
||||||
/// KernelSU userspace cli
|
/// KernelSU userspace cli
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
@@ -58,6 +58,9 @@ enum Debug {
|
|||||||
apk: String,
|
apk: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Get kernel version
|
||||||
|
Version,
|
||||||
|
|
||||||
/// For testing
|
/// For testing
|
||||||
Test,
|
Test,
|
||||||
}
|
}
|
||||||
@@ -115,17 +118,19 @@ pub fn run() -> Result<()> {
|
|||||||
Commands::Sepolicy => todo!(),
|
Commands::Sepolicy => todo!(),
|
||||||
Commands::Services => event::on_services(),
|
Commands::Services => event::on_services(),
|
||||||
|
|
||||||
Commands::Debug { command } => {
|
Commands::Debug { command } => match command {
|
||||||
match command {
|
|
||||||
Debug::SetManager { apk } => debug::set_manager(&apk),
|
Debug::SetManager { apk } => debug::set_manager(&apk),
|
||||||
Debug::GetSign { apk } => {
|
Debug::GetSign { apk } => {
|
||||||
let sign = apk_sign::get_apk_signature(&apk)?;
|
let sign = apk_sign::get_apk_signature(&apk)?;
|
||||||
println!("size: {:#x}, hash: {:#x}", sign.0, sign.1);
|
println!("size: {:#x}, hash: {:#x}", sign.0, sign.1);
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
|
Debug::Version => {
|
||||||
|
println!("Kernel Version: {}", crate::ksu::get_version());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Debug::Test => todo!(),
|
Debug::Test => todo!(),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = &result {
|
if let Err(e) = &result {
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ pub fn do_systemless_mount(module_dir: &str) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_post_data_fs() -> Result<()> {
|
pub fn on_post_data_fs() -> Result<()> {
|
||||||
|
crate::ksu::report_post_fs_data();
|
||||||
let module_update_img = defs::MODULE_UPDATE_IMG;
|
let module_update_img = defs::MODULE_UPDATE_IMG;
|
||||||
let module_img = defs::MODULE_IMG;
|
let module_img = defs::MODULE_IMG;
|
||||||
let module_dir = defs::MODULE_DIR;
|
let module_dir = defs::MODULE_DIR;
|
||||||
@@ -151,6 +152,7 @@ pub fn on_services() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_boot_completed() -> Result<()> {
|
pub fn on_boot_completed() -> Result<()> {
|
||||||
|
crate::ksu::report_boot_complete();
|
||||||
let module_update_img = Path::new(defs::MODULE_UPDATE_IMG);
|
let module_update_img = Path::new(defs::MODULE_UPDATE_IMG);
|
||||||
let module_img = Path::new(defs::MODULE_IMG);
|
let module_img = Path::new(defs::MODULE_IMG);
|
||||||
if module_update_img.exists() {
|
if module_update_img.exists() {
|
||||||
|
|||||||
58
userspace/ksud/src/ksu.rs
Normal file
58
userspace/ksud/src/ksu.rs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
const KERNEL_SU_OPTION: u32 = 0xDEADBEEF;
|
||||||
|
|
||||||
|
// const CMD_GRANT_ROOT: u64 = 0;
|
||||||
|
// const CMD_BECOME_MANAGER: u64 = 1;
|
||||||
|
const CMD_GET_VERSION: u64 = 2;
|
||||||
|
// const CMD_ALLOW_SU: u64 = 3;
|
||||||
|
// const CMD_DENY_SU: u64 = 4;
|
||||||
|
// const CMD_GET_ALLOW_LIST: u64 = 5;
|
||||||
|
// const CMD_GET_DENY_LIST: u64 = 6;
|
||||||
|
const CMD_REPORT_EVENT: u64 = 7;
|
||||||
|
|
||||||
|
const EVENT_POST_FS_DATA: u64 = 1;
|
||||||
|
const EVENT_BOOT_COMPLETED: u64 = 2;
|
||||||
|
|
||||||
|
|
||||||
|
// pub fn grant_root() -> bool {
|
||||||
|
// let mut result: i32 = 0;
|
||||||
|
// unsafe {
|
||||||
|
// libc::prctl(
|
||||||
|
// KERNEL_SU_OPTION as i32,
|
||||||
|
// CMD_GRANT_ROOT,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// &mut result as *mut _ as *mut libc::c_void,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// return result as u32 == KERNEL_SU_OPTION;
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn get_version() -> i32 {
|
||||||
|
let mut result: i32 = 0;
|
||||||
|
unsafe {
|
||||||
|
libc::prctl(
|
||||||
|
KERNEL_SU_OPTION as i32,
|
||||||
|
CMD_GET_VERSION,
|
||||||
|
&mut result as *mut _ as *mut libc::c_void,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn report_event(event: u64){
|
||||||
|
unsafe {
|
||||||
|
libc::prctl(
|
||||||
|
KERNEL_SU_OPTION as i32,
|
||||||
|
CMD_REPORT_EVENT,
|
||||||
|
event,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn report_post_fs_data(){
|
||||||
|
report_event(EVENT_POST_FS_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn report_boot_complete(){
|
||||||
|
report_event(EVENT_BOOT_COMPLETED);
|
||||||
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
mod cli;
|
|
||||||
mod event;
|
|
||||||
mod module;
|
|
||||||
mod defs;
|
|
||||||
mod utils;
|
|
||||||
mod restorecon;
|
|
||||||
mod debug;
|
|
||||||
mod apk_sign;
|
mod apk_sign;
|
||||||
|
mod cli;
|
||||||
|
mod debug;
|
||||||
|
mod defs;
|
||||||
|
mod event;
|
||||||
|
mod ksu;
|
||||||
|
mod module;
|
||||||
|
mod restorecon;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
cli::run()
|
cli::run()
|
||||||
|
|||||||
@@ -109,7 +109,11 @@ fn check_image(img: &str) -> Result<()> {
|
|||||||
// 0: no error
|
// 0: no error
|
||||||
// 1: file system errors corrected
|
// 1: file system errors corrected
|
||||||
// https://man7.org/linux/man-pages/man8/e2fsck.8.html
|
// https://man7.org/linux/man-pages/man8/e2fsck.8.html
|
||||||
ensure!(code == Some(0) || code == Some(1), "check image e2fsck exec failed: {}", code.unwrap_or(-1));
|
ensure!(
|
||||||
|
code == Some(0) || code == Some(1),
|
||||||
|
"check image e2fsck exec failed: {}",
|
||||||
|
code.unwrap_or(-1)
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +124,10 @@ fn grow_image_size(img: &str, extra_size: u64) -> Result<()> {
|
|||||||
// check image
|
// check image
|
||||||
check_image(img)?;
|
check_image(img)?;
|
||||||
|
|
||||||
println!("- Target image size: {}", humansize::format_size(target_size, humansize::DECIMAL));
|
println!(
|
||||||
|
"- Target image size: {}",
|
||||||
|
humansize::format_size(target_size, humansize::DECIMAL)
|
||||||
|
);
|
||||||
let target_size = target_size / 1024 + 1;
|
let target_size = target_size / 1024 + 1;
|
||||||
|
|
||||||
let result = Exec::shell(format!("resize2fs {} {}K", img, target_size))
|
let result = Exec::shell(format!("resize2fs {} {}K", img, target_size))
|
||||||
@@ -331,7 +338,10 @@ pub fn install_module(zip: String) -> Result<()> {
|
|||||||
let grow_size_per_m = grow_size / 1024 / 1024 + 1;
|
let grow_size_per_m = grow_size / 1024 / 1024 + 1;
|
||||||
|
|
||||||
println!("- Preparing image");
|
println!("- Preparing image");
|
||||||
println!("- Module size: {}", humansize::format_size(zip_uncompressed_size, humansize::DECIMAL));
|
println!(
|
||||||
|
"- Module size: {}",
|
||||||
|
humansize::format_size(zip_uncompressed_size, humansize::DECIMAL)
|
||||||
|
);
|
||||||
|
|
||||||
if !modules_img_exist && !modules_update_img_exist {
|
if !modules_img_exist && !modules_update_img_exist {
|
||||||
// if no modules and modules_update, it is brand new installation, we should create a new img
|
// if no modules and modules_update, it is brand new installation, we should create a new img
|
||||||
|
|||||||
Reference in New Issue
Block a user