added initial commit
This commit is contained in:
commit
3f5fc7d16f
|
@ -0,0 +1,5 @@
|
||||||
|
**/.git
|
||||||
|
/.devcontainer
|
||||||
|
/.vscode
|
||||||
|
/debug
|
||||||
|
/target
|
|
@ -0,0 +1,208 @@
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,intellij+all,windows,linux,macos,rust,rust-analyzer
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,intellij+all,windows,linux,macos,rust,rust-analyzer
|
||||||
|
|
||||||
|
### Intellij+all ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### Intellij+all Patch ###
|
||||||
|
# Ignore everything but code style settings and run configurations
|
||||||
|
# that are supposed to be shared within teams.
|
||||||
|
|
||||||
|
.idea/*
|
||||||
|
|
||||||
|
!.idea/codeStyles
|
||||||
|
!.idea/runConfigurations
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### macOS Patch ###
|
||||||
|
# iCloud generated files
|
||||||
|
*.icloud
|
||||||
|
|
||||||
|
### Rust ###
|
||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
debug/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
|
Cargo.lock
|
||||||
|
|
||||||
|
# These are backup files generated by rustfmt
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
### rust-analyzer ###
|
||||||
|
# Can be generated by other build systems other than cargo (ex: bazelbuild/rust_rules)
|
||||||
|
rust-project.json
|
||||||
|
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Built Visual Studio Code Extensions
|
||||||
|
*.vsix
|
||||||
|
|
||||||
|
### VisualStudioCode Patch ###
|
||||||
|
# Ignore all local history of files
|
||||||
|
.history
|
||||||
|
.ionide
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,intellij+all,windows,linux,macos,rust,rust-analyzer
|
||||||
|
|
||||||
|
/target
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
{
|
||||||
|
"rust-analyzer.cargo.target": "aarch64-unknown-linux-musl",
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
[package]
|
||||||
|
name = "init-wrapper"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = { version = "0.2", default-features = false }
|
||||||
|
libc-print = "0.1.22"
|
||||||
|
errno = { version = "*", default-features = false }
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
# This isn't required for development builds, but makes development
|
||||||
|
# build behavior match release builds. To enable unwinding panics
|
||||||
|
# during development, simply remove this line.
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
#opt-level = 'z' # Optimize for size.
|
||||||
|
lto = true # Enable Link Time Optimization
|
||||||
|
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
|
||||||
|
panic = 'abort' # Abort on panic
|
||||||
|
strip = true # Strip symbols from binary*
|
||||||
|
debug-assertions = false
|
||||||
|
debug = false
|
||||||
|
rpath = false
|
||||||
|
incremental = false
|
|
@ -0,0 +1,37 @@
|
||||||
|
#syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
##
|
||||||
|
## Build
|
||||||
|
##
|
||||||
|
FROM rust:1-alpine3.19 AS build
|
||||||
|
LABEL org.opencontainers.image.authors="Sangbum Kim <sangbumkim@amuz.es>"
|
||||||
|
|
||||||
|
# set the workdir and copy the source into it
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
ENV RUSTFLAGS='-C link-arg=-s -C link-arg=-fuse-ld=lld'
|
||||||
|
|
||||||
|
RUN set -x && \
|
||||||
|
apk add --no-cache \
|
||||||
|
libcap-static \
|
||||||
|
libcap-dev \
|
||||||
|
lld \
|
||||||
|
musl-dev
|
||||||
|
|
||||||
|
RUN set -x && \
|
||||||
|
cargo build --release && \
|
||||||
|
ls -alh target/release/init-wrapper
|
||||||
|
# && \
|
||||||
|
# ldd target/release/init-wrapper
|
||||||
|
|
||||||
|
# RUN --mount=type=bind,rw,source=.,target=/host \
|
||||||
|
# cp -avf target/release/init-wrapper /host/init-wrapper && \
|
||||||
|
# ./target/release/init-wrapper
|
||||||
|
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=build /app/target/release/init-wrapper /init-wrapper
|
||||||
|
|
||||||
|
|
||||||
|
# ENTRYPOINT ['/init-wrapper']
|
|
@ -0,0 +1,32 @@
|
||||||
|
#syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
##
|
||||||
|
## Build
|
||||||
|
##
|
||||||
|
FROM rust:1-slim AS build
|
||||||
|
LABEL org.opencontainers.image.authors="Sangbum Kim <sangbumkim@amuz.es>"
|
||||||
|
|
||||||
|
# set the workdir and copy the source into it
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
# ENV RUSTFLAGS='-C link-arg=-s -C linker=rust-lld -C link-arg=-fuse-ld=lld'
|
||||||
|
# ENV RUSTFLAGS='-C link-arg=-s -C link-arg=-fuse-ld=lld'
|
||||||
|
# ENV RUSTFLAGS='-C target-feature=+crt-static -C link-arg=-s -C link-args=-nostartfiles -C link-arg=-nostdlib'
|
||||||
|
# ENV RUSTFLAGS='-C target-feature=+crt-static -C link-arg=-s'
|
||||||
|
# ENV RUSTFLAGS='-C target-feature=+crt-static -C link-arg=-s'
|
||||||
|
# ENV RUSTFLAGS='-C target-feature=+crt-static -C link-arg=-static -C link-arg=-s'
|
||||||
|
# ENV RUSTFLAGS='-C target-feature=+crt-static -C link-arg=-static -C link-arg=-s -C link-arg=-fuse-ld=lld'
|
||||||
|
# ENV RUSTFLAGS='-C target-feature=+crt-static -C link-arg=-s -C link-arg=-fuse-ld=lld'
|
||||||
|
|
||||||
|
# do a release build
|
||||||
|
RUN set -x && \
|
||||||
|
cargo build --release && \
|
||||||
|
ldd target/release/init-wrapper
|
||||||
|
|
||||||
|
#RUN --mount=type=bind,rw,source=.,target=/host \
|
||||||
|
# cp -avf target/release/init-wrapper /host/init-wrapper
|
||||||
|
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=build /app/target/release/init-wrapper /init-wrapper
|
|
@ -0,0 +1,2 @@
|
||||||
|
[build]
|
||||||
|
target = "aarch64-unknown-linux-musl"
|
|
@ -0,0 +1,17 @@
|
||||||
|
#![allow(non_camel_case_types, dead_code)]
|
||||||
|
|
||||||
|
use libc::FILE;
|
||||||
|
|
||||||
|
#[link(name = "c")]
|
||||||
|
extern "C" {
|
||||||
|
static stdin: *mut FILE;
|
||||||
|
static stdout: *mut FILE;
|
||||||
|
static stderr: *mut FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
#[inline(never)]
|
||||||
|
#[cfg(not(test))]
|
||||||
|
unsafe fn panic_handler(_: &core::panic::PanicInfo) -> ! {
|
||||||
|
libc::exit(2)
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#![allow(non_camel_case_types, dead_code)]
|
||||||
|
|
||||||
|
use libc::{c_int, exit, FILE};
|
||||||
|
|
||||||
|
#[repr(C, align(16))]
|
||||||
|
struct f128 {
|
||||||
|
a: [u8; 16],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn __letf2(_a: f128, _b: f128) -> c_int {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn __unordtf2(_a: f128, _b: f128) -> c_int {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn _Unwind_Resume() -> ! {
|
||||||
|
exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn __gcc_personality_v0() {}
|
|
@ -0,0 +1,314 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
mod link;
|
||||||
|
mod mem;
|
||||||
|
|
||||||
|
use alloc::ffi::CString;
|
||||||
|
use core::ffi::CStr;
|
||||||
|
use core::ops::Sub;
|
||||||
|
use core::ptr::null;
|
||||||
|
use core::time::Duration;
|
||||||
|
use errno::{errno, Errno};
|
||||||
|
use libc::{
|
||||||
|
c_int, c_void, chdir, clock_gettime, execvp, mkdir, mode_t, mount, rmdir, syscall, timespec,
|
||||||
|
umount2, SYS_pivot_root, CLOCK_BOOTTIME, EXIT_FAILURE, EXIT_SUCCESS, MNT_DETACH, MS_BIND,
|
||||||
|
MS_LAZYTIME, MS_MOVE, MS_NODEV, MS_NOSUID, MS_PRIVATE, MS_RDONLY, MS_REC, MS_RELATIME,
|
||||||
|
};
|
||||||
|
use libc_print::std_name::eprintln;
|
||||||
|
|
||||||
|
struct Timespec {
|
||||||
|
ts: timespec,
|
||||||
|
}
|
||||||
|
|
||||||
|
type SystemResult = Result<(), Errno>;
|
||||||
|
|
||||||
|
impl Sub<Timespec> for Timespec {
|
||||||
|
type Output = Duration;
|
||||||
|
|
||||||
|
fn sub(self, other: Timespec) -> Duration {
|
||||||
|
let sec = self.ts.tv_sec - other.ts.tv_sec;
|
||||||
|
let nsec = self.ts.tv_nsec - other.ts.tv_nsec;
|
||||||
|
if nsec < 0 {
|
||||||
|
Duration::from_secs(sec as u64) - Duration::from_nanos(nsec.unsigned_abs())
|
||||||
|
} else {
|
||||||
|
Duration::from_secs(sec as u64) + Duration::from_nanos(nsec.unsigned_abs())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<timespec> for Timespec {
|
||||||
|
fn from(item: timespec) -> Self {
|
||||||
|
Timespec { ts: item }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<timespec> for Timespec {
|
||||||
|
fn into(self) -> timespec {
|
||||||
|
self.ts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_mount(
|
||||||
|
source: Option<&str>,
|
||||||
|
target: Option<&str>,
|
||||||
|
fs: Option<&str>,
|
||||||
|
flags: u64,
|
||||||
|
opt: Option<&str>,
|
||||||
|
) -> SystemResult {
|
||||||
|
// has ownership
|
||||||
|
let raw_src = source.map(|v| CString::new(v).ok()).flatten();
|
||||||
|
let raw_tgt = target.map(|v| CString::new(v).ok()).flatten();
|
||||||
|
let raw_fs = fs.map(|v| CString::new(v).ok()).flatten();
|
||||||
|
let raw_fs_opt = opt.map(|v| CString::new(v).ok()).flatten();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if mount(
|
||||||
|
raw_src.as_ref().map(|v| v.as_ptr()).unwrap_or_else(null),
|
||||||
|
raw_tgt.as_ref().map(|v| v.as_ptr()).unwrap_or_else(null),
|
||||||
|
raw_fs.as_ref().map(|v| v.as_ptr()).unwrap_or_else(null),
|
||||||
|
flags,
|
||||||
|
raw_fs_opt.as_ref().map(|v| v.as_ptr()).unwrap_or_else(null) as *const c_void,
|
||||||
|
) == -1
|
||||||
|
{
|
||||||
|
Err(errno())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn do_umount(path: &str, flags: i32) -> SystemResult {
|
||||||
|
// has ownership
|
||||||
|
let raw_path = CString::new(path).unwrap();
|
||||||
|
unsafe {
|
||||||
|
if umount2(raw_path.as_ref().as_ptr(), flags) == -1 {
|
||||||
|
Err(errno())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_mkdir(path: &str, mode: mode_t) -> SystemResult {
|
||||||
|
// has ownership
|
||||||
|
let raw_path = CString::new(path).unwrap();
|
||||||
|
unsafe {
|
||||||
|
if mkdir(raw_path.as_ref().as_ptr(), mode) == -1 {
|
||||||
|
Err(errno())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn do_rmdir(path: &str) -> SystemResult {
|
||||||
|
// has ownership
|
||||||
|
let raw_path = CString::new(path).unwrap();
|
||||||
|
unsafe {
|
||||||
|
if rmdir(raw_path.as_ref().as_ptr()) == -1 {
|
||||||
|
Err(errno())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn do_chdir(path: &str) -> SystemResult {
|
||||||
|
// has ownership
|
||||||
|
let raw_path = CString::new(path).unwrap();
|
||||||
|
unsafe {
|
||||||
|
if chdir(raw_path.as_ref().as_ptr()) == -1 {
|
||||||
|
Err(errno())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pivot_root(new_root: &str, put_old: &str) -> SystemResult {
|
||||||
|
let raw_new_root = CString::new(new_root).unwrap();
|
||||||
|
let raw_put_old = CString::new(put_old).unwrap();
|
||||||
|
unsafe {
|
||||||
|
if syscall(
|
||||||
|
SYS_pivot_root,
|
||||||
|
raw_new_root.as_ref().as_ptr(),
|
||||||
|
raw_put_old.as_ref().as_ptr(),
|
||||||
|
) == -1
|
||||||
|
{
|
||||||
|
Err(errno())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_gettime() -> Result<Timespec, Errno> {
|
||||||
|
let mut time = timespec {
|
||||||
|
tv_sec: 0,
|
||||||
|
tv_nsec: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if clock_gettime(CLOCK_BOOTTIME, &mut time) == -1 {
|
||||||
|
Err(errno())
|
||||||
|
} else {
|
||||||
|
Ok(time.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn replace_root() -> Result<(), ()> {
|
||||||
|
match do_mount(None, Some("/"), None, MS_REC | MS_PRIVATE, None) {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("remount \"/\" with private option failed: {}", e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("\"/\" remounted"),
|
||||||
|
};
|
||||||
|
|
||||||
|
match do_mount(
|
||||||
|
Some("parentfs"),
|
||||||
|
Some("/run"),
|
||||||
|
Some("tmpfs"),
|
||||||
|
MS_LAZYTIME | MS_NODEV | MS_NOSUID | MS_RELATIME,
|
||||||
|
None,
|
||||||
|
) {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("mount \"/run\" failed: {}", e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("\"/run\" mounted"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let ovr_dir_structures = [
|
||||||
|
"/run/overlay",
|
||||||
|
"/run/overlay/lower",
|
||||||
|
"/run/overlay/upper",
|
||||||
|
"/run/overlay/work",
|
||||||
|
"/run/overlay/merged",
|
||||||
|
];
|
||||||
|
for path in ovr_dir_structures {
|
||||||
|
match do_mkdir(path, 0o0700) {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("mkdir \"{}\" failed: {}", path, e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("\"{}\" created", path),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match do_mount(
|
||||||
|
Some("/"),
|
||||||
|
Some("/run/overlay/lower"),
|
||||||
|
None,
|
||||||
|
MS_BIND | MS_RDONLY,
|
||||||
|
None,
|
||||||
|
) {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("mount \"/run/overlay/lower\" failed: {}", e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("\"/run/overlay/lower\" mounted"),
|
||||||
|
};
|
||||||
|
|
||||||
|
match do_mount(
|
||||||
|
Some("rootfs"),
|
||||||
|
Some("/run/overlay/merged"),
|
||||||
|
Some("overlay"), MS_RELATIME|MS_LAZYTIME,
|
||||||
|
Some("lowerdir=/run/overlay/lower,upperdir=/run/overlay/upper,workdir=/run/overlay/work,redirect_dir=on,uuid=on,metacopy=on,volatile"),
|
||||||
|
) {
|
||||||
|
Err(e) => {eprintln!("mount \"/run/overlay/merged\" failed: {}", e);
|
||||||
|
return Err(());
|
||||||
|
},
|
||||||
|
Ok(_) => eprintln!("\"/run/overlay/merged\" mounted"),
|
||||||
|
};
|
||||||
|
|
||||||
|
match do_mkdir("/run/overlay/merged/oldroot", 0o0700) {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("mkdir \"/run/overlay/merged/oldroot\" failed: {}", e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("\"/run/overlay/merged/oldroot\" created"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match pivot_root("/run/overlay/merged", "/run/overlay/merged/oldroot") {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("pivot_root failed: {}", e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("pivot_root done"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match do_chdir("/") {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("chdir \"/\" failed: {}", e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("chdir \"/\" done"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match do_mount(
|
||||||
|
Some("/oldroot/run"),
|
||||||
|
Some("/run"),
|
||||||
|
None,
|
||||||
|
MS_REC | MS_MOVE,
|
||||||
|
None,
|
||||||
|
) {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("moving mountpoint \"/oldroot/run\" failed: {}", e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("mountpoint \"/oldroot/run\" moved"),
|
||||||
|
};
|
||||||
|
|
||||||
|
match do_umount("/oldroot", MNT_DETACH) {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("umount mountpoint \"/oldroot\" failed: {}", e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("mountpoint \"/oldroot/run\" unmounted"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let unused_dirs = ["/oldroot", "/run/overlay/merged"];
|
||||||
|
for path in unused_dirs {
|
||||||
|
match do_rmdir(path) {
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("remove \"{}\" failed: {}", path, e);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(_) => eprintln!("\"{}\" removed", path),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn main(_argc: c_int, argv: *const *const u8) -> c_int {
|
||||||
|
let start = match do_gettime() {
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
Ok(v) => v,
|
||||||
|
};
|
||||||
|
|
||||||
|
match replace_root() {
|
||||||
|
Err(_) => return EXIT_FAILURE,
|
||||||
|
Ok(_) => eprintln!("rootfs replaced with overlayfs!"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let end = match do_gettime() {
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
Ok(v) => v,
|
||||||
|
};
|
||||||
|
let elapsed = end - start;
|
||||||
|
eprintln!("processed in {:?}", elapsed);
|
||||||
|
|
||||||
|
let init_path = CStr::from_bytes_with_nul_unchecked(b"/sbin/init\0");
|
||||||
|
execvp(init_path.as_ptr(), argv);
|
||||||
|
|
||||||
|
EXIT_SUCCESS
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
use core::alloc::{GlobalAlloc, Layout};
|
||||||
|
use libc::{c_void, free, malloc};
|
||||||
|
/// The global allocator type.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Allocator;
|
||||||
|
|
||||||
|
unsafe impl GlobalAlloc for Allocator {
|
||||||
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
|
malloc(layout.size()) as *mut u8
|
||||||
|
}
|
||||||
|
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
|
||||||
|
free(ptr as *mut c_void);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The static global allocator.
|
||||||
|
#[global_allocator]
|
||||||
|
static GLOBAL_ALLOCATOR: Allocator = Allocator;
|
Loading…
Reference in New Issue