Selaa lähdekoodia

first available version.

ZRY 10 kuukautta sitten
vanhempi
säilyke
df2bce6791
27 muutettua tiedostoa jossa 2820 lisäystä ja 0 poistoa
  1. 6 0
      .cargo/config.toml
  2. 5 0
      .gitignore
  3. 8 0
      .idea/.gitignore
  4. 7 0
      .idea/misc.xml
  5. 8 0
      .idea/modules.xml
  6. 12 0
      .idea/rumia.iml
  7. 6 0
      .idea/vcs.xml
  8. 1212 0
      Cargo.lock
  9. 17 0
      Cargo.toml
  10. 94 0
      src/cfg/config.rs
  11. 139 0
      src/cfg/mod.rs
  12. 25 0
      src/cfg/rumia.rs
  13. 51 0
      src/env.rs
  14. 59 0
      src/exec.rs
  15. 149 0
      src/log.rs
  16. 35 0
      src/main.rs
  17. 97 0
      src/mount.rs
  18. 34 0
      src/op/makesure.rs
  19. 3 0
      src/op/mod.rs
  20. 219 0
      src/op/once.rs
  21. 189 0
      src/op/seq.rs
  22. 33 0
      src/power.rs
  23. 102 0
      src/repl/mgrsh.rs
  24. 183 0
      src/repl/mod.rs
  25. 86 0
      src/repl/prepare.rs
  26. 23 0
      src/swap.rs
  27. 18 0
      src/swroot.rs

+ 6 - 0
.cargo/config.toml

@@ -0,0 +1,6 @@
+[build]
+target = "armv7-unknown-linux-musleabihf"
+
+[target.armv7-unknown-linux-musleabihf]
+#linker = "armv7l-linux-musleabihf-ld"
+linker = "rust-lld"

+ 5 - 0
.gitignore

@@ -11,3 +11,8 @@
 # Generated by Cargo
 /target/
 
+
+
+# Added by cargo
+
+/target

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 7 - 0
.idea/misc.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="XMakeProjectSettings">
+    <option name="currentArchitecture" value="x86" />
+    <option name="workingDirectory" value="$PROJECT_DIR$" />
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/rumia.iml" filepath="$PROJECT_DIR$/.idea/rumia.iml" />
+    </modules>
+  </component>
+</project>

+ 12 - 0
.idea/rumia.iml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="Go" enabled="true" />
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>

+ 1212 - 0
Cargo.lock

@@ -0,0 +1,1212 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ahash"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "base-x"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
+
+[[package]]
+name = "base64"
+version = "0.21.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
+
+[[package]]
+name = "bcrypt"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9df288bec72232f78c1ec5fe4e8f1d108aa0265476e93097593c803c8c02062a"
+dependencies = [
+ "base64",
+ "blowfish",
+ "getrandom",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "blowfish"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
+dependencies = [
+ "byteorder",
+ "cipher",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
+name = "clipboard-win"
+version = "4.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362"
+dependencies = [
+ "error-code",
+ "str-buf",
+ "winapi",
+]
+
+[[package]]
+name = "const_fn"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset 0.9.0",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "dirs-next"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
+dependencies = [
+ "cfg-if",
+ "dirs-sys-next",
+]
+
+[[package]]
+name = "dirs-sys-next"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
+name = "discard"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
+
+[[package]]
+name = "easy-repl"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81d0001ed25c451c57f8d6724d448a6546a5d78bbac77a63a22e32c735b7ea16"
+dependencies = [
+ "anyhow",
+ "rustyline",
+ "rustyline-derive",
+ "shell-words",
+ "textwrap",
+ "thiserror",
+ "trie-rs",
+]
+
+[[package]]
+name = "either"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+
+[[package]]
+name = "endian-type"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
+
+[[package]]
+name = "equivalent"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
+
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "error-code"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21"
+dependencies = [
+ "libc",
+ "str-buf",
+]
+
+[[package]]
+name = "fd-lock"
+version = "3.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39ae6b3d9530211fb3b12a95374b8b0823be812f53d09e18c5675c0146b09642"
+dependencies = [
+ "cfg-if",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
+name = "fid-rs"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c28658c0c3420305705adde833a0d2d614207507d013a5f25707553fb2ae2cd"
+dependencies = [
+ "rayon",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+
+[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
+name = "indexmap"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.14.0",
+]
+
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.146"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
+[[package]]
+name = "log"
+version = "0.4.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
+
+[[package]]
+name = "louds-rs"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e16a91fb20f74b6d9a758a0103a2884af525a2fa34fbfe19f4b3c5482a4a54e9"
+dependencies = [
+ "fid-rs",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "memoffset"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "nibble_vec"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
+dependencies = [
+ "smallvec",
+]
+
+[[package]]
+name = "nix"
+version = "0.23.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c"
+dependencies = [
+ "bitflags",
+ "cc",
+ "cfg-if",
+ "libc",
+ "memoffset 0.6.5",
+]
+
+[[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "memoffset 0.7.1",
+ "pin-utils",
+ "static_assertions",
+]
+
+[[package]]
+name = "nonblock"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51c7a4f22e5f2e2bd805d6ab56f1ae87eb1815673e1b452048896fb687a8a3d4"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+dependencies = [
+ "hermit-abi 0.2.6",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkg_compile_time"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8970e7dfe13374320bfa3b2acc21e0c0f0e01ad7e8c140dd4882e21c7caf993"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "time",
+]
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.20+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.63"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "radix_trie"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
+dependencies = [
+ "endian-type",
+ "nibble_vec",
+]
+
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
+name = "regex"
+version = "1.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
+
+[[package]]
+name = "rumia"
+version = "0.1.0"
+dependencies = [
+ "bcrypt",
+ "easy-repl",
+ "lazy_static",
+ "nix 0.26.2",
+ "nonblock",
+ "pkg_compile_time",
+ "serde",
+ "simple-rw-global",
+ "toml",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustix"
+version = "0.37.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "rustyline"
+version = "9.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "clipboard-win",
+ "dirs-next",
+ "fd-lock",
+ "libc",
+ "log",
+ "memchr",
+ "nix 0.23.2",
+ "radix_trie",
+ "scopeguard",
+ "smallvec",
+ "unicode-segmentation",
+ "unicode-width",
+ "utf8parse",
+ "winapi",
+]
+
+[[package]]
+name = "rustyline-derive"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb35a55ab810b5c0fe31606fe9b47d1354e4dc519bec0a102655f78ea2b38057"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
+[[package]]
+name = "serde"
+version = "1.0.164"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.164"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.22",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.99"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "sha1"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
+dependencies = [
+ "sha1_smol",
+]
+
+[[package]]
+name = "sha1_smol"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
+
+[[package]]
+name = "shell-words"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
+
+[[package]]
+name = "simple-rw-global"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7dcb8c9e89265f47231a034abfe881421993530f338d13fafa9be9e5a319026"
+
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "smawk"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
+
+[[package]]
+name = "standback"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "stdweb"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
+dependencies = [
+ "discard",
+ "rustc_version",
+ "stdweb-derive",
+ "stdweb-internal-macros",
+ "stdweb-internal-runtime",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "stdweb-derive"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_derive",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "stdweb-internal-macros"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
+dependencies = [
+ "base-x",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "sha1",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "stdweb-internal-runtime"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
+
+[[package]]
+name = "str-buf"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
+
+[[package]]
+name = "subtle"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
+dependencies = [
+ "smawk",
+ "unicode-linebreak",
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.22",
+]
+
+[[package]]
+name = "time"
+version = "0.2.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
+dependencies = [
+ "const_fn",
+ "libc",
+ "standback",
+ "stdweb",
+ "time-macros",
+ "version_check",
+ "winapi",
+]
+
+[[package]]
+name = "time-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
+dependencies = [
+ "proc-macro-hack",
+ "time-macros-impl",
+]
+
+[[package]]
+name = "time-macros-impl"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "standback",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "toml"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.19.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "trie-rs"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5096c019d49566aff57593a06e401c7f588da84e9a575d0ed2ac0913f51928c0"
+dependencies = [
+ "louds-rs",
+]
+
+[[package]]
+name = "typenum"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
+
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137"
+dependencies = [
+ "hashbrown 0.12.3",
+ "regex",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.87"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.87"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.22",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.87"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.87"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.22",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.87"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
+[[package]]
+name = "winnow"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"

+ 17 - 0
Cargo.toml

@@ -0,0 +1,17 @@
+[package]
+name = "rumia"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+lazy_static = "1.4.0"
+simple-rw-global = "0.4.0"
+nix = "0.26.2"
+toml = "0.7.4"
+serde = { version = "1.0", features = ["derive"] }
+easy-repl = "0.2.1"
+bcrypt = "0.14.0"
+pkg_compile_time = "0.1.3"
+nonblock = "0.2.0"

+ 94 - 0
src/cfg/config.rs

@@ -0,0 +1,94 @@
+use std::collections::HashMap;
+use serde::Deserialize;
+use toml::map::Map;
+use toml::Value;
+use crate::log::logger;
+
+const DEFAULT_PATH_ENV:&str = "/sbin:/usr/sbin:/bin:/usr/bin";
+
+#[derive(Deserialize, Clone)]
+pub struct ConfigDef {
+    initrd_env: Map<String, Value>,
+    env: Map<String, Value>,
+    misc_fs_cfg: MiscFsConfigDef,
+    fstab: Vec<FsItemDef>,
+}
+
+impl ConfigDef {
+    pub fn default() -> ConfigDef {
+        let mut initrd_env = Map::new();
+        initrd_env.insert("path".to_string(), Value::String(DEFAULT_PATH_ENV.to_string()));
+        let env = Map::new();
+        let misc_fs_cfg = MiscFsConfigDef{
+            runfs_option: "size=20%,mode=0755".to_string(),
+            new_root: "/mnt/root_ov".to_string(),
+            new_init: "/init".to_string(),
+            swap: None,
+        };
+        let fstab = Vec::new();
+        ConfigDef{ initrd_env, env, misc_fs_cfg, fstab }
+    }
+
+    fn _get_env(map: &Map<String, Value>, typ: &str) -> HashMap<String, String> {
+        let mut ret_map = HashMap::new();
+        for (k, v) in map {
+            match v {
+                Value::String(val) => {
+                    ret_map.insert(k.clone(), val.clone());
+                }
+                _ => {
+                    logger().warn("env", format!("{} var '{}' is invalid, ignored.", typ, k).as_str())
+                }
+            }
+        }
+        ret_map
+    }
+
+    pub fn get_env(&self) -> HashMap<String, String> {
+        ConfigDef::_get_env(&self.env, "env")
+    }
+
+    pub fn get_initrd_env(&self) -> HashMap<String, String> {
+        ConfigDef::_get_env(&self.initrd_env, "initrd_env")
+    }
+
+    pub fn get_runfs_option(&self) -> String {
+        self.misc_fs_cfg.runfs_option.clone()
+    }
+
+    pub fn get_fstab(&self) -> &Vec<FsItemDef> {
+        &self.fstab
+    }
+
+    pub fn get_new_root(&self) -> String {
+        self.misc_fs_cfg.new_root.clone()
+    }
+
+    pub fn get_new_init(&self) -> String {
+        self.misc_fs_cfg.new_init.clone()
+    }
+
+    pub fn get_swap_dev(&self) -> Option<String> {
+        self.misc_fs_cfg.swap.clone()
+    }
+}
+
+#[derive(Deserialize, Clone)]
+pub struct MiscFsConfigDef {
+    new_root: String,
+    new_init: String,
+    runfs_option: String,
+    swap: Option<String>,
+}
+
+#[derive(Deserialize, Clone)]
+pub struct FsItemDef {
+    pub fstype: Option<String>,
+    pub src: Option<String>,
+    pub target: String,
+    pub option: Option<String>,
+    pub must_mount: Option<bool>,
+    pub pre_mkdir: Option<Vec<String>>,
+    pub post_mkdir: Option<Vec<String>>,
+    pub flags: Option<Vec<String>>,
+}

+ 139 - 0
src/cfg/mod.rs

@@ -0,0 +1,139 @@
+mod config;
+mod rumia;
+
+use std::fmt::{Debug, Display, Formatter};
+use std::fs::File;
+use std::io::Read;
+use std::path::Path;
+use lazy_static::lazy_static;
+use simple_rw_global::GlobalContainer;
+use serde::de::DeserializeOwned;
+use crate::cfg::config::ConfigDef;
+use crate::cfg::rumia::RumiaConDef;
+use crate::log::logger;
+
+const CFG_PATH:&str = "/boot/config/initrd.toml";
+const CONSOLE_CFG_PATH:&str = "/rumia_con.toml";
+
+lazy_static! {
+    pub static ref CFG : GlobalContainer<ConfigManager> = GlobalContainer::new();
+}
+
+pub struct ConfigManager {
+    cfg_content: ConfigDef,
+    rumia_con_content: RumiaConDef,
+}
+
+impl ConfigManager {
+    #[allow(dead_code)]
+    pub fn empty() -> ConfigManager{
+        let rcd = RumiaConDef::default();
+        let bcd = ConfigDef::default();
+        ConfigManager{
+            cfg_content: bcd,
+            rumia_con_content: rcd,
+        }
+    }
+
+    pub fn preload() -> ConfigManager{
+        logger().info("cfg", format!("loading rumia_con config from '{}'...", CONSOLE_CFG_PATH).as_str());
+        let rc_res = ConfigManager::load_file::<RumiaConDef>(CONSOLE_CFG_PATH);
+        let rc_cfg = match rc_res {
+            Ok(s) => {s}
+            Err(err) => {
+                ConfigManager::print_cfg_fail_info(CONSOLE_CFG_PATH, err);
+                RumiaConDef::default()
+            }
+        };
+        logger().debug("cfg", "loading rumia_con config OK.");
+        ConfigManager{cfg_content: ConfigDef::default(), rumia_con_content: rc_cfg}
+    }
+
+    pub fn load_cfg(&mut self){
+        logger().info("cfg", format!("loading rumia initrd config from '{}'...", CFG_PATH).as_str());
+        let cfg_res = ConfigManager::load_file::<ConfigDef>(CFG_PATH);
+        let main_cfg = match cfg_res {
+            Ok(s) => {s}
+            Err(err) => {
+                ConfigManager::print_cfg_fail_info(CFG_PATH, err);
+                ConfigDef::default()
+            }
+        };
+        self.cfg_content = main_cfg;
+        logger().debug("cfg", "loading rumia initrd config OK.");
+    }
+
+    fn load_file<T>(fname: &str) -> Result<T, CfgError>
+        where T: DeserializeOwned,
+    {
+        let fpath = Path::new(fname);
+        let mut file = File::open(fpath)?;
+        let mut toml_str = String::new();
+        file.read_to_string(&mut toml_str)?;
+        let etc = toml::from_str(&toml_str)?;
+        Ok(etc)
+    }
+
+    fn print_cfg_fail_info(cfgname: &str, err: CfgError) {
+        logger().warn("cfg", format!("loading config '{}' failed: {:?}", cfgname, err).as_str());
+        logger().warn("cfg", "rollback to default config for it instead.");
+    }
+
+    pub fn get_cfg(&self) -> &ConfigDef {
+        &self.cfg_content
+    }
+
+    pub fn get_rumia_con_cfg(&self) -> &RumiaConDef {
+        &self.rumia_con_content
+    }
+}
+
+pub fn load_phase1() {
+    let cm = ConfigManager::preload();
+    CFG.set(cm);
+}
+
+pub fn load_phase2() {
+    let mut cm = CFG.get_mut();
+    cm.load_cfg();
+}
+
+
+pub enum CfgError{
+    IOError(std::io::Error),
+    DeserializeError(toml::de::Error),
+}
+
+impl Debug for CfgError {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        match self {
+            CfgError::IOError(e) => {
+                write!(f, "IOError: {:?}", e)
+            }
+            CfgError::DeserializeError(e) => {
+                write!(f, "DeserializeError: {:?}", e)
+            }
+        }
+    }
+}
+
+impl Display for CfgError {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        (self as &dyn Debug).fmt(f)
+    }
+}
+
+impl std::error::Error for CfgError {
+}
+
+impl From<std::io::Error> for CfgError {
+    fn from(value: std::io::Error) -> Self {
+        CfgError::IOError(value)
+    }
+}
+
+impl From<toml::de::Error> for CfgError {
+    fn from(value: toml::de::Error) -> Self {
+        CfgError::DeserializeError(value)
+    }
+}

+ 25 - 0
src/cfg/rumia.rs

@@ -0,0 +1,25 @@
+use serde::Deserialize;
+
+#[derive(Deserialize, Clone)]
+pub struct RumiaConDef {
+    admin: RumiaConAdminDef,
+}
+
+impl RumiaConDef {
+    pub fn default() -> RumiaConDef {
+        RumiaConDef{
+            admin: RumiaConAdminDef {
+                password: "$2a$10$0UEdvSx8SKjDEnntvHgJ8uJjNBDmF5LJjNoJ4.PJ2b3VkenfU3fRS".to_string()
+            }
+        }
+    }
+
+    pub fn get_password_bcrypt(&self) -> String {
+        self.admin.password.clone()
+    }
+}
+
+#[derive(Deserialize, Clone)]
+pub struct RumiaConAdminDef {
+    password: String,
+}

+ 51 - 0
src/env.rs

@@ -0,0 +1,51 @@
+use std::fmt::Display;
+use crate::log::logger;
+use std::str::FromStr;
+
+const DEFAULT_BOOTDEV: &str = "/dev/mmcblk0p1";
+const DEFAULT_BOOTFS: &str = "vfat";
+const DEFAULT_RUMIA_DEBUG: &str = "0";
+
+pub fn get_env_with_default<T>(varname: &str, default: T) -> String
+    where T : ToString + Display
+{
+    let res = std::env::var(varname);
+    match res {
+        Ok(v) => {
+            if v.is_empty() {
+                logger().info("env", format!("use default '{}' value: {}", varname, default).as_str());
+                default.to_string()
+            }else{
+                v
+            }
+        },
+        Err(err) => {
+            logger().warn("env", format!("failed get env var '{}': {}", varname, err).as_str());
+            logger().info("env", format!("use default '{}' value: {}", varname, default).as_str());
+            default.to_string()
+        }
+    }
+}
+
+pub fn get_debug() -> bool {
+    let dbg_str = get_env_with_default("RUMIA_DEBUG", DEFAULT_RUMIA_DEBUG);
+    let res = FromStr::from_str(dbg_str.as_str());
+    let num: u32 = match res {
+        Ok(v) => {
+            v
+        }
+        Err(err) => {
+            logger().warn("env", format!("failed parse env var 'RUMIA_DEBUG': can not convert to u32: {:?}", err).as_str());
+            0
+        }
+    };
+    num > 0
+}
+
+pub fn get_bootdev() -> String {
+    get_env_with_default("bootdev", DEFAULT_BOOTDEV)
+}
+
+pub fn get_bootfs() -> String {
+    get_env_with_default("bootfs", DEFAULT_BOOTFS)
+}

+ 59 - 0
src/exec.rs

@@ -0,0 +1,59 @@
+use std::ffi::{CString};
+use crate::log::logger;
+
+pub fn shell_run_cmd(program: String) {
+    let p = std::process::Command::new(program.clone()).spawn();
+    let r = match p {
+        Ok(mut ch) => {ch.wait()}
+        Err(err) => {
+            logger().warn("mgrsh", format!("failed exec {}: {:?}", program.as_str(), err).as_str());
+            return;
+        }
+    };
+    match r {
+        Ok(ec) => {
+            match ec.code() {
+                None => {
+                    println!("exit with no code.")
+                }
+                Some(c) => {
+                    println!("exit with code {}.", c)
+                }
+            }
+        }
+        Err(err) => {
+            println!("failed run command: {:?}.", err)
+        }
+    }
+}
+
+pub fn unix_execv(path: &str, args: Vec<String>) {
+    let mut sv = Vec::<CString>::new();
+    for i in args {
+        let csi_r = CString::new(i.clone());
+        let csi = match csi_r {
+            Ok(v) => v,
+            Err(err) => {
+                logger().fatal("execv", format!("failed convert arg '{}' into CString: {:?}", i.as_str(), err).as_str());
+                return;
+            }
+        };
+        sv.push(csi);
+    }
+    let ss = sv.as_slice();
+    let cstring_path_res = CString::new(path);
+    let cstring_path = match cstring_path_res {
+        Ok(v) => v,
+        Err(err) => {
+            logger().fatal("execv", format!("failed convert path into CString: {:?}", err).as_str());
+            return;
+        }
+    };
+    let exec_res = nix::unistd::execv(&cstring_path, ss);
+    match exec_res {
+        Ok(_) => {}
+        Err(err) => {
+            logger().fatal("execv", format!("failed execv: {:?}", err).as_str());
+        }
+    }
+}

+ 149 - 0
src/log.rs

@@ -0,0 +1,149 @@
+use std::any::Any;
+use std::fmt::{Debug, Display, Formatter};
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::{RwLockReadGuard};
+use lazy_static::lazy_static;
+use simple_rw_global::{GlobalContainer, GOption};
+use crate::{env, repl};
+
+const PREFIX: &str = "[   @rumia   ]";
+
+lazy_static!{
+    static ref DEBUG_MODE: AtomicBool = AtomicBool::new(false);
+    static ref IN_REPL: AtomicBool = AtomicBool::new(false);
+    static ref LOGGER : GlobalContainer<LogWriter> = GlobalContainer::new();
+}
+
+pub enum LogLevel {
+    #[allow(dead_code)]
+    Debug,
+    #[allow(dead_code)]
+    Info,
+    #[allow(dead_code)]
+    Warn,
+    #[allow(dead_code)]
+    Error,
+    #[allow(dead_code)]
+    Fatal,
+}
+
+impl Display for LogLevel {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        let s = match self {
+            LogLevel::Info => "I",
+            LogLevel::Warn => "W",
+            LogLevel::Error => "E",
+            LogLevel::Fatal => "F",
+            LogLevel::Debug => "D",
+        };
+        write!(f, "{}", s)
+    }
+}
+
+pub trait LogBackend {
+    fn log(&self, module: &str ,lv: LogLevel, msg: &str);
+}
+
+pub struct ConsoleLogBackend{}
+
+impl LogBackend for ConsoleLogBackend {
+    fn log(&self, module: &str, lv: LogLevel, msg: &str) {
+        println!("{} <{}> ({}) {}", PREFIX, lv, module, msg)
+    }
+}
+
+pub struct LogWriter
+{
+    backend: Box<dyn LogBackend + Send + Sync>
+}
+
+impl LogWriter
+{
+
+    #[inline]
+    #[allow(dead_code)]
+    pub fn info(&self, module: &str, msg: &str) {
+        self.backend.log(module,LogLevel::Info, msg);
+    }
+
+    #[inline]
+    #[allow(dead_code)]
+    pub fn warn(&self, module: &str, msg: &str) {
+        self.backend.log(module,LogLevel::Warn, msg);
+    }
+
+    #[inline]
+    #[allow(dead_code)]
+    pub fn error(&self, module: &str, msg: &str) {
+        self.backend.log(module,LogLevel::Error, msg);
+    }
+
+    #[inline]
+    #[allow(dead_code)]
+    pub fn fatal(&self, module: &str, msg: &str) {
+        self.backend.log(module,LogLevel::Fatal, msg);
+        //panic!("module '{}' panic with message: {}", module, msg)
+        if ! IN_REPL.load(Ordering::Relaxed) {
+            repl::fatal_to_shell();
+        }
+    }
+
+    #[inline]
+    #[allow(dead_code)]
+    pub fn chk_fatal<T, E>(&self, op: Result<T, E>, module: &str, msg: &str) -> Option<T>
+        where T: Any, E: Debug
+    {
+        match op {
+            Ok(v) => Some(v),
+            Err(e) => {
+                self.fatal(module, format!("{}: {:?}", msg, e).as_str());
+                None
+            }
+        }
+    }
+
+    #[inline]
+    #[allow(dead_code)]
+    pub fn debug(&self, module: &str, msg: &str) {
+        if DEBUG_MODE.load(Ordering::Relaxed) {
+            self.backend.log(module, LogLevel::Debug, msg);
+        }
+    }
+
+    #[allow(dead_code)]
+    pub fn is_debug_mode() -> bool {
+        DEBUG_MODE.load(Ordering::Relaxed)
+    }
+}
+
+pub fn logger_init(backend: Box<dyn LogBackend + Send + Sync>)
+{
+    LOGGER.set(LogWriter{backend})
+}
+
+pub fn logger<'a>() -> RwLockReadGuard<'a, GOption<LogWriter>>
+{
+    if LOGGER.is_empty() {
+        panic!("use logger before init")
+    }
+    LOGGER.get()
+}
+
+pub fn set_debug_mode(mode: bool) {
+    DEBUG_MODE.store(mode, Ordering::Relaxed);
+}
+
+pub fn print_debug_mode() {
+    let mode = DEBUG_MODE.load(Ordering::Relaxed);
+    let mn = if mode { "on" } else { "off" };
+    logger().info("log", format!("debug mode: {}", mn).as_str());
+}
+
+pub fn set_in_repl(mode: bool) {
+    IN_REPL.store(mode, Ordering::Relaxed);
+}
+
+pub fn set_debug_mode_from_env() {
+    let dbg_mode = env::get_debug();
+    set_debug_mode(dbg_mode);
+}

+ 35 - 0
src/main.rs

@@ -0,0 +1,35 @@
+use pkg_compile_time::{pkg_compile_date, pkg_compile_time};
+use crate::log::{ConsoleLogBackend, logger};
+use crate::op::{makesure, once, seq};
+
+mod log;
+mod mount;
+mod env;
+mod repl;
+mod power;
+mod cfg;
+mod exec;
+mod op;
+mod swroot;
+mod swap;
+
+fn main() {
+    let console_log_backend = Box::new(ConsoleLogBackend{});
+    log::logger_init(console_log_backend);
+    logger().info("main", "ELIP4NG initramfs mounted. This program named 'rumia' will process the pre-init phase.");
+    logger().info("main",format!("this version has been compiled at {} {}", pkg_compile_date!(), pkg_compile_time!()).as_str());
+    log::set_debug_mode_from_env();
+    log::print_debug_mode();
+    once::mount_sysfs();
+    once::mount_proc();
+    once::mount_temporary_devtmpfs();
+    cfg::load_phase1();
+    makesure::mkdir_p("/var/lock");
+    repl::check_enter_pause_to_shell();
+    seq::prepare();
+    seq::fstab_mount();
+    once::turn_on_swap();
+    seq::new_env();
+    seq::move_prepare_mount();
+    swroot::switch_root();
+}

+ 97 - 0
src/mount.rs

@@ -0,0 +1,97 @@
+use std::fmt::Display;
+use nix::mount::{mount, MsFlags};
+use crate::log::logger;
+
+pub fn mount_sysfs() -> nix::Result<()>{
+    let flag = MsFlags::MS_NODEV
+        .union(MsFlags::MS_NOEXEC)
+        .union(MsFlags::MS_NOSUID);
+    mount(Some("sysfs"),"/sys",Some("sysfs"),flag, Some("nodev,noexec,nosuid"))
+}
+
+pub fn mount_proc() -> nix::Result<()>{
+    let flag = MsFlags::MS_NODEV
+        .union(MsFlags::MS_NOEXEC)
+        .union(MsFlags::MS_NOSUID);
+    mount(Some("proc"),"/proc",Some("proc"),flag, Some("nodev,noexec,nosuid"))
+}
+
+pub fn mount_devtmpfs<T1, T2>(target: &str, size: T1, mode: T2) -> nix::Result<()>
+    where T1: Display, T2: Display
+{
+    let flag = MsFlags::empty();
+    let option = format!("size={}, mode={}", size, mode);
+    mount(Some("udev"),target,Some("devtmpfs"),flag, Some(option.as_str()))
+}
+
+pub fn mount_runfs(opt: &str) -> nix::Result<()>
+{
+    let flag = MsFlags::MS_NOSUID;
+    //let flag = MsFlags::empty();
+    let option = if opt.is_empty(){
+        "".to_string()
+    }else{
+        format!("{}", opt)
+    };
+    mount(Some("tmpfs"),"/run",Some("tmpfs"),flag, Some(option.as_str()))
+}
+
+
+pub fn mount_custom(src: Option<&str>, target: &str, fstype: Option<&str>, opt: Option<&str>, flag: MsFlags) -> nix::Result<()>
+{
+    mount(src, target,fstype,flag, opt)
+}
+
+pub fn move_mount(src: &str, target: &str) -> nix::Result<()>{
+    let flag = MsFlags::MS_MOVE;
+    mount(Some(src),target,None as Option<&str>,flag, Some("move"))
+}
+
+pub fn convert_flag_from_string_vec(flags: &Option<Vec<String>>, fsname: &str) -> MsFlags {
+    let mut flag_val = MsFlags::empty();
+    match flags {
+        None => {
+            flag_val
+        }
+        Some(flag_list) => {
+            for fstr in flag_list {
+                match fstr.as_str() {
+                    "bind" => { flag_val = flag_val.union(MsFlags::MS_REC) }
+                    "rbind" => {}
+                    "ro" => { flag_val = flag_val.union(MsFlags::MS_RDONLY) }
+                    "rw" => {}
+                    "nosuid" => { flag_val = flag_val.union(MsFlags::MS_NOSUID) }
+                    "suid" => {}
+                    "nodev" => { flag_val = flag_val.union(MsFlags::MS_NODEV) }
+                    "dev" => {}
+                    "noexec" => { flag_val = flag_val.union(MsFlags::MS_NOEXEC) }
+                    "exec" => {}
+                    "sync" => { flag_val = flag_val.union(MsFlags::MS_SYNCHRONOUS) }
+                    "async" => {}
+                    "noatime" => { flag_val = flag_val.union(MsFlags::MS_NOATIME) }
+                    "atime" => {}
+                    "realtime" => { flag_val = flag_val.union(MsFlags::MS_RELATIME) }
+                    "norealtime" => {}
+                    "nodiratime" => { flag_val = flag_val.union(MsFlags::MS_NODIRATIME) }
+                    "diratime" => {}
+                    "silent" => { flag_val = flag_val.union(MsFlags::MS_SILENT) }
+                    "loud" => {}
+                    "shared" => { flag_val = flag_val.union(MsFlags::MS_SHARED) }
+                    "rshared" => { flag_val = flag_val.union(MsFlags::MS_SHARED).union(MsFlags::MS_REC) }
+                    "slave" => { flag_val = flag_val.union(MsFlags::MS_SLAVE) }
+                    "rslave" => { flag_val = flag_val.union(MsFlags::MS_SLAVE).union(MsFlags::MS_REC) }
+                    "private" => { flag_val = flag_val.union(MsFlags::MS_PRIVATE) }
+                    "rprivate" => { flag_val = flag_val.union(MsFlags::MS_PRIVATE).union(MsFlags::MS_REC) }
+                    "unbindable" => { flag_val = flag_val.union(MsFlags::MS_UNBINDABLE) }
+                    "runbindable" => { flag_val = flag_val.union(MsFlags::MS_UNBINDABLE).union(MsFlags::MS_REC) }
+                    "remount" => { flag_val = flag_val.union(MsFlags::MS_REMOUNT) }
+                    "move" => { flag_val = flag_val.union(MsFlags::MS_MOVE) }
+                    _ => {
+                        logger().warn("mount", format!("unknown flag name '{}' for mounting '{}'", fstr, fsname).as_str());
+                    }
+                }
+            }
+            flag_val
+        }
+    }
+}

+ 34 - 0
src/op/makesure.rs

@@ -0,0 +1,34 @@
+use std::fs;
+use std::fs::DirBuilder;
+use std::os::unix::fs::DirBuilderExt;
+use crate::cfg;
+use crate::log::logger;
+
+pub fn mkdir_p(dir: &str) {
+    logger().debug("mkdir", format!("mkdir '{}'...", dir).as_str());
+    logger().chk_fatal(fs::create_dir_all(dir),"mkdir",format!("failed create dir '{}'", dir).as_str());
+}
+
+pub fn export_initrd_env_from_cfg() {
+    let env_var = cfg::CFG.get().get_cfg().get_initrd_env();
+    for (k, v) in env_var {
+        logger().debug("env", format!("export {}={}", &k, &v).as_str());
+        std::env::set_var(k, v);
+    }
+}
+
+pub fn export_env_from_cfg() {
+    let env_var = cfg::CFG.get().get_cfg().get_env();
+    for (k, v) in env_var {
+        logger().debug("env", format!("export {}={}", &k, &v).as_str());
+        std::env::set_var(k, v);
+    }
+}
+
+pub fn mkdir_p_with_mode(dir: &str, mode: u32) {
+    let mut db = DirBuilder::new();
+    db.recursive(true);
+    db.mode(mode);
+    let r = db.create(dir);
+    logger().chk_fatal(r, "mkdir", format!("failed create dir '{}'", dir).as_str());
+}

+ 3 - 0
src/op/mod.rs

@@ -0,0 +1,3 @@
+pub mod once;
+pub mod makesure;
+pub mod seq;

+ 219 - 0
src/op/once.rs

@@ -0,0 +1,219 @@
+use lazy_static::lazy_static;
+use crate::{cfg, env, mount};
+use crate::log::{logger};
+use std::sync::atomic::{AtomicBool, Ordering};
+use nix::mount::MsFlags;
+use crate::op::makesure::mkdir_p;
+use crate::swap::swap_on;
+
+lazy_static!{
+    static ref PREPARE_OK_SYSFS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_PROC: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_BOOTFS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_TMP_DEVTMPFS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_DEVTMPFS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_DEVPTS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_RUNFS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_MOVE_SYSFS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_MOVE_PROC: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_MOVE_BOOTFS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_MOVE_TMP_DEVTMPFS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_MOVE_RUNFS: AtomicBool = AtomicBool::new(false);
+    static ref PREPARE_OK_SWAPON: AtomicBool = AtomicBool::new(false);
+}
+
+pub fn mount_sysfs() {
+    if PREPARE_OK_SYSFS.load(Ordering::Relaxed) {
+        logger().warn("mount", "The sysfs is already mounted and cannot be repeated.");
+        return;
+    }
+    match mount::mount_sysfs() {
+        Ok(_) => {
+            logger().info("mount", "sysfs mounted at '/sys'.");
+        }
+        Err(err) => {
+            logger().fatal("mount", format!("mount sysfs error: {:?}", err).as_str());
+        }
+    }
+    PREPARE_OK_SYSFS.store(true, Ordering::Relaxed);
+}
+
+pub fn mount_proc() {
+    if PREPARE_OK_PROC.load(Ordering::Relaxed) {
+        logger().warn("mount", "The proc is already mounted and cannot be repeated.");
+        return;
+    }
+    match mount::mount_proc() {
+        Ok(_) => {
+            logger().info("mount", "sysfs mounted at '/sys'.");
+        }
+        Err(err) => {
+            logger().fatal("mount", format!("mount sysfs error: {:?}", err).as_str());
+        }
+    }
+    PREPARE_OK_PROC.store(true, Ordering::Relaxed);
+}
+
+pub fn mount_bootfs() {
+    if PREPARE_OK_BOOTFS.load(Ordering::Relaxed) {
+        logger().warn("mount", "The '/boot' is already mounted and cannot be repeated.");
+        return;
+    }
+    let bootdev = env::get_bootdev();
+    let bootfs = env::get_bootfs();
+    logger().info("mount", format!("boot_device={}, fstype={}", bootdev, bootfs).as_str());
+    match mount::mount_custom(Some(bootdev.as_str()), "/boot", Some(bootfs.as_str()), None, MsFlags::MS_RDONLY) {
+        Ok(_) => {
+            logger().info("mount", format!("dev '{}' ({}) mounted at '/boot'", bootdev, bootfs).as_str());
+        }
+        Err(err) => {
+            logger().fatal("mount", format!("mount '/boot' error: {:?}", err).as_str());
+        }
+    }
+    PREPARE_OK_BOOTFS.store(true, Ordering::Relaxed);
+}
+
+pub fn mount_temporary_devtmpfs() {
+    if PREPARE_OK_TMP_DEVTMPFS.load(Ordering::Relaxed) {
+        logger().warn("mount", "The devtmpfs for initrd temporary usage is already mounted and cannot be repeated.");
+        return;
+    }
+    match mount::mount_devtmpfs("/dev","1M", "0755") {
+        Ok(_) => {
+            logger().info("mount", "devtmpfs mounted at '/dev'.");
+        }
+        Err(err) => {
+            logger().fatal("mount", format!("mount devtmpfs for initrd temporary usage error: {:?}", err).as_str());
+        }
+    }
+    PREPARE_OK_TMP_DEVTMPFS.store(true, Ordering::Relaxed);
+}
+
+pub fn mount_runfs(opt: &str) {
+    if PREPARE_OK_RUNFS.load(Ordering::Relaxed) {
+        logger().warn("mount", "The '/run' is already mounted and cannot be repeated.");
+        return;
+    }
+    match mount::mount_runfs(opt) {
+        Ok(_) => {
+            logger().info("mount", "'/run' mounted.");
+        }
+        Err(err) => {
+            logger().fatal("mount", format!("mount '/run' error: {:?}", err).as_str());
+        }
+    }
+    PREPARE_OK_RUNFS.store(true, Ordering::Relaxed);
+}
+
+pub fn mount_runfs_from_cfg() {
+    let opt = cfg::CFG.get().get_cfg().get_runfs_option();
+    mount_runfs(opt.as_str())
+}
+
+pub fn move_sysfs(target: &str) {
+    if PREPARE_OK_MOVE_SYSFS.load(Ordering::Relaxed) {
+        logger().warn("mount", "The sysfs is already moved and cannot be repeated.");
+        return;
+    }
+    mkdir_p(target);
+    match mount::move_mount("/sys", target) {
+        Ok(_) => {
+            logger().info("mount", format!("sysfs mount point moved to '{}'.", target).as_str());
+        }
+        Err(err) => {
+            logger().fatal("mount", format!("move sysfs mount error: {:?}", err).as_str());
+        }
+    }
+    PREPARE_OK_MOVE_SYSFS.store(true, Ordering::Relaxed);
+}
+
+pub fn move_proc(target: &str) {
+    if PREPARE_OK_MOVE_PROC.load(Ordering::Relaxed) {
+        logger().warn("mount", "The proc is already moved and cannot be repeated.");
+        return;
+    }
+    mkdir_p(target);
+    match mount::move_mount("/proc", target) {
+        Ok(_) => {
+            logger().info("mount", format!("proc mount point moved to '{}'.", target).as_str());
+        }
+        Err(err) => {
+            logger().fatal("mount", format!("move proc mount error: {:?}", err).as_str());
+        }
+    }
+    PREPARE_OK_MOVE_PROC.store(true, Ordering::Relaxed);
+}
+
+pub fn move_bootfs(target: &str) {
+    if PREPARE_OK_MOVE_BOOTFS.load(Ordering::Relaxed) {
+        logger().warn("mount", "The '/boot' is already moved and cannot be repeated.");
+        return;
+    }
+    mkdir_p(target);
+    match mount::move_mount("/boot", target) {
+        Ok(_) => {
+            logger().info("mount", format!("'/boot' mount point moved to '{}'.", target).as_str());
+        }
+        Err(err) => {
+            logger().fatal("mount", format!("move '/boot' mount error: {:?}", err).as_str());
+        }
+    }
+    PREPARE_OK_MOVE_BOOTFS.store(true, Ordering::Relaxed);
+}
+
+pub fn move_temporary_devtmpfs(newroot: &str) {
+    if PREPARE_OK_MOVE_TMP_DEVTMPFS.load(Ordering::Relaxed) {
+        logger().warn("mount", "The temporary devtmpfs for initrd is already moved and cannot be repeated.");
+        return;
+    }
+    if !PREPARE_OK_TMP_DEVTMPFS.load(Ordering::Relaxed) {
+        logger().warn("mount", "The temporary devtmpfs for initrd has been never mounted.");
+        return;
+    }
+    let move_target = format!("{}/mnt/old-dev", newroot);
+    mkdir_p(move_target.as_str());
+    match mount::move_mount("/dev", move_target.as_str()) {
+        Ok(_) => {
+            logger().info("mount", format!("'/dev' mount point moved to '{}'.", move_target).as_str());
+            PREPARE_OK_MOVE_TMP_DEVTMPFS.store(true, Ordering::Relaxed);
+        }
+        Err(err) => {
+            logger().warn("mount", format!("move '/dev' mount error: {:?}", err).as_str());
+        }
+    }
+}
+
+pub fn move_run(target: &str) {
+    if PREPARE_OK_MOVE_RUNFS.load(Ordering::Relaxed) {
+        logger().warn("mount", "The '/run' is already moved and cannot be repeated.");
+        return;
+    }
+    mkdir_p(target);
+    match mount::move_mount("/run", target) {
+        Ok(_) => {
+            logger().info("mount", format!("'/run' mount point moved to '{}'.", target).as_str());
+        }
+        Err(err) => {
+            logger().fatal("mount", format!("move '/run' mount error: {:?}", err).as_str());
+        }
+    }
+    PREPARE_OK_MOVE_RUNFS.store(true, Ordering::Relaxed);
+}
+
+pub fn turn_on_swap() {
+    if PREPARE_OK_SWAPON.load(Ordering::Relaxed) {
+        logger().warn("swap", "swap is already turned on and cannot be repeated.");
+        return;
+    }
+    let swap_dev = cfg::CFG.get().get_cfg().get_swap_dev();
+    match swap_dev {
+        None => {
+            logger().info("swap", "no swap specified in config file. ignored.")
+        }
+        Some(sw) => {
+            logger().info("swap", format!("turn on swap on '{}'...", sw.as_str()).as_str());
+            swap_on(sw.as_str());
+            PREPARE_OK_SWAPON.store(true, Ordering::Relaxed);
+        }
+    }
+}

+ 189 - 0
src/op/seq.rs

@@ -0,0 +1,189 @@
+use std::fs;
+use lazy_static::lazy_static;
+use crate::log::{logger};
+use std::sync::atomic::{AtomicBool, Ordering};
+use crate::op::{makesure, once};
+use crate::{cfg};
+use crate::mount::{convert_flag_from_string_vec, mount_custom};
+
+lazy_static!{
+    static ref SEQ_OK_PREPARE: AtomicBool = AtomicBool::new(false);
+    static ref SEQ_OK_FSMOUNT: AtomicBool = AtomicBool::new(false);
+    static ref SEQ_OK_NEWENV: AtomicBool = AtomicBool::new(false);
+    static ref SEQ_OK_MOVEMNT: AtomicBool = AtomicBool::new(false);
+}
+
+pub fn prepare() {
+    if SEQ_OK_PREPARE.load(Ordering::Relaxed) {
+        logger().warn("seq", "The sequence 'prepare' is already executed. Ignored.");
+        return;
+    }
+    makesure::mkdir_p("/boot");
+    once::mount_bootfs();
+    cfg::load_phase2();
+    makesure::export_initrd_env_from_cfg();
+    once::mount_runfs_from_cfg();
+    SEQ_OK_PREPARE.store(true, Ordering::Relaxed);
+}
+
+pub fn fstab_mount() {
+    if SEQ_OK_FSMOUNT.load(Ordering::Relaxed) {
+        logger().warn("seq", "The sequence 'fstab-mount' is already executed. Ignored.");
+        return;
+    }
+    let cfg_inst = cfg::CFG.get();
+    let fstab = cfg_inst.get_cfg().get_fstab();
+    'mount_fs:
+    for item in fstab {
+        let m_must_mount = match item.must_mount {
+            None => false,
+            Some(v) => v,
+        };
+        let m_src = match &item.src {
+            None => None,
+            Some(v) => Some(v.as_str())
+        };
+        let m_fstype = match &item.fstype {
+            None => None,
+            Some(v) => Some(v.as_str())
+        };
+        let m_opt = match &item.option {
+            None => None,
+            Some(v) => Some(v.as_str())
+        };
+        let m_target = (&item.target).as_str();
+        let m_flg = convert_flag_from_string_vec(&item.flags, m_target);
+        let d_src = match &item.src {
+            None => "<none>",
+            Some(v) => {v.as_str()}
+        };
+        let d_fstype = match &item.fstype {
+            None => "<none>",
+            Some(v) => {v.as_str()}
+        };
+        let d_opt = match &item.option {
+            None => "<none>",
+            Some(v) => {v.as_str()}
+        };
+        match &item.pre_mkdir {
+            None => {}
+            Some(v) => {
+                for pmi in v.clone() {
+                    let mkr = fs::create_dir_all(pmi.as_str());
+                    match mkr {
+                        Ok(_) => {}
+                        Err(err) => {
+                            if m_must_mount{
+                                logger().fatal("fstab", format!(
+                                    "failed mount '{}': failed in creating pre-mount dir '{}': {:?}",
+                                    d_src,
+                                    pmi.as_str(),
+                                    err
+                                ).as_str())
+                            }else {
+                                logger().warn("fstab", format!(
+                                    "failed mount '{}': failed in creating pre-mount dir '{}': {:?}",
+                                    d_src,
+                                    m_target,
+                                    err
+                                ).as_str());
+                                continue 'mount_fs;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        let r = mount_custom(m_src, m_target, m_fstype, m_opt, m_flg);
+        match r {
+            Ok(_) => {
+                logger().debug("fstab", format!(
+                    "mounted '{}' at '{}' with fstype='{}', option='{}', flags={:#x}.",
+                    d_src,
+                    m_target,
+                    d_fstype,
+                    d_opt,
+                    m_flg,
+                ).as_str())
+            }
+            Err(err) => {
+                if m_must_mount {
+                    logger().fatal("fstab", format!(
+                        "failed mount '{}' at '{}' with fstype='{}', option='{}', flags={:#x}: {:?}",
+                        d_src,
+                        m_target,
+                        d_fstype,
+                        d_opt,
+                        m_flg,
+                        err
+                    ).as_str());
+                    continue 'mount_fs;
+                }else{
+                    logger().warn("fstab", format!(
+                        "failed mount '{}' at '{}' with fstype='{}', option='{}', flags={:#x}: {:?}",
+                        d_src,
+                        m_target,
+                        d_fstype,
+                        d_opt,
+                        m_flg,
+                        err
+                    ).as_str());
+                    continue 'mount_fs;
+                }
+            }
+        }
+        match &item.post_mkdir {
+            None => {}
+            Some(v) => {
+                for pmi in v.clone() {
+                    let mkr = fs::create_dir_all(pmi.as_str());
+                    match mkr {
+                        Ok(_) => {}
+                        Err(err) => {
+                            if m_must_mount{
+                                logger().fatal("fstab", format!(
+                                    "failed mount '{}': failed in creating post-mount dir '{}': {:?}",
+                                    d_src,
+                                    pmi.as_str(),
+                                    err
+                                ).as_str())
+                            }else {
+                                logger().warn("fstab", format!(
+                                    "failed mount '{}': failed in creating post-mount dir '{}': {:?}",
+                                    d_src,
+                                    m_target,
+                                    err
+                                ).as_str());
+                                continue 'mount_fs;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    SEQ_OK_FSMOUNT.store(true, Ordering::Relaxed);
+}
+
+pub fn new_env() {
+    if SEQ_OK_NEWENV.load(Ordering::Relaxed) {
+        logger().warn("seq", "The sequence 'new-env' is already executed. Ignored.");
+        return;
+    }
+    makesure::export_env_from_cfg();
+    SEQ_OK_NEWENV.store(true, Ordering::Relaxed)
+}
+
+pub fn move_prepare_mount() {
+    if SEQ_OK_MOVEMNT.load(Ordering::Relaxed) {
+        logger().warn("seq", "The sequence 'move-mnt' is already executed. Ignored.");
+        return;
+    }
+    let new_root = cfg::CFG.get().get_cfg().get_new_root();
+    once::move_sysfs(format!("{}/sys", new_root).as_str());
+    once::move_proc(format!("{}/proc", new_root).as_str());
+    once::move_bootfs(format!("{}/boot", new_root).as_str());
+    once::move_run(format!("{}/run", new_root).as_str());
+    once::move_temporary_devtmpfs(new_root.as_str());
+    SEQ_OK_MOVEMNT.store(true, Ordering::Relaxed)
+}

+ 33 - 0
src/power.rs

@@ -0,0 +1,33 @@
+use nix::sys::reboot::RebootMode;
+
+pub fn shutdown()  -> !{
+    println!("system shutting down...");
+    let _ = nix::sys::reboot::reboot(RebootMode::RB_POWER_OFF);
+    loop {
+    }
+}
+
+pub fn reboot() -> ! {
+    println!("system rebooting...");
+    let _ = nix::sys::reboot::reboot(RebootMode::RB_AUTOBOOT);
+    loop {
+    }
+}
+
+pub fn safe_shutdown() -> ! {
+    sync();
+    sync();
+    sync();
+    shutdown()
+}
+
+pub fn safe_reboot() -> ! {
+    sync();
+    sync();
+    sync();
+    reboot()
+}
+
+pub fn sync() {
+    nix::unistd::sync();
+}

+ 102 - 0
src/repl/mgrsh.rs

@@ -0,0 +1,102 @@
+use easy_repl::{command, CommandStatus, Repl};
+use crate::{exec, op};
+use crate::repl::prepare::prepare_view;
+use crate::repl::schedule_switch_root;
+
+pub fn mgr_shell() {
+    let repl_bresult = Repl::builder()
+        .description("rumia-cli system view: /")
+        .prompt("[ rumia-cli: / ] ")
+        .add("checklist", command! {
+            "print a checklist for sequences should be done for initrd",
+            () => || {
+                println!("Prepare Sequence:\n\
+                    do-prepare\n\
+                    do-fstab-mount\n\
+                    swapon\n\
+                    do-new-env\n\
+                    do-move-mnt\n\
+                ");
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("exec", command! {
+            "run a command, without arguments",
+            (shell: String) => |shell:String| {
+                exec::shell_run_cmd(shell);
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("sh", command! {
+            "run /bin/sh",
+            () => || {
+                exec::shell_run_cmd("/bin/sh".to_string());
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("do-prepare", command! {
+            "do the sequence 'prepare'",
+            () => || {
+                op::seq::prepare();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("prepare-view", command! {
+            "enter the view 'prepare'",
+            () => || {
+                prepare_view();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("do-fstab-mount", command! {
+            "do the sequence 'fstab-mount'",
+            () => || {
+                op::seq::fstab_mount();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("do-new-env", command! {
+            "do the sequence 'new-env'",
+            () => || {
+                op::seq::new_env();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("do-move-mnt", command! {
+            "do the sequence 'move-mnt'",
+            () => || {
+                op::seq::move_prepare_mount();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("swapon", command! {
+            "turn on swap with config",
+            () => || {
+                op::once::turn_on_swap();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("switch-root", command! {
+            "switch to new root",
+            () => || {
+                schedule_switch_root();
+                Ok(CommandStatus::Quit)
+            }
+        })
+        .build();
+    let mut repl = match repl_bresult {
+        Ok(t) => t,
+        Err(err) => {
+            println!("[ERROR] admin Shell Init Fatal Error: {:?}", err);
+            return;
+        }
+    };
+    let repl_run_result = repl.run();
+    match repl_run_result {
+        Ok(_) => {}
+        Err(err) => {
+            println!("[ERROR] this view crash by error: {:?}", err);
+            println!("back to parent view...");
+        }
+    };
+}

+ 183 - 0
src/repl/mod.rs

@@ -0,0 +1,183 @@
+mod mgrsh;
+mod prepare;
+
+use std::{thread, time};
+use easy_repl::{command, Repl, CommandStatus};
+use easy_repl::repl::BuilderError;
+use lazy_static::lazy_static;
+use nonblock::NonBlockingReader;
+use crate::{cfg, log};
+use crate::repl::mgrsh::mgr_shell;
+use crate::power;
+use std::sync::atomic::{AtomicBool, Ordering};
+use crate::swroot::switch_root;
+
+lazy_static!{
+    static ref DO_SWITCH_ROOT_AFTER_QUIT: AtomicBool = AtomicBool::new(false);
+}
+
+pub fn build_repl_shell<'a>() -> Result<Repl<'a>, BuilderError> {
+    Repl::builder()
+        .description("rumia-cli operator view")
+        .prompt("< rumia-cli > ")
+        .add("print", command! {
+            "print what input",
+            (msg: String) => |msg:String| {
+                println!("{}", msg.as_str());
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("reboot", command! {
+            "reboot system",
+            () => || {
+                power::safe_reboot();
+            }
+        })
+        .add("shutdown", command! {
+            "shutdown system",
+            () => || {
+                power::safe_shutdown();
+            }
+        })
+        .add("debug-on", command! {
+            "turn on debug printing for rumia",
+            () => || {
+                log::set_debug_mode(true);
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("debug-off", command! {
+            "turn off debug printing for rumia",
+            () => || {
+                log::set_debug_mode(false);
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("sys", command! {
+            "login to system view",
+            (password: String) => |password:String| {
+                let bhash = cfg::CFG.get().get_rumia_con_cfg().get_password_bcrypt();
+                let res = bcrypt::verify(password, &bhash);
+                match res {
+                    Ok(b) => {
+                        if b {
+                            mgr_shell();
+                        }else{
+                            println!("incorrect password.")
+                        }
+                    }
+                    Err(err) => {
+                        println!("failed verify password: {:?}", err)
+                    }
+                }
+                if DO_SWITCH_ROOT_AFTER_QUIT.load(Ordering::Relaxed) {
+                    Ok(CommandStatus::Quit)
+                }else{
+                    Ok(CommandStatus::Done)
+                }
+            }
+        })
+        .build()
+}
+
+pub fn fatal_to_shell() {
+    DO_SWITCH_ROOT_AFTER_QUIT.store(false, Ordering::Relaxed);
+    let repl_bresult= build_repl_shell();
+    let mut repl = match repl_bresult {
+        Ok(t) => t,
+        Err(err) => {
+            panic!("rumia shell init panic: {:?}", err);
+        }
+    };
+    println!("Pre-init process aborted by fatal error.");
+    println!("Now entering into the rumia shell...");
+    loop {
+        log::set_in_repl(true);
+        let repl_run_result = repl.run();
+        log::set_in_repl(false);
+        match repl_run_result {
+            Ok(_) => {
+                if DO_SWITCH_ROOT_AFTER_QUIT.load(Ordering::Relaxed) {
+                    switch_root();
+                }else{
+                    println!("[WARN] You shouldn't quit this shell now,\
+                     because of pre-init process aborted by fatal error. \
+                     You may need to fix some problems or you can just use \
+                     reboot or shutdown command to exit this shell.");
+                    println!("shell will restart");
+                }
+            }
+            Err(err) => {
+                println!("[ERROR] shell crash by error: {:?}", err);
+                println!("shell will restart");
+            }
+        };
+    }
+}
+
+pub fn user_pause_to_shell() {
+    DO_SWITCH_ROOT_AFTER_QUIT.store(false, Ordering::Relaxed);
+    let repl_bresult= build_repl_shell();
+    let mut repl = match repl_bresult {
+        Ok(t) => t,
+        Err(err) => {
+            panic!("rumia shell init panic: {:?}", err);
+        }
+    };
+    println!("Pre-init process paused by user press <Enter>.");
+    println!("Now entering into the rumia shell...");
+    log::set_in_repl(true);
+    let repl_run_result = repl.run();
+    log::set_in_repl(false);
+    match repl_run_result {
+        Ok(_) => {
+            if DO_SWITCH_ROOT_AFTER_QUIT.load(Ordering::Relaxed) {
+                switch_root();
+            }else {
+                println!("continue pre-init process...");
+            }
+        }
+        Err(err) => {
+            println!("[ERROR] shell crash by error: {:?}", err);
+            println!("system will restart");
+            thread::sleep(time::Duration::from_secs(2));
+            power::safe_reboot();
+        }
+    };
+}
+
+pub fn check_user_pause() -> bool {
+    let nb_reader_res = NonBlockingReader::from_fd(std::io::stdin());
+    let mut nb_reader = match nb_reader_res {
+        Ok(r) => {r}
+        Err(err) => {
+            panic!("failed make stdin unblocking: {:?}", err)
+        }
+    };
+    let mut rstr = String::new();
+    let read_res = nb_reader.read_available_to_string(&mut rstr);
+    nb_reader.into_blocking().expect("failed turn stdin into blocking mode.");
+    match read_res {
+        Ok(len) => {
+            if len > 0 {
+                true
+            }else{
+                false
+            }
+        }
+        Err(_) => {
+            false
+        }
+    }
+}
+
+pub fn check_enter_pause_to_shell() {
+    let r = check_user_pause();
+    if r {
+        user_pause_to_shell();
+    }
+}
+
+pub fn schedule_switch_root() {
+    DO_SWITCH_ROOT_AFTER_QUIT.store(true, Ordering::Relaxed);
+}

+ 86 - 0
src/repl/prepare.rs

@@ -0,0 +1,86 @@
+use easy_repl::{command, CommandStatus, Repl};
+use crate::{cfg};
+use crate::op::{makesure, once};
+
+pub fn prepare_view() {
+    let repl_bresult = Repl::builder()
+        .description("rumia-cli system view: /prepare")
+        .prompt("[ rumia-cli: /prepare ] ")
+        .add("checklist", command! {
+            "print a checklist for prepare sequence",
+            () => || {
+                println!("Prepare Sequence:\n\
+                    sysfs-mount\n\
+                    proc-mount\n\
+                    bootfs-mount\n\
+                    cfg-phase2-load\n\
+                    initrd-env-load\n\
+                    run-mount-from-cfg\
+                ");
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("bootfs-mount", command! {
+            "mount /boot",
+            () => || {
+                makesure::mkdir_p("/boot");
+                once::mount_bootfs();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("cfg-phase2-load", command! {
+            "load rumia config phase 2",
+            () => || {
+                cfg::load_phase2();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("initrd-env-load", command! {
+            "load rumia config phase 2",
+            () => || {
+                makesure::export_initrd_env_from_cfg();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("env-load", command! {
+            "load rumia config phase 2",
+            () => || {
+                makesure::export_env_from_cfg();
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("run-mount-cli", command! {
+            "mount '/run' with given option",
+            (option: String) => |option:String| {
+                makesure::mkdir_p("/run");
+                once::mount_runfs(option.as_str());
+                makesure::mkdir_p_with_mode("/run/initramfs", 0o755);
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("run-mount-from-cfg", command! {
+            "mount '/run' with config",
+            () => || {
+                makesure::mkdir_p("/run");
+                once::mount_runfs_from_cfg();
+                makesure::mkdir_p_with_mode("/run/initramfs", 0o755);
+                Ok(CommandStatus::Done)
+            }
+        })
+        .build();
+    let mut repl = match repl_bresult {
+        Ok(t) => t,
+        Err(err) => {
+            println!("[ERROR] fatal error when initializing this view: {:?}", err);
+            return;
+        }
+    };
+    let repl_run_result = repl.run();
+    match repl_run_result {
+        Ok(_) => {}
+        Err(err) => {
+            println!("[ERROR] this view crash by error: {:?}", err);
+            println!("back to parent view...");
+        }
+    };
+}

+ 23 - 0
src/swap.rs

@@ -0,0 +1,23 @@
+use std::ffi::{CString};
+use nix::libc::swapon;
+use crate::log::logger;
+
+pub fn swap_on(dev: &str) {
+    let cstr_res = CString::new(dev.clone());
+    let cstr = match cstr_res {
+        Ok(v) => v,
+        Err(err) => {
+            logger().warn("swap", format!("failed convert dev path '{}' to CString: {:?}", dev, err).as_str());
+            return;
+        }
+    };
+    let ret = unsafe {
+         swapon(cstr.as_ptr(),0)
+    };
+    if ret != 0 {
+        let eno = nix::errno::from_i32(ret);
+        logger().warn("swap", format!("failed turn on swap'{}': {:?}", dev, eno).as_str());
+    }else{
+        logger().info("swap", format!("turn on swap '{}' ok.", dev).as_str());
+    }
+}

+ 18 - 0
src/swroot.rs

@@ -0,0 +1,18 @@
+use crate::cfg;
+use crate::exec::unix_execv;
+use crate::log::logger;
+
+pub fn switch_root() {
+    let new_root = cfg::CFG.get().get_cfg().get_new_root();
+    let new_init = cfg::CFG.get().get_cfg().get_new_init();
+    let mut args = Vec::<String>::new();
+    args.push("switch_root".to_string());
+    args.push(new_root.clone());
+    args.push(new_init.clone());
+    logger().info("switch-root", format!(
+        "switching to new root '{}' with new init '{}'...",
+        new_root.as_str(),
+        new_init.as_str()
+    ).as_str());
+    unix_execv("/usr/sbin/switch_root", args)
+}