Refactoring:
- Split into workspace crates - Split into two binaries `corebox` and `hashbox` - Add `mount` crate to workspace to prepare for third binary `utilbox`
This commit is contained in:
parent
59b80e3b85
commit
06b88d2c24
396
Cargo.lock
generated
396
Cargo.lock
generated
@ -2,6 +2,24 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
@ -25,12 +43,39 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bindgen"
|
||||||
|
version = "0.58.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f8523b410d7187a43085e7e064416ea32ded16bd0a4e6fc025e21616d01258f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cexpr",
|
||||||
|
"clang-sys",
|
||||||
|
"clap 2.34.0",
|
||||||
|
"env_logger",
|
||||||
|
"lazy_static",
|
||||||
|
"lazycell",
|
||||||
|
"log",
|
||||||
|
"peeking_take_while",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"rustc-hash",
|
||||||
|
"shlex",
|
||||||
|
"which",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags-mini"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "blake2b_simd"
|
name = "blake2b_simd"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -42,6 +87,30 @@ dependencies = [
|
|||||||
"constant_time_eq",
|
"constant_time_eq",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blkid"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4f68440dfd06d6a97a56f8e67729316f33c7e52c31f59f16f6e9641777702bb7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"blkid-sys",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"strum",
|
||||||
|
"strum_macros",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blkid-sys"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d31e0255bb872b7d67a444b670eb55b5b2b46d59c70ab0376e2e04737c7a489e"
|
||||||
|
dependencies = [
|
||||||
|
"bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
@ -57,12 +126,47 @@ version = "1.0.79"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cexpr"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
|
||||||
|
dependencies = [
|
||||||
|
"nom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clang-sys"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3"
|
||||||
|
dependencies = [
|
||||||
|
"glob",
|
||||||
|
"libc",
|
||||||
|
"libloading",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "2.34.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"atty",
|
||||||
|
"bitflags",
|
||||||
|
"strsim 0.8.0",
|
||||||
|
"textwrap 0.11.0",
|
||||||
|
"unicode-width",
|
||||||
|
"vec_map",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.1.4"
|
version = "4.1.4"
|
||||||
@ -72,7 +176,7 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
"is-terminal",
|
"is-terminal",
|
||||||
"strsim",
|
"strsim 0.10.0",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -82,7 +186,7 @@ version = "4.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d6540eedc41f8a5a76cf3d8d458057dcdf817be4158a55b5f861f7a5483de75"
|
checksum = "3d6540eedc41f8a5a76cf3d8d458057dcdf817be4158a55b5f861f7a5483de75"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap 4.1.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -91,7 +195,7 @@ version = "0.1.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c7fa41f5e6aa83bd151b70fd0ceaee703d68cd669522795dc812df9edad1252c"
|
checksum = "c7fa41f5e6aa83bd151b70fd0ceaee703d68cd669522795dc812df9edad1252c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap 4.1.4",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -110,7 +214,7 @@ version = "0.2.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb258c6232b4d728d13d6072656627924c16707aae6267cd5a1ea05abff9a25c"
|
checksum = "eb258c6232b4d728d13d6072656627924c16707aae6267cd5a1ea05abff9a25c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap 4.1.4",
|
||||||
"roff",
|
"roff",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -155,6 +259,19 @@ dependencies = [
|
|||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
"termcolor",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
@ -186,6 +303,21 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
@ -201,6 +333,12 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
|
checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-lifetimes"
|
name = "io-lifetimes"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
@ -223,18 +361,49 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazycell"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.139"
|
version = "0.2.139"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md-5"
|
name = "md-5"
|
||||||
version = "0.10.5"
|
version = "0.10.5"
|
||||||
@ -244,18 +413,102 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mount"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"blkid",
|
||||||
|
"sc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "5.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_str_bytes"
|
name = "os_str_bytes"
|
||||||
version = "6.4.1"
|
version = "6.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "peeking_take_while"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.51"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pw"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roff"
|
name = "roff"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316"
|
checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.36.8"
|
version = "0.36.8"
|
||||||
@ -270,6 +523,12 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@ -312,8 +571,9 @@ name = "shitbox"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
|
"bitflags-mini",
|
||||||
"blake2b_simd",
|
"blake2b_simd",
|
||||||
"clap",
|
"clap 4.1.4",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
"clap_complete_nushell",
|
"clap_complete_nushell",
|
||||||
"clap_mangen",
|
"clap_mangen",
|
||||||
@ -321,26 +581,72 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
"libc",
|
"libc",
|
||||||
"md-5",
|
"md-5",
|
||||||
|
"mount",
|
||||||
|
"pw",
|
||||||
"sc",
|
"sc",
|
||||||
"sha1",
|
"sha1",
|
||||||
"sha2",
|
"sha2",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"textwrap",
|
"textwrap 0.16.0",
|
||||||
|
"unistd",
|
||||||
|
"unix-mode",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smawk"
|
name = "smawk"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
|
checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.23.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.107"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -350,6 +656,15 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.16.0"
|
version = "0.16.0"
|
||||||
@ -359,12 +674,72 @@ dependencies = [
|
|||||||
"smawk",
|
"smawk",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
|
[[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 = "unistd"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"sc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unix-mode"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags-mini",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vec_map"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
@ -382,6 +757,15 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "which"
|
||||||
|
version = "3.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
39
Cargo.toml
39
Cargo.toml
@ -3,7 +3,20 @@ name = "shitbox"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
[workspace]
|
||||||
|
members = [ "bitflags-mini", "mount", "pw", "unistd", "unix-mode" ]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "corebox"
|
||||||
|
path = "corebox/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "hashbox"
|
||||||
|
path = "hashbox/main.rs"
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
libc = "0.2"
|
||||||
|
sc = "0.2"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
@ -14,15 +27,33 @@ clap_complete_nushell = "0.1"
|
|||||||
clap_mangen = "0.2"
|
clap_mangen = "0.2"
|
||||||
data-encoding = "2.3"
|
data-encoding = "2.3"
|
||||||
digest = "0.10.6"
|
digest = "0.10.6"
|
||||||
libc = "0.2"
|
libc = { workspace = true }
|
||||||
md-5 = "0.10"
|
md5 = { version = "0.10", package = "md-5" }
|
||||||
sc = "0.2"
|
sc = { workspace = true }
|
||||||
sha1 = "0.10"
|
sha1 = "0.10"
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
termcolor = "1.1"
|
termcolor = "1.1"
|
||||||
textwrap = { version = "0.16", default-features = false, features = ["smawk"] }
|
textwrap = { version = "0.16", default-features = false, features = ["smawk"] }
|
||||||
walkdir = "2.3"
|
walkdir = "2.3"
|
||||||
|
|
||||||
|
[dependencies.bitflags]
|
||||||
|
package = "bitflags-mini"
|
||||||
|
path = "bitflags-mini"
|
||||||
|
|
||||||
|
[dependencies.unistd]
|
||||||
|
package = "unistd"
|
||||||
|
path = "unistd"
|
||||||
|
|
||||||
|
[dependencies.mode]
|
||||||
|
package = "unix-mode"
|
||||||
|
path = "unix-mode"
|
||||||
|
|
||||||
|
[dependencies.mount]
|
||||||
|
path = "mount"
|
||||||
|
|
||||||
|
[dependencies.pw]
|
||||||
|
path = "pw"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
strip = true
|
strip = true
|
||||||
|
8
bitflags-mini/Cargo.toml
Normal file
8
bitflags-mini/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "bitflags-mini"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
@ -1,5 +1,5 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::args;
|
use shitbox::args;
|
||||||
use clap::{value_parser, Arg, ArgAction, Command};
|
use clap::{value_parser, Arg, ArgAction, Command};
|
||||||
use data_encoding::BASE32;
|
use data_encoding::BASE32;
|
||||||
use std::{
|
use std::{
|
||||||
@ -68,8 +68,8 @@ impl Cmd for Base32 {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -63,8 +63,8 @@ impl Cmd for Base64 {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -41,7 +41,7 @@ impl Cmd for Basename {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -154,7 +154,7 @@ impl Cmd for Bootstrap {
|
|||||||
fn run(&self, matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
|
fn run(&self, matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||||
if let Some(prefix) = matches.get_one::<String>("prefix") {
|
if let Some(prefix) = matches.get_one::<String>("prefix") {
|
||||||
let usr = matches.get_flag("usr");
|
let usr = matches.get_flag("usr");
|
||||||
if let Some(progpath) = crate::progpath() {
|
if let Some(progpath) = shitbox::progpath() {
|
||||||
let mut outpath = PathBuf::from(prefix);
|
let mut outpath = PathBuf::from(prefix);
|
||||||
outpath.push("bin");
|
outpath.push("bin");
|
||||||
println!("Installing binary:");
|
println!("Installing binary:");
|
||||||
@ -191,7 +191,7 @@ impl Cmd for Bootstrap {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,16 +239,16 @@ impl BootstrapCmd for dyn Cmd {
|
|||||||
if let Some(linkpath) = self.linkpath(prefix, usr) {
|
if let Some(linkpath) = self.linkpath(prefix, usr) {
|
||||||
if soft {
|
if soft {
|
||||||
let binpath = match self.path().unwrap() {
|
let binpath = match self.path().unwrap() {
|
||||||
crate::Path::Bin => "shitbox",
|
shitbox::Path::Bin => "shitbox",
|
||||||
crate::Path::Sbin => "../bin/shitbox",
|
shitbox::Path::Sbin => "../bin/shitbox",
|
||||||
crate::Path::UsrBin => {
|
shitbox::Path::UsrBin => {
|
||||||
if usr {
|
if usr {
|
||||||
"../../bin/shitbox"
|
"../../bin/shitbox"
|
||||||
} else {
|
} else {
|
||||||
"shitbox"
|
"shitbox"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
crate::Path::UsrSbin => {
|
shitbox::Path::UsrSbin => {
|
||||||
if usr {
|
if usr {
|
||||||
"../../bin/shitbox"
|
"../../bin/shitbox"
|
||||||
} else {
|
} else {
|
||||||
@ -294,7 +294,7 @@ fn manpages(prefix: &str) -> Result<(), io::Error> {
|
|||||||
println!("Generating Unix man pages:");
|
println!("Generating Unix man pages:");
|
||||||
COMMANDS
|
COMMANDS
|
||||||
.iter()
|
.iter()
|
||||||
.try_for_each(|cmd| crate::cmd::get(cmd).unwrap().manpage(prefix))?;
|
.try_for_each(|cmd| super::get(cmd).unwrap().manpage(prefix))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,35 +305,35 @@ fn completions(prefix: &str, matches: &ArgMatches) -> Result<(), io::Error> {
|
|||||||
.iter()
|
.iter()
|
||||||
.collect();
|
.collect();
|
||||||
COMMANDS.iter().try_for_each(|cmd| {
|
COMMANDS.iter().try_for_each(|cmd| {
|
||||||
let cmd = crate::cmd::get(cmd).unwrap();
|
let cmd = super::get(cmd).unwrap();
|
||||||
cmd.completion(&outdir, "bash")
|
cmd.completion(&outdir, "bash")
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
if matches.get_flag("fish") || matches.get_flag("all") {
|
if matches.get_flag("fish") || matches.get_flag("all") {
|
||||||
let outdir: PathBuf = [prefix, "share", "fish", "completions"].iter().collect();
|
let outdir: PathBuf = [prefix, "share", "fish", "completions"].iter().collect();
|
||||||
COMMANDS.iter().try_for_each(|cmd| {
|
COMMANDS.iter().try_for_each(|cmd| {
|
||||||
let cmd = crate::cmd::get(cmd).unwrap();
|
let cmd = super::get(cmd).unwrap();
|
||||||
cmd.completion(&outdir, "fish")
|
cmd.completion(&outdir, "fish")
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
if matches.get_flag("nu") || matches.get_flag("all") {
|
if matches.get_flag("nu") || matches.get_flag("all") {
|
||||||
let outdir: PathBuf = [prefix, "share", "nu", "completions"].iter().collect();
|
let outdir: PathBuf = [prefix, "share", "nu", "completions"].iter().collect();
|
||||||
COMMANDS.iter().try_for_each(|cmd| {
|
COMMANDS.iter().try_for_each(|cmd| {
|
||||||
let cmd = crate::cmd::get(cmd).unwrap();
|
let cmd = super::get(cmd).unwrap();
|
||||||
cmd.completion(&outdir, "nu")
|
cmd.completion(&outdir, "nu")
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
if matches.get_flag("pwsh") || matches.get_flag("all") {
|
if matches.get_flag("pwsh") || matches.get_flag("all") {
|
||||||
let outdir: PathBuf = [prefix, "share", "pwsh", "completions"].iter().collect();
|
let outdir: PathBuf = [prefix, "share", "pwsh", "completions"].iter().collect();
|
||||||
COMMANDS.iter().try_for_each(|cmd| {
|
COMMANDS.iter().try_for_each(|cmd| {
|
||||||
let cmd = crate::cmd::get(cmd).unwrap();
|
let cmd = super::get(cmd).unwrap();
|
||||||
cmd.completion(&outdir, "pwsh")
|
cmd.completion(&outdir, "pwsh")
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
if matches.get_flag("zsh") || matches.get_flag("all") {
|
if matches.get_flag("zsh") || matches.get_flag("all") {
|
||||||
let outdir: PathBuf = [prefix, "share", "zsh", "site-functions"].iter().collect();
|
let outdir: PathBuf = [prefix, "share", "zsh", "site-functions"].iter().collect();
|
||||||
COMMANDS.iter().try_for_each(|cmd| {
|
COMMANDS.iter().try_for_each(|cmd| {
|
||||||
let cmd = crate::cmd::get(cmd).unwrap();
|
let cmd = super::get(cmd).unwrap();
|
||||||
cmd.completion(&outdir, "zsh")
|
cmd.completion(&outdir, "zsh")
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@ -371,7 +371,7 @@ fn links(prefix: &str, usr: bool, cmd: &ArgMatches) -> Result<(), Box<dyn Error>
|
|||||||
}
|
}
|
||||||
let soft = cmd.get_flag("soft");
|
let soft = cmd.get_flag("soft");
|
||||||
COMMANDS.iter().try_for_each(|c| {
|
COMMANDS.iter().try_for_each(|c| {
|
||||||
let cmd = crate::cmd::get(c).unwrap();
|
let cmd = super::get(c).unwrap();
|
||||||
cmd.link(prefix, usr, soft)
|
cmd.link(prefix, usr, soft)
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
@ -1,9 +1,7 @@
|
|||||||
use super::{Cmd, Feedback};
|
use super::{Cmd, Feedback};
|
||||||
use crate::{
|
use shitbox::args;
|
||||||
args,
|
|
||||||
mode::{Mode, Parser},
|
|
||||||
};
|
|
||||||
use clap::{Arg, ArgAction, Command};
|
use clap::{Arg, ArgAction, Command};
|
||||||
|
use mode::{Mode, Parser};
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
fs::{self, File, Permissions},
|
fs::{self, File, Permissions},
|
||||||
@ -78,8 +76,8 @@ impl Cmd for Chmod {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
|||||||
use super::{Group, Recurse, Traversal};
|
use super::{Feedback, Group, Recurse, Traversal};
|
||||||
use crate::cmd::{Cmd, Feedback};
|
use shitbox::Cmd;
|
||||||
use crate::pw;
|
|
||||||
use clap::{Arg, ArgGroup, Command, ValueHint};
|
use clap::{Arg, ArgGroup, Command, ValueHint};
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
@ -71,8 +70,8 @@ impl Cmd for Chgrp {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
use super::{Cmd, Feedback};
|
use super::{Cmd, Feedback};
|
||||||
use crate::{args, pw};
|
use shitbox::args;
|
||||||
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint};
|
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint};
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
@ -82,8 +82,8 @@ impl Cmd for Chown {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ impl Cmd for Chroot {
|
|||||||
return Err(command.exec().into());
|
return Err(command.exec().into());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrSbin)
|
Some(shitbox::Path::UsrSbin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,7 +18,7 @@ impl Cmd for Clear {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,25 +1,26 @@
|
|||||||
use super::{Cmd, COMMANDS};
|
use super::COMMANDS;
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
|
use shitbox::Cmd;
|
||||||
use std::{error::Error, process};
|
use std::{error::Error, process};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Shitbox;
|
pub struct Corebox;
|
||||||
|
|
||||||
impl Cmd for Shitbox {
|
impl Cmd for Corebox {
|
||||||
fn cli(&self) -> clap::Command {
|
fn cli(&self) -> clap::Command {
|
||||||
let subcommands: Vec<Command> = {
|
let subcommands: Vec<Command> = {
|
||||||
let mut s = vec![];
|
let mut s = vec![];
|
||||||
for c in COMMANDS {
|
for c in COMMANDS {
|
||||||
if c == "shitbox" {
|
if c == "corebox" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(cmd) = crate::cmd::get(c) {
|
if let Some(cmd) = crate::commands::get(c) {
|
||||||
s.push(cmd.cli());
|
s.push(cmd.cli());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s
|
s
|
||||||
};
|
};
|
||||||
Command::new("shitbox")
|
Command::new("corebox")
|
||||||
.about("The box store multitool of embedded Linux")
|
.about("The box store multitool of embedded Linux")
|
||||||
.version(env!("CARGO_PKG_VERSION"))
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
.propagate_version(true)
|
.propagate_version(true)
|
||||||
@ -31,7 +32,7 @@ impl Cmd for Shitbox {
|
|||||||
|
|
||||||
fn run(&self, matches: &clap::ArgMatches) -> Result<(), Box<dyn Error>> {
|
fn run(&self, matches: &clap::ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||||
if let Some((name, matches)) = matches.subcommand() {
|
if let Some((name, matches)) = matches.subcommand() {
|
||||||
if let Some(command) = crate::cmd::get(name) {
|
if let Some(command) = crate::commands::get(name) {
|
||||||
if let Err(e) = command.run(matches) {
|
if let Err(e) = command.run(matches) {
|
||||||
eprintln!("Error: {name}: {e}");
|
eprintln!("Error: {name}: {e}");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
@ -41,7 +42,7 @@ impl Cmd for Shitbox {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -100,8 +100,8 @@ impl Cmd for Cut {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ impl Cmd for Dirname {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ impl Cmd for Echo {
|
|||||||
|
|
||||||
fn run(&self, _matches: &clap::ArgMatches) -> Result<(), Box<dyn Error>> {
|
fn run(&self, _matches: &clap::ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
let idx = match crate::progname() {
|
let idx = match shitbox::progname() {
|
||||||
Some(s) if s.as_str() == "echo" => 1,
|
Some(s) if s.as_str() == "echo" => 1,
|
||||||
Some(_) => 2,
|
Some(_) => 2,
|
||||||
None => unreachable!(),
|
None => unreachable!(),
|
||||||
@ -42,7 +42,7 @@ impl Cmd for Echo {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,7 +42,7 @@ impl Cmd for Expand {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,8 +40,8 @@ impl Cmd for Factor {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -17,7 +17,7 @@ impl Cmd for False {
|
|||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -64,8 +64,8 @@ impl Cmd for Fold {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,4 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::pw;
|
|
||||||
use clap::{Arg, Command};
|
use clap::{Arg, Command};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -37,7 +36,7 @@ impl Cmd for Groups {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{args, Path};
|
use shitbox::{args, Path};
|
||||||
use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
|
use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
@ -59,7 +59,7 @@ impl Cmd for Head {
|
|||||||
|
|
||||||
fn run(&self, matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
|
fn run(&self, matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||||
let args: Vec<_> = env::args().collect();
|
let args: Vec<_> = env::args().collect();
|
||||||
let idx = match crate::progname() {
|
let idx = match shitbox::progname() {
|
||||||
Some(s) if s.as_str() == "head" => 1,
|
Some(s) if s.as_str() == "head" => 1,
|
||||||
_ => 2,
|
_ => 2,
|
||||||
};
|
};
|
||||||
@ -109,7 +109,7 @@ impl Cmd for Head {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<Path> {
|
fn path(&self) -> Option<Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +19,7 @@ impl Cmd for Hostid {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::unistd;
|
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||||
use std::{error::Error, io};
|
use std::{error::Error, io};
|
||||||
|
|
||||||
@ -48,7 +47,7 @@ impl Cmd for Hostname {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::args;
|
use shitbox::args;
|
||||||
use clap::{Arg, Command};
|
use clap::{Arg, Command};
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ impl Cmd for Link {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::unistd;
|
|
||||||
use clap::{Arg, ArgAction, Command};
|
use clap::{Arg, ArgAction, Command};
|
||||||
use std::{error::Error, fs, io, os, path::PathBuf};
|
use std::{error::Error, fs, io, os, path::PathBuf};
|
||||||
|
|
||||||
@ -88,8 +87,8 @@ impl Cmd for Ln {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ impl Cmd for Logname {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{args, mode::Parser, stat};
|
use shitbox::{args, stat};
|
||||||
use clap::{Arg, ArgMatches, Command};
|
use clap::{Arg, ArgMatches, Command};
|
||||||
|
use mode::Parser;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -55,7 +56,7 @@ impl Cmd for MkFifo {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,7 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{
|
use shitbox::{args, stat};
|
||||||
args,
|
|
||||||
mode::{get_umask, Parser},
|
|
||||||
stat,
|
|
||||||
};
|
|
||||||
use clap::{value_parser, Arg, ArgMatches, Command};
|
use clap::{value_parser, Arg, ArgMatches, Command};
|
||||||
|
use mode::{get_umask, Parser};
|
||||||
use std::{convert::Infallible, error::Error, io, str::FromStr};
|
use std::{convert::Infallible, error::Error, io, str::FromStr};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -92,8 +89,8 @@ impl Cmd for MkNod {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Sbin)
|
Some(shitbox::Path::Sbin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +79,7 @@ impl Cmd for MkTemp {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
172
corebox/commands/mod.rs
Normal file
172
corebox/commands/mod.rs
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
use clap::ArgMatches;
|
||||||
|
use shitbox::Cmd;
|
||||||
|
|
||||||
|
mod corebox;
|
||||||
|
mod base32;
|
||||||
|
mod base64;
|
||||||
|
mod basename;
|
||||||
|
mod bootstrap;
|
||||||
|
mod cat;
|
||||||
|
mod chmod;
|
||||||
|
mod chown;
|
||||||
|
mod chroot;
|
||||||
|
mod clear;
|
||||||
|
mod cp;
|
||||||
|
mod cut;
|
||||||
|
mod date;
|
||||||
|
mod dd;
|
||||||
|
mod dirname;
|
||||||
|
mod echo;
|
||||||
|
mod expand;
|
||||||
|
mod factor;
|
||||||
|
mod r#false;
|
||||||
|
mod fold;
|
||||||
|
mod getty;
|
||||||
|
mod groups;
|
||||||
|
mod head;
|
||||||
|
mod hostid;
|
||||||
|
mod hostname;
|
||||||
|
mod link;
|
||||||
|
mod ln;
|
||||||
|
mod logname;
|
||||||
|
mod ls;
|
||||||
|
mod mkfifo;
|
||||||
|
mod mknod;
|
||||||
|
mod mktemp;
|
||||||
|
mod mountpoint;
|
||||||
|
mod mv;
|
||||||
|
mod nologin;
|
||||||
|
mod nproc;
|
||||||
|
mod printenv;
|
||||||
|
mod pwd;
|
||||||
|
mod readlink;
|
||||||
|
mod realpath;
|
||||||
|
mod rev;
|
||||||
|
mod rm;
|
||||||
|
mod rmdir;
|
||||||
|
mod sleep;
|
||||||
|
mod sync;
|
||||||
|
mod r#true;
|
||||||
|
mod unlink;
|
||||||
|
mod wc;
|
||||||
|
mod which;
|
||||||
|
mod whoami;
|
||||||
|
mod yes;
|
||||||
|
|
||||||
|
/// Parses a string into a command to run
|
||||||
|
#[must_use]
|
||||||
|
#[allow(clippy::box_default)]
|
||||||
|
pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
||||||
|
match name {
|
||||||
|
"base64" => Some(Box::new(base64::Base64::default())),
|
||||||
|
"base32" => Some(Box::new(base32::Base32::default())),
|
||||||
|
"basename" => Some(Box::new(basename::Basename::default())),
|
||||||
|
"bootstrap" => Some(Box::new(bootstrap::Bootstrap::default())),
|
||||||
|
"chmod" => Some(Box::new(chmod::Chmod::default())),
|
||||||
|
"chgrp" => Some(Box::new(chown::Chgrp::default())),
|
||||||
|
"chown" => Some(Box::new(chown::Chown::default())),
|
||||||
|
"chroot" => Some(Box::new(chroot::Chroot::default())),
|
||||||
|
"clear" => Some(Box::new(clear::Clear::default())),
|
||||||
|
"corebox" => Some(Box::new(corebox::Corebox::default())),
|
||||||
|
"cut" => Some(Box::new(cut::Cut::default())),
|
||||||
|
"dirname" => Some(Box::new(dirname::Dirname::default())),
|
||||||
|
"echo" => Some(Box::new(echo::Echo::default())),
|
||||||
|
"factor" => Some(Box::new(factor::Factor::default())),
|
||||||
|
"false" => Some(Box::new(r#false::False::default())),
|
||||||
|
"fold" => Some(Box::new(fold::Fold::default())),
|
||||||
|
"groups" => Some(Box::new(groups::Groups::default())),
|
||||||
|
"head" => Some(Box::new(head::Head::default())),
|
||||||
|
"hostid" => Some(Box::new(hostid::Hostid::default())),
|
||||||
|
"hostname" => Some(Box::new(hostname::Hostname::default())),
|
||||||
|
"link" => Some(Box::new(link::Link::default())),
|
||||||
|
"ln" => Some(Box::new(ln::Ln::default())),
|
||||||
|
"logname" => Some(Box::new(logname::Logname::default())),
|
||||||
|
"mkfifo" => Some(Box::new(mkfifo::MkFifo::default())),
|
||||||
|
"mknod" => Some(Box::new(mknod::MkNod::default())),
|
||||||
|
"mktemp" => Some(Box::new(mktemp::MkTemp::default())),
|
||||||
|
"mountpoint" => Some(Box::new(mountpoint::Mountpoint::default())),
|
||||||
|
"nologin" => Some(Box::new(nologin::Nologin::default())),
|
||||||
|
"nproc" => Some(Box::new(nproc::Nproc::default())),
|
||||||
|
"printenv" => Some(Box::new(printenv::Printenv::default())),
|
||||||
|
"pwd" => Some(Box::new(pwd::Pwd::default())),
|
||||||
|
"readlink" => Some(Box::new(readlink::Readlink::default())),
|
||||||
|
"realpath" => Some(Box::new(realpath::Realpath::default())),
|
||||||
|
"rev" => Some(Box::new(rev::Rev::default())),
|
||||||
|
"rm" => Some(Box::new(rm::Rm::default())),
|
||||||
|
"rmdir" => Some(Box::new(rmdir::Rmdir::default())),
|
||||||
|
"sleep" => Some(Box::new(sleep::Sleep::default())),
|
||||||
|
"sync" => Some(Box::new(sync::Sync::default())),
|
||||||
|
"true" => Some(Box::new(r#true::True::default())),
|
||||||
|
"unlink" => Some(Box::new(unlink::Unlink::default())),
|
||||||
|
"wc" => Some(Box::new(wc::Wc::default())),
|
||||||
|
"which" => Some(Box::new(which::Which::default())),
|
||||||
|
"whoami" => Some(Box::new(whoami::Whoami::default())),
|
||||||
|
"yes" => Some(Box::new(yes::Yes::default())),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static COMMANDS: [&str; 44] = [
|
||||||
|
"base32",
|
||||||
|
"base64",
|
||||||
|
"basename",
|
||||||
|
"bootstrap",
|
||||||
|
"chgrp",
|
||||||
|
"chmod",
|
||||||
|
"chown",
|
||||||
|
"chroot",
|
||||||
|
"clear",
|
||||||
|
"corebox",
|
||||||
|
"cut",
|
||||||
|
"dirname",
|
||||||
|
"echo",
|
||||||
|
"false",
|
||||||
|
"factor",
|
||||||
|
"fold",
|
||||||
|
"groups",
|
||||||
|
"head",
|
||||||
|
"hostid",
|
||||||
|
"hostname",
|
||||||
|
"link",
|
||||||
|
"ln",
|
||||||
|
"logname",
|
||||||
|
"mkfifo",
|
||||||
|
"mknod",
|
||||||
|
"mktemp",
|
||||||
|
"mountpoint",
|
||||||
|
"nologin",
|
||||||
|
"nproc",
|
||||||
|
"printenv",
|
||||||
|
"pwd",
|
||||||
|
"readlink",
|
||||||
|
"realpath",
|
||||||
|
"rev",
|
||||||
|
"rm",
|
||||||
|
"rmdir",
|
||||||
|
"sleep",
|
||||||
|
"sync",
|
||||||
|
"true",
|
||||||
|
"unlink",
|
||||||
|
"wc",
|
||||||
|
"which",
|
||||||
|
"whoami",
|
||||||
|
"yes",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
enum Feedback {
|
||||||
|
Full,
|
||||||
|
Changes,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Feedback {
|
||||||
|
fn from_matches(matches: &ArgMatches) -> Option<Self> {
|
||||||
|
if matches.get_flag("verbose") {
|
||||||
|
Some(Feedback::Full)
|
||||||
|
} else if matches.get_flag("changes") {
|
||||||
|
Some(Feedback::Changes)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -82,8 +82,8 @@ impl Cmd for Mountpoint {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -17,7 +17,7 @@ impl Cmd for Nologin {
|
|||||||
process::exit(42);
|
process::exit(42);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Sbin)
|
Some(shitbox::Path::Sbin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,8 +27,8 @@ impl Cmd for Nproc {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ impl Cmd for Printenv {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -38,7 +38,7 @@ impl Cmd for Pwd {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use crate::Cmd;
|
use shitbox::Cmd;
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command, ValueHint};
|
use clap::{Arg, ArgAction, ArgMatches, Command, ValueHint};
|
||||||
use std::{fs, path::PathBuf};
|
use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ impl Cmd for Readlink {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -57,7 +57,7 @@ impl Cmd for Realpath {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::args;
|
use shitbox::args;
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
@ -48,8 +48,8 @@ impl Cmd for Rev {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{args, fs::FileType};
|
use shitbox::{args, fs::FileType};
|
||||||
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint};
|
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint};
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
@ -91,8 +91,8 @@ impl Cmd for Rm {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::args;
|
use shitbox::args;
|
||||||
use clap::{Arg, ArgAction, Command, ValueHint};
|
use clap::{Arg, ArgAction, Command, ValueHint};
|
||||||
use std::{error::Error, fs, path::Path};
|
use std::{error::Error, fs, path::Path};
|
||||||
|
|
||||||
@ -44,8 +44,8 @@ impl Cmd for Rmdir {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ impl Cmd for Sleep {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::unistd;
|
|
||||||
use clap::{Arg, ArgAction, Command};
|
use clap::{Arg, ArgAction, Command};
|
||||||
use std::{error::Error, fs::OpenOptions};
|
use std::{error::Error, fs::OpenOptions};
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ impl Cmd for Sync {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ impl Cmd for True {
|
|||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::Bin)
|
Some(shitbox::Path::Bin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{args, unistd};
|
use shitbox::args;
|
||||||
use clap::{Arg, Command};
|
use clap::{Arg, Command};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -32,7 +32,7 @@ impl Cmd for Unlink {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::bitflags::BitFlags;
|
use bitflags::BitFlags;
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||||
use std::{
|
use std::{
|
||||||
cmp,
|
cmp,
|
||||||
@ -79,8 +79,8 @@ impl Cmd for Wc {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{bitflags::BitFlags, mode::Bit};
|
use bitflags::BitFlags;
|
||||||
use clap::{Arg, Command};
|
use clap::{Arg, Command};
|
||||||
|
use mode::Bit;
|
||||||
use std::{env, fs::File, os::unix::prelude::MetadataExt, path::PathBuf, process};
|
use std::{env, fs::File, os::unix::prelude::MetadataExt, path::PathBuf, process};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -43,8 +44,8 @@ impl Cmd for Which {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ fn which(command: &str, path: &[&str]) -> Option<String> {
|
|||||||
if let Ok(meta) = exe.metadata() {
|
if let Ok(meta) = exe.metadata() {
|
||||||
let mode = meta.mode();
|
let mode = meta.mode();
|
||||||
let myuid = unsafe { libc::geteuid() };
|
let myuid = unsafe { libc::geteuid() };
|
||||||
let mygroups = crate::pw::get_gids();
|
let mygroups = pw::get_gids();
|
||||||
// we own the file and it has u+x
|
// we own the file and it has u+x
|
||||||
if myuid == meta.uid() && mode.contains(Bit::UExec) {
|
if myuid == meta.uid() && mode.contains(Bit::UExec) {
|
||||||
return Some(format!("{}", file.display()));
|
return Some(format!("{}", file.display()));
|
@ -25,7 +25,7 @@ impl Cmd for Whoami {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,7 +19,7 @@ impl Cmd for Yes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
18
corebox/main.rs
Normal file
18
corebox/main.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use std::process;
|
||||||
|
|
||||||
|
mod commands;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
if let Some(progname) = shitbox::progname() {
|
||||||
|
if let Some(command) = commands::get(&progname) {
|
||||||
|
let cli = command.cli();
|
||||||
|
if let Err(e) = command.run(&cli.get_matches()) {
|
||||||
|
eprintln!("{progname}: Error: {e}");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("shitbox: Error: unknown command {progname}");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::args;
|
|
||||||
use blake2b_simd::Params;
|
use blake2b_simd::Params;
|
||||||
use clap::{value_parser, Arg, Command};
|
use clap::{value_parser, Arg, Command};
|
||||||
|
use shitbox::args;
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, BufRead, BufReader, Read},
|
io::{self, BufRead, BufReader, Read},
|
||||||
@ -98,7 +98,7 @@ impl Cmd for B2sum {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
48
hashbox/commands/hashbox/mod.rs
Normal file
48
hashbox/commands/hashbox/mod.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use super::COMMANDS;
|
||||||
|
use clap::Command;
|
||||||
|
use shitbox::Cmd;
|
||||||
|
use std::{error::Error, process};
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Hashbox;
|
||||||
|
|
||||||
|
impl Cmd for Hashbox {
|
||||||
|
fn cli(&self) -> clap::Command {
|
||||||
|
let subcommands: Vec<Command> = {
|
||||||
|
let mut s = vec![];
|
||||||
|
for c in COMMANDS {
|
||||||
|
if c == "hashbox" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(cmd) = crate::commands::get(c) {
|
||||||
|
s.push(cmd.cli());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s
|
||||||
|
};
|
||||||
|
Command::new("hashbox")
|
||||||
|
.about("The box store multitool of embedded Linux")
|
||||||
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
|
.propagate_version(true)
|
||||||
|
.arg_required_else_help(true)
|
||||||
|
.subcommand_value_name("APPLET")
|
||||||
|
.subcommand_help_heading("APPLETS")
|
||||||
|
.subcommands(&subcommands)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, matches: &clap::ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||||
|
if let Some((name, matches)) = matches.subcommand() {
|
||||||
|
if let Some(command) = crate::commands::get(name) {
|
||||||
|
if let Err(e) = command.run(matches) {
|
||||||
|
eprintln!("Error: {name}: {e}");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,8 @@
|
|||||||
use super::Cmd;
|
use crate::hash::{self, HashType};
|
||||||
use crate::{
|
|
||||||
args,
|
|
||||||
hash::{self, HashType},
|
|
||||||
};
|
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use md5::{Digest, Md5};
|
use md5::{Digest, Md5};
|
||||||
|
use shitbox::args;
|
||||||
|
use shitbox::Cmd;
|
||||||
use std::{io, process};
|
use std::{io, process};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -44,7 +42,7 @@ impl Cmd for Md5sum {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
37
hashbox/commands/mod.rs
Normal file
37
hashbox/commands/mod.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use shitbox::Cmd;
|
||||||
|
|
||||||
|
mod b2sum;
|
||||||
|
mod hashbox;
|
||||||
|
mod md5sum;
|
||||||
|
mod sha1sum;
|
||||||
|
mod sha224sum;
|
||||||
|
mod sha256sum;
|
||||||
|
mod sha384sum;
|
||||||
|
mod sha512sum;
|
||||||
|
|
||||||
|
/// Parses a string into a command to run
|
||||||
|
#[must_use]
|
||||||
|
#[allow(clippy::box_default)]
|
||||||
|
pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
||||||
|
match name {
|
||||||
|
"b2sum" => Some(Box::new(b2sum::B2sum::default())),
|
||||||
|
"hashbox" => Some(Box::new(hashbox::Hashbox::default())),
|
||||||
|
"md5sum" => Some(Box::new(md5sum::Md5sum::default())),
|
||||||
|
"sha1sum" => Some(Box::new(sha1sum::Sha1sum::default())),
|
||||||
|
"sha224sum" => Some(Box::new(sha224sum::Sha224sum::default())),
|
||||||
|
"sha256sum" => Some(Box::new(sha256sum::Sha256sum::default())),
|
||||||
|
"sha384sum" => Some(Box::new(sha384sum::Sha384sum::default())),
|
||||||
|
"sha512sum" => Some(Box::new(sha512sum::Sha512sum::default())),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static COMMANDS: [&str; 7] = [
|
||||||
|
"b2sum",
|
||||||
|
"md5sum",
|
||||||
|
"sha1sum",
|
||||||
|
"sha224sum",
|
||||||
|
"sha256sum",
|
||||||
|
"sha384sum",
|
||||||
|
"sha512sum",
|
||||||
|
];
|
@ -1,10 +1,7 @@
|
|||||||
use super::Cmd;
|
use crate::hash::{self, HashType};
|
||||||
use crate::{
|
|
||||||
args,
|
|
||||||
hash::{self, HashType},
|
|
||||||
};
|
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use sha1::{Digest, Sha1};
|
use sha1::{Digest, Sha1};
|
||||||
|
use shitbox::{args, Cmd};
|
||||||
use std::{io, process};
|
use std::{io, process};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -44,7 +41,7 @@ impl Cmd for Sha1sum {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,8 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{
|
use crate::hash::{self, HashType};
|
||||||
args,
|
|
||||||
hash::{self, HashType},
|
|
||||||
};
|
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use sha2::{Digest, Sha224};
|
use sha2::{Digest, Sha224};
|
||||||
|
use shitbox::args;
|
||||||
use std::{io, process};
|
use std::{io, process};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -44,7 +42,7 @@ impl Cmd for Sha224sum {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,8 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{
|
use crate::hash::{self, HashType};
|
||||||
args,
|
|
||||||
hash::{self, HashType},
|
|
||||||
};
|
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
use shitbox::args;
|
||||||
use std::{io, process};
|
use std::{io, process};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -44,7 +42,7 @@ impl Cmd for Sha256sum {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,8 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{
|
use crate::hash::{self, HashType};
|
||||||
args,
|
|
||||||
hash::{self, HashType},
|
|
||||||
};
|
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use sha2::{Digest, Sha384};
|
use sha2::{Digest, Sha384};
|
||||||
|
use shitbox::args;
|
||||||
use std::{io, process};
|
use std::{io, process};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -44,7 +42,7 @@ impl Cmd for Sha384sum {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,8 @@
|
|||||||
use super::Cmd;
|
use super::Cmd;
|
||||||
use crate::{
|
use crate::hash::{self, HashType};
|
||||||
args,
|
|
||||||
hash::{self, HashType},
|
|
||||||
};
|
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use sha2::{Digest, Sha512};
|
use sha2::{Digest, Sha512};
|
||||||
|
use shitbox::args;
|
||||||
use std::{io, process};
|
use std::{io, process};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
@ -44,7 +42,7 @@ impl Cmd for Sha512sum {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(&self) -> Option<crate::Path> {
|
fn path(&self) -> Option<shitbox::Path> {
|
||||||
Some(crate::Path::UsrBin)
|
Some(shitbox::Path::UsrBin)
|
||||||
}
|
}
|
||||||
}
|
}
|
19
hashbox/main.rs
Normal file
19
hashbox/main.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use std::process;
|
||||||
|
|
||||||
|
pub mod commands;
|
||||||
|
pub mod hash;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
if let Some(progname) = shitbox::progname() {
|
||||||
|
if let Some(command) = commands::get(&progname) {
|
||||||
|
let cli = command.cli();
|
||||||
|
if let Err(e) = command.run(&cli.get_matches()) {
|
||||||
|
eprintln!("{progname}: Error: {e}");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("shitbox: Error: unknown command {progname}");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
mount/Cargo.toml
Normal file
10
mount/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "mount"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
blkid = "1.0"
|
||||||
|
sc = { workspace = true }
|
56
mount/src/lib.rs
Normal file
56
mount/src/lib.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use sc::*;
|
||||||
|
use std::{io, ffi::CString};
|
||||||
|
|
||||||
|
mod mntent;
|
||||||
|
mod mntentries;
|
||||||
|
mod mntflags;
|
||||||
|
|
||||||
|
pub use self::{
|
||||||
|
mntent::MntEntry,
|
||||||
|
mntentries::MntEntries,
|
||||||
|
mntflags::{Flags as MntFlags, ParseFlagsError},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Wraps the Linux SYS_mount syscall in a nicer interface
|
||||||
|
pub fn mount(
|
||||||
|
dev: &str,
|
||||||
|
mountpoint: &str,
|
||||||
|
fstype: &str,
|
||||||
|
flags: u32,
|
||||||
|
opts: Option<&str>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let ret = unsafe {
|
||||||
|
if let Some(opts) = opts {
|
||||||
|
syscall!(
|
||||||
|
MOUNT,
|
||||||
|
CString::new(dev)?.as_ptr(),
|
||||||
|
CString::new(mountpoint)?.as_ptr(),
|
||||||
|
CString::new(fstype)?.as_ptr(),
|
||||||
|
flags as usize,
|
||||||
|
CString::new(opts)?.as_ptr()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
syscall!(
|
||||||
|
MOUNT,
|
||||||
|
CString::new(dev)?.as_ptr(),
|
||||||
|
CString::new(mountpoint)?.as_ptr(),
|
||||||
|
CString::new(fstype)?.as_ptr(),
|
||||||
|
flags as usize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ret == 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn swapon(dev: &str, flags: usize) -> io::Result<()> {
|
||||||
|
let ret = unsafe { syscall!(SWAPON, CString::new(dev)?.as_ptr(), flags) };
|
||||||
|
if ret == 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
|
}
|
||||||
|
}
|
279
mount/src/mntent.rs
Normal file
279
mount/src/mntent.rs
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
//! A Rust reimplementation of libc's mntent, for parsing /etc/fstab or
|
||||||
|
//! /proc/mounts
|
||||||
|
use super::{MntEntries, MntFlags};
|
||||||
|
use blkid::{
|
||||||
|
cache::Cache,
|
||||||
|
tag::{PartitionTag, SuperblockTag, TagType},
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
fmt::{self, Write},
|
||||||
|
fs::File,
|
||||||
|
io,
|
||||||
|
os::unix::fs::MetadataExt,
|
||||||
|
path::PathBuf,
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The information for a mount broken out into a struct
|
||||||
|
pub struct MntEntry {
|
||||||
|
pub fsname: String,
|
||||||
|
pub dir: String,
|
||||||
|
pub fstype: String,
|
||||||
|
pub opts: String,
|
||||||
|
pub freq: i32,
|
||||||
|
pub passno: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MntEntry {
|
||||||
|
/// Mount the mount specified by this entry
|
||||||
|
pub fn mount(&self) -> io::Result<()> {
|
||||||
|
let dev = self.device()?;
|
||||||
|
let dev = dev.to_string_lossy();
|
||||||
|
let (flags, opts) = self.parse_opts()
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
|
super::mount(&dev, &self.dir, &self.fstype, flags, Some(&opts))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_mounted(&self) -> bool {
|
||||||
|
if let Ok(entries) = MntEntries::new("/proc/mounts") {
|
||||||
|
for e in entries {
|
||||||
|
if self.dir == e.dir && self.fstype == e.fstype {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_opts(&self) -> Result<(u32, String), fmt::Error> {
|
||||||
|
let mut res = (0, String::new());
|
||||||
|
let splitopts = self.opts.split(',');
|
||||||
|
for opt in splitopts {
|
||||||
|
match opt.parse::<MntFlags>() {
|
||||||
|
Ok(f) => res.0 |= f,
|
||||||
|
Err(_) => match opt {
|
||||||
|
"async" => res.0 &= !MntFlags::Synchronous,
|
||||||
|
"atime" => res.0 &= !MntFlags::NoAtime,
|
||||||
|
"dev" => res.0 &= !MntFlags::NoDev,
|
||||||
|
"diratime" => res.0 &= !MntFlags::NoDirAtime,
|
||||||
|
"exec" => res.0 &= !MntFlags::NoExec,
|
||||||
|
"group" => res.0 &= MntFlags::NoSuid | MntFlags::NoDev,
|
||||||
|
"noiversion" => res.0 &= !MntFlags::IVersion,
|
||||||
|
"mand" => res.0 &= !MntFlags::NoRemoteLock,
|
||||||
|
"norelatime" => res.0 &= !MntFlags::RelAtime,
|
||||||
|
"nostrictatime" => res.0 &= !MntFlags::StrictAtime,
|
||||||
|
"nolazytime" => res.0 &= !MntFlags::LazyTime,
|
||||||
|
"loud" => res.0 &= !MntFlags::Silent,
|
||||||
|
"owner" => res.0 |= MntFlags::NoSuid | MntFlags::NoDev,
|
||||||
|
"rw" => res.0 &= !MntFlags::ReadOnly,
|
||||||
|
"user" => {
|
||||||
|
res.0 &= !MntFlags::NoUser;
|
||||||
|
res.0 |= MntFlags::NoExec | MntFlags::NoSuid | MntFlags::NoDev;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if res.1.is_empty() {
|
||||||
|
write!(res.1, "{opt}")?;
|
||||||
|
} else {
|
||||||
|
write!(res.1, ",{opt}")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the canonical path to the device pointed to by this entry
|
||||||
|
pub fn device(&self) -> io::Result<PathBuf> {
|
||||||
|
match self.fsname.as_str() {
|
||||||
|
s if s.starts_with("UUID=") => dev_from_uuid(s),
|
||||||
|
s if s.starts_with("LABEL=") => dev_from_label(s),
|
||||||
|
s if s.starts_with("PARTUUID=") => dev_from_partuuid(s),
|
||||||
|
s if s.starts_with("PARTLABEL=") => dev_from_partlabel(s),
|
||||||
|
s => {
|
||||||
|
let mut p = PathBuf::from(s);
|
||||||
|
if p.exists() {
|
||||||
|
p = p.canonicalize()?;
|
||||||
|
let fd = File::open(&p)?;
|
||||||
|
let meta = fd.metadata()?;
|
||||||
|
if meta.rdev() != 0 {
|
||||||
|
Ok(p)
|
||||||
|
} else {
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "not a block device"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(io::Error::new(io::ErrorKind::NotFound, "no such file"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for MntEntry {
|
||||||
|
type Err = io::Error;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let s = match s.split_once('#') {
|
||||||
|
Some((lhs, _)) => lhs,
|
||||||
|
None => s,
|
||||||
|
};
|
||||||
|
let mut split = s.split_whitespace();
|
||||||
|
let Some(fsname) = split.next() else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "missing field"));
|
||||||
|
};
|
||||||
|
let Some(dir) = split.next() else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "missing field"));
|
||||||
|
};
|
||||||
|
let Some(fstype) = split.next() else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "missing field"));
|
||||||
|
};
|
||||||
|
let Some(opts) = split.next() else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "missing field"));
|
||||||
|
};
|
||||||
|
let Some(freq) = split.next() else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "missing field"));
|
||||||
|
};
|
||||||
|
let Some(passno) = split.next() else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "missing field"));
|
||||||
|
};
|
||||||
|
if split.next().is_some() {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "extra field"));
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
fsname: fsname.to_string(),
|
||||||
|
dir: dir.to_string(),
|
||||||
|
fstype: fstype.to_string(),
|
||||||
|
opts: opts.to_string(),
|
||||||
|
freq: freq
|
||||||
|
.parse()
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
|
||||||
|
passno: passno
|
||||||
|
.parse()
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dev_from_uuid(s: &str) -> io::Result<PathBuf> {
|
||||||
|
let uuid = s.strip_prefix("UUID=").ok_or(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"this should never happen",
|
||||||
|
))?;
|
||||||
|
let cache = Cache::new().map_err(|x| io::Error::new(io::ErrorKind::Other, x))?;
|
||||||
|
let devs = cache.devs();
|
||||||
|
for dev in devs {
|
||||||
|
let tags = dev.tags();
|
||||||
|
for tag in tags {
|
||||||
|
match tag.typ() {
|
||||||
|
TagType::Superblock(SuperblockTag::Uuid) => {
|
||||||
|
if uuid.to_lowercase().as_str() == tag.value() {
|
||||||
|
let devname = dev.name();
|
||||||
|
let devfile = devname.canonicalize()?;
|
||||||
|
let fd = File::open(&devfile)?;
|
||||||
|
let meta = fd.metadata()?;
|
||||||
|
if meta.rdev() != 0 {
|
||||||
|
return Ok(devfile);
|
||||||
|
} else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "not a block device"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "device not found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dev_from_label(s: &str) -> io::Result<PathBuf> {
|
||||||
|
let label = s.strip_prefix("LABEL=").ok_or(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"this should never happen",
|
||||||
|
))?;
|
||||||
|
let cache = Cache::new().map_err(|x| io::Error::new(io::ErrorKind::Other, x))?;
|
||||||
|
let devs = cache.devs();
|
||||||
|
for dev in devs {
|
||||||
|
let tags = dev.tags();
|
||||||
|
for tag in tags {
|
||||||
|
match tag.typ() {
|
||||||
|
TagType::Superblock(SuperblockTag::Label) => {
|
||||||
|
if label == tag.value() {
|
||||||
|
let devname = dev.name();
|
||||||
|
let devfile = devname.canonicalize()?;
|
||||||
|
let fd = File::open(&devfile)?;
|
||||||
|
let meta = fd.metadata()?;
|
||||||
|
if meta.rdev() != 0 {
|
||||||
|
return Ok(devfile);
|
||||||
|
} else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "not a block device"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "device not found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dev_from_partuuid(s: &str) -> io::Result<PathBuf> {
|
||||||
|
let partlabel = s.strip_prefix("PARTUUID=").ok_or(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"this should never happen",
|
||||||
|
))?;
|
||||||
|
let cache = Cache::new().map_err(|x| io::Error::new(io::ErrorKind::Other, x))?;
|
||||||
|
let devs = cache.devs();
|
||||||
|
for dev in devs {
|
||||||
|
let tags = dev.tags();
|
||||||
|
for tag in tags {
|
||||||
|
match tag.typ() {
|
||||||
|
TagType::Partition(PartitionTag::PartEntryUuid) => {
|
||||||
|
if partlabel == tag.value() {
|
||||||
|
let devname = dev.name();
|
||||||
|
let devfile = devname.canonicalize()?;
|
||||||
|
let fd = File::open(&devfile)?;
|
||||||
|
let meta = fd.metadata()?;
|
||||||
|
if meta.rdev() != 0 {
|
||||||
|
return Ok(devfile);
|
||||||
|
} else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "not a block device"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "device not found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dev_from_partlabel(s: &str) -> io::Result<PathBuf> {
|
||||||
|
let partlabel = s.strip_prefix("PARTLABEL=").ok_or(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"this should never happen",
|
||||||
|
))?;
|
||||||
|
let cache = Cache::new().map_err(|x| io::Error::new(io::ErrorKind::Other, x))?;
|
||||||
|
let devs = cache.devs();
|
||||||
|
for dev in devs {
|
||||||
|
let tags = dev.tags();
|
||||||
|
for tag in tags {
|
||||||
|
match tag.typ() {
|
||||||
|
TagType::Partition(PartitionTag::PartEntryName) => {
|
||||||
|
if partlabel == tag.value() {
|
||||||
|
let devname = dev.name();
|
||||||
|
let devfile = devname.canonicalize()?;
|
||||||
|
let fd = File::open(&devfile)?;
|
||||||
|
let meta = fd.metadata()?;
|
||||||
|
if meta.rdev() != 0 {
|
||||||
|
return Ok(devfile);
|
||||||
|
} else {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, "not a block device"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "device not found"))
|
||||||
|
}
|
41
mount/src/mntentries.rs
Normal file
41
mount/src/mntentries.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//! An `Iterator` of the entries in /etc/fstab of /proc/mounts
|
||||||
|
use super::MntEntry;
|
||||||
|
use std::{
|
||||||
|
fs::File,
|
||||||
|
io::{self, BufRead, BufReader, Lines},
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// An `Iterator` of the entries in /etc/fstab of /proc/mounts
|
||||||
|
pub struct MntEntries {
|
||||||
|
lines: Lines<BufReader<File>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MntEntries {
|
||||||
|
/// Create a new `Iterator` over the mounts specified in the file `p`
|
||||||
|
pub fn new<P: AsRef<Path>>(p: P) -> io::Result<Self> {
|
||||||
|
let fd = File::open(p)?;
|
||||||
|
let reader = BufReader::new(fd);
|
||||||
|
Ok(Self {
|
||||||
|
lines: reader.lines(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for MntEntries {
|
||||||
|
type Item = MntEntry;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
loop {
|
||||||
|
if let Some(line) = self.lines.next() {
|
||||||
|
if let Ok(line) = line {
|
||||||
|
if let Ok(entry) = line.parse() {
|
||||||
|
break Some(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
148
mount/src/mntflags.rs
Normal file
148
mount/src/mntflags.rs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
use std::{
|
||||||
|
error::Error,
|
||||||
|
fmt::Display,
|
||||||
|
ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub enum Flags {
|
||||||
|
ReadOnly = 1,
|
||||||
|
NoSuid = 2,
|
||||||
|
NoDev = 4,
|
||||||
|
NoExec = 8,
|
||||||
|
Synchronous = 16,
|
||||||
|
Remount = 32,
|
||||||
|
MandLock = 64,
|
||||||
|
DirSync = 128,
|
||||||
|
NoSymFollow = 256,
|
||||||
|
NoAtime = 1024,
|
||||||
|
NoDirAtime = 2048,
|
||||||
|
Bind = 4096,
|
||||||
|
Move = 8192,
|
||||||
|
Rec = 16384,
|
||||||
|
Silent = 32768,
|
||||||
|
PosixAcl = (1 << 16),
|
||||||
|
UnBindable = (1 << 17),
|
||||||
|
Private = (1 << 18),
|
||||||
|
Slave = (1 << 19),
|
||||||
|
Shared = (1 << 20),
|
||||||
|
RelAtime = (1 << 21),
|
||||||
|
KerrnMount = (1 << 22),
|
||||||
|
IVersion = (1 << 23),
|
||||||
|
StrictAtime = (1 << 24),
|
||||||
|
LazyTime = (1 << 25),
|
||||||
|
NoRemoteLock = (1 << 27),
|
||||||
|
NoSec = (1 << 28),
|
||||||
|
Born = (1 << 29),
|
||||||
|
Active = (1 << 30),
|
||||||
|
NoUser = (1 << 31),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Flags {
|
||||||
|
type Err = ParseFlagsError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"ro" => Ok(Self::ReadOnly),
|
||||||
|
"nosuid" => Ok(Self::NoSuid),
|
||||||
|
"nodev" => Ok(Self::NoDev),
|
||||||
|
"noexec" => Ok(Self::NoExec),
|
||||||
|
"sync" => Ok(Self::Synchronous),
|
||||||
|
"remount" => Ok(Self::Remount),
|
||||||
|
"mand" => Ok(Self::MandLock),
|
||||||
|
"dirsync" => Ok(Self::DirSync),
|
||||||
|
"nosymfollow" => Ok(Self::NoSymFollow),
|
||||||
|
"noatime" => Ok(Self::NoAtime),
|
||||||
|
"nodiratime" => Ok(Self::NoDirAtime),
|
||||||
|
"bind" => Ok(Self::Bind),
|
||||||
|
"silent" => Ok(Self::Silent),
|
||||||
|
"acl" => Ok(Self::PosixAcl),
|
||||||
|
"relatime" => Ok(Self::RelAtime),
|
||||||
|
"iversion" => Ok(Self::IVersion),
|
||||||
|
"strictatime" => Ok(Self::StrictAtime),
|
||||||
|
"lazytime" => Ok(Self::LazyTime),
|
||||||
|
"nomand" => Ok(Self::NoRemoteLock),
|
||||||
|
"nouser" => Ok(Self::NoUser),
|
||||||
|
_ => Err(ParseFlagsError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ParseFlagsError;
|
||||||
|
|
||||||
|
impl Display for ParseFlagsError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ParseFlagsError {}
|
||||||
|
|
||||||
|
impl BitAnd<u32> for Flags {
|
||||||
|
type Output = u32;
|
||||||
|
|
||||||
|
fn bitand(self, rhs: u32) -> Self::Output {
|
||||||
|
self as u32 & rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitAnd<Flags> for u32 {
|
||||||
|
type Output = u32;
|
||||||
|
|
||||||
|
fn bitand(self, rhs: Flags) -> Self::Output {
|
||||||
|
self & rhs as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitAnd for Flags {
|
||||||
|
type Output = u32;
|
||||||
|
|
||||||
|
fn bitand(self, rhs: Self) -> Self::Output {
|
||||||
|
self as u32 & rhs as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitAndAssign<Flags> for u32 {
|
||||||
|
fn bitand_assign(&mut self, rhs: Flags) {
|
||||||
|
*self = *self & rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitOr<u32> for Flags {
|
||||||
|
type Output = u32;
|
||||||
|
|
||||||
|
fn bitor(self, rhs: u32) -> Self::Output {
|
||||||
|
self as u32 | rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitOr<Flags> for u32 {
|
||||||
|
type Output = u32;
|
||||||
|
|
||||||
|
fn bitor(self, rhs: Flags) -> Self::Output {
|
||||||
|
self | rhs as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitOr for Flags {
|
||||||
|
type Output = u32;
|
||||||
|
|
||||||
|
fn bitor(self, rhs: Self) -> Self::Output {
|
||||||
|
self as u32 | rhs as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitOrAssign<Flags> for u32 {
|
||||||
|
fn bitor_assign(&mut self, rhs: Flags) {
|
||||||
|
*self = *self | rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Not for Flags {
|
||||||
|
type Output = u32;
|
||||||
|
|
||||||
|
fn not(self) -> Self::Output {
|
||||||
|
!(self as u32)
|
||||||
|
}
|
||||||
|
}
|
9
pw/Cargo.toml
Normal file
9
pw/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "pw"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = { workspace = true }
|
190
src/cmd/mod.rs
190
src/cmd/mod.rs
@ -1,64 +1,6 @@
|
|||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use std::{error::Error, fmt};
|
use std::{error::Error, fmt};
|
||||||
|
|
||||||
mod b2sum;
|
|
||||||
pub mod base32;
|
|
||||||
mod base64;
|
|
||||||
mod basename;
|
|
||||||
mod bootstrap;
|
|
||||||
mod cat;
|
|
||||||
mod chmod;
|
|
||||||
mod chown;
|
|
||||||
mod chroot;
|
|
||||||
mod clear;
|
|
||||||
mod cp;
|
|
||||||
mod cut;
|
|
||||||
mod date;
|
|
||||||
mod dd;
|
|
||||||
mod dirname;
|
|
||||||
mod echo;
|
|
||||||
mod expand;
|
|
||||||
mod factor;
|
|
||||||
mod r#false;
|
|
||||||
mod fold;
|
|
||||||
mod getty;
|
|
||||||
mod groups;
|
|
||||||
mod head;
|
|
||||||
mod hostid;
|
|
||||||
mod hostname;
|
|
||||||
mod link;
|
|
||||||
mod ln;
|
|
||||||
mod logname;
|
|
||||||
mod ls;
|
|
||||||
mod md5sum;
|
|
||||||
mod mkfifo;
|
|
||||||
mod mknod;
|
|
||||||
mod mktemp;
|
|
||||||
mod mountpoint;
|
|
||||||
mod mv;
|
|
||||||
mod nologin;
|
|
||||||
mod nproc;
|
|
||||||
mod printenv;
|
|
||||||
mod pwd;
|
|
||||||
mod readlink;
|
|
||||||
mod realpath;
|
|
||||||
mod rev;
|
|
||||||
mod rm;
|
|
||||||
mod rmdir;
|
|
||||||
mod sha1sum;
|
|
||||||
mod sha224sum;
|
|
||||||
mod sha256sum;
|
|
||||||
mod sha384sum;
|
|
||||||
mod sha512sum;
|
|
||||||
mod shitbox;
|
|
||||||
mod sleep;
|
|
||||||
mod sync;
|
|
||||||
mod r#true;
|
|
||||||
mod unlink;
|
|
||||||
mod wc;
|
|
||||||
mod which;
|
|
||||||
mod whoami;
|
|
||||||
mod yes;
|
|
||||||
|
|
||||||
/// Defines a command or applet, it's cli interface, and it's installation directory
|
/// Defines a command or applet, it's cli interface, and it's installation directory
|
||||||
/// relative to the binary
|
/// relative to the binary
|
||||||
@ -73,135 +15,3 @@ pub trait Cmd: fmt::Debug + Sync {
|
|||||||
/// will be installed
|
/// will be installed
|
||||||
fn path(&self) -> Option<crate::Path>;
|
fn path(&self) -> Option<crate::Path>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a string into a command to run
|
|
||||||
#[must_use]
|
|
||||||
#[allow(clippy::box_default)]
|
|
||||||
pub fn get(name: &str) -> Option<Box<dyn Cmd>> {
|
|
||||||
match name {
|
|
||||||
"b2sum" => Some(Box::new(b2sum::B2sum::default())),
|
|
||||||
"base64" => Some(Box::new(base64::Base64::default())),
|
|
||||||
"base32" => Some(Box::new(base32::Base32::default())),
|
|
||||||
"basename" => Some(Box::new(basename::Basename::default())),
|
|
||||||
"bootstrap" => Some(Box::new(bootstrap::Bootstrap::default())),
|
|
||||||
"chmod" => Some(Box::new(chmod::Chmod::default())),
|
|
||||||
"chgrp" => Some(Box::new(chown::Chgrp::default())),
|
|
||||||
"chown" => Some(Box::new(chown::Chown::default())),
|
|
||||||
"chroot" => Some(Box::new(chroot::Chroot::default())),
|
|
||||||
"clear" => Some(Box::new(clear::Clear::default())),
|
|
||||||
"cut" => Some(Box::new(cut::Cut::default())),
|
|
||||||
"dirname" => Some(Box::new(dirname::Dirname::default())),
|
|
||||||
"echo" => Some(Box::new(echo::Echo::default())),
|
|
||||||
"factor" => Some(Box::new(factor::Factor::default())),
|
|
||||||
"false" => Some(Box::new(r#false::False::default())),
|
|
||||||
"fold" => Some(Box::new(fold::Fold::default())),
|
|
||||||
"groups" => Some(Box::new(groups::Groups::default())),
|
|
||||||
"head" => Some(Box::new(head::Head::default())),
|
|
||||||
"hostid" => Some(Box::new(hostid::Hostid::default())),
|
|
||||||
"hostname" => Some(Box::new(hostname::Hostname::default())),
|
|
||||||
"link" => Some(Box::new(link::Link::default())),
|
|
||||||
"ln" => Some(Box::new(ln::Ln::default())),
|
|
||||||
"logname" => Some(Box::new(logname::Logname::default())),
|
|
||||||
"md5sum" => Some(Box::new(md5sum::Md5sum::default())),
|
|
||||||
"mkfifo" => Some(Box::new(mkfifo::MkFifo::default())),
|
|
||||||
"mknod" => Some(Box::new(mknod::MkNod::default())),
|
|
||||||
"mktemp" => Some(Box::new(mktemp::MkTemp::default())),
|
|
||||||
"mountpoint" => Some(Box::new(mountpoint::Mountpoint::default())),
|
|
||||||
"nologin" => Some(Box::new(nologin::Nologin::default())),
|
|
||||||
"nproc" => Some(Box::new(nproc::Nproc::default())),
|
|
||||||
"printenv" => Some(Box::new(printenv::Printenv::default())),
|
|
||||||
"pwd" => Some(Box::new(pwd::Pwd::default())),
|
|
||||||
"readlink" => Some(Box::new(readlink::Readlink::default())),
|
|
||||||
"realpath" => Some(Box::new(realpath::Realpath::default())),
|
|
||||||
"rev" => Some(Box::new(rev::Rev::default())),
|
|
||||||
"rm" => Some(Box::new(rm::Rm::default())),
|
|
||||||
"rmdir" => Some(Box::new(rmdir::Rmdir::default())),
|
|
||||||
"sha1sum" => Some(Box::new(sha1sum::Sha1sum::default())),
|
|
||||||
"sha224sum" => Some(Box::new(sha224sum::Sha224sum::default())),
|
|
||||||
"sha256sum" => Some(Box::new(sha256sum::Sha256sum::default())),
|
|
||||||
"sha384sum" => Some(Box::new(sha384sum::Sha384sum::default())),
|
|
||||||
"sha512sum" => Some(Box::new(sha512sum::Sha512sum::default())),
|
|
||||||
"shitbox" => Some(Box::new(shitbox::Shitbox::default())),
|
|
||||||
"sleep" => Some(Box::new(sleep::Sleep::default())),
|
|
||||||
"sync" => Some(Box::new(sync::Sync::default())),
|
|
||||||
"true" => Some(Box::new(r#true::True::default())),
|
|
||||||
"unlink" => Some(Box::new(unlink::Unlink::default())),
|
|
||||||
"wc" => Some(Box::new(wc::Wc::default())),
|
|
||||||
"which" => Some(Box::new(which::Which::default())),
|
|
||||||
"whoami" => Some(Box::new(whoami::Whoami::default())),
|
|
||||||
"yes" => Some(Box::new(yes::Yes::default())),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub static COMMANDS: [&str; 51] = [
|
|
||||||
"b2sum",
|
|
||||||
"base32",
|
|
||||||
"base64",
|
|
||||||
"basename",
|
|
||||||
"bootstrap",
|
|
||||||
"chgrp",
|
|
||||||
"chmod",
|
|
||||||
"chown",
|
|
||||||
"chroot",
|
|
||||||
"clear",
|
|
||||||
"cut",
|
|
||||||
"dirname",
|
|
||||||
"echo",
|
|
||||||
"false",
|
|
||||||
"factor",
|
|
||||||
"fold",
|
|
||||||
"groups",
|
|
||||||
"head",
|
|
||||||
"hostid",
|
|
||||||
"hostname",
|
|
||||||
"link",
|
|
||||||
"ln",
|
|
||||||
"logname",
|
|
||||||
"md5sum",
|
|
||||||
"mkfifo",
|
|
||||||
"mknod",
|
|
||||||
"mktemp",
|
|
||||||
"mountpoint",
|
|
||||||
"nologin",
|
|
||||||
"nproc",
|
|
||||||
"printenv",
|
|
||||||
"pwd",
|
|
||||||
"readlink",
|
|
||||||
"realpath",
|
|
||||||
"rev",
|
|
||||||
"rm",
|
|
||||||
"rmdir",
|
|
||||||
"sha1sum",
|
|
||||||
"sha224sum",
|
|
||||||
"sha256sum",
|
|
||||||
"sha384sum",
|
|
||||||
"sha512sum",
|
|
||||||
"shitbox",
|
|
||||||
"sleep",
|
|
||||||
"sync",
|
|
||||||
"true",
|
|
||||||
"unlink",
|
|
||||||
"wc",
|
|
||||||
"which",
|
|
||||||
"whoami",
|
|
||||||
"yes",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
enum Feedback {
|
|
||||||
Full,
|
|
||||||
Changes,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Feedback {
|
|
||||||
fn from_matches(matches: &ArgMatches) -> Option<Self> {
|
|
||||||
if matches.get_flag("verbose") {
|
|
||||||
Some(Feedback::Full)
|
|
||||||
} else if matches.get_flag("changes") {
|
|
||||||
Some(Feedback::Changes)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
23
src/lib.rs
23
src/lib.rs
@ -1,16 +1,11 @@
|
|||||||
#![warn(clippy::all, clippy::pedantic)]
|
#![warn(clippy::all, clippy::pedantic)]
|
||||||
use std::{env, path::PathBuf, process, string::ToString};
|
use std::{env, path::PathBuf, string::ToString};
|
||||||
|
|
||||||
pub mod args;
|
pub mod args;
|
||||||
pub mod bitflags;
|
|
||||||
mod cmd;
|
mod cmd;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod hash;
|
|
||||||
pub mod math;
|
pub mod math;
|
||||||
pub mod mode;
|
|
||||||
pub mod pw;
|
|
||||||
pub mod stat;
|
pub mod stat;
|
||||||
pub mod unistd;
|
|
||||||
|
|
||||||
pub use cmd::Cmd;
|
pub use cmd::Cmd;
|
||||||
|
|
||||||
@ -62,19 +57,3 @@ pub fn progpath() -> Option<PathBuf> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The entry point of the program
|
|
||||||
pub fn run() {
|
|
||||||
if let Some(progname) = progname() {
|
|
||||||
if let Some(command) = cmd::get(&progname) {
|
|
||||||
let cli = command.cli();
|
|
||||||
if let Err(e) = command.run(&cli.get_matches()) {
|
|
||||||
eprintln!("{progname}: Error: {e}");
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
eprintln!("shitbox: Error: unknown command {progname}");
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
fn main() {
|
|
||||||
shitbox::run();
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
use crate::bitflags::BitFlags;
|
|
||||||
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
|
|
||||||
|
|
||||||
/// Unix permission bit flags
|
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
|
||||||
pub enum Bit {
|
|
||||||
Suid = 0o4000,
|
|
||||||
Sgid = 0o2000,
|
|
||||||
Sticky = 0o1000,
|
|
||||||
URead = 0o400,
|
|
||||||
UWrite = 0o200,
|
|
||||||
UExec = 0o100,
|
|
||||||
GRead = 0o40,
|
|
||||||
GWrite = 0o20,
|
|
||||||
GExec = 0o10,
|
|
||||||
ORead = 0o4,
|
|
||||||
OWrite = 0o2,
|
|
||||||
OExec = 0o1,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitAnd<u32> for Bit {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn bitand(self, rhs: u32) -> Self::Output {
|
|
||||||
self as u32 & rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitAnd<Bit> for u32 {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn bitand(self, rhs: Bit) -> Self::Output {
|
|
||||||
self & rhs as u32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitAnd for Bit {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn bitand(self, rhs: Self) -> Self::Output {
|
|
||||||
self as u32 & rhs as u32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitAndAssign<Bit> for u32 {
|
|
||||||
fn bitand_assign(&mut self, rhs: Bit) {
|
|
||||||
*self = *self & rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitOr<u32> for Bit {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn bitor(self, rhs: u32) -> Self::Output {
|
|
||||||
self as u32 | rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitOr<Bit> for u32 {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn bitor(self, rhs: Bit) -> Self::Output {
|
|
||||||
self | rhs as u32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitOr for Bit {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn bitor(self, rhs: Self) -> Self::Output {
|
|
||||||
self as u32 | rhs as u32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitOrAssign<Bit> for u32 {
|
|
||||||
fn bitor_assign(&mut self, rhs: Bit) {
|
|
||||||
*self = *self | rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bit {
|
|
||||||
pub fn as_char(&self, mode: u32) -> char {
|
|
||||||
if mode & *self != 0 {
|
|
||||||
match self {
|
|
||||||
Self::Suid | Self::Sgid => 's',
|
|
||||||
Self::Sticky => 't',
|
|
||||||
Self::URead | Self::GRead | Self::ORead => 'r',
|
|
||||||
Self::UWrite | Self::GWrite | Self::OWrite => 'w',
|
|
||||||
Self::UExec if mode.contains(Self::Suid) => 's',
|
|
||||||
Self::GExec if mode.contains(Self::Sgid) => 's',
|
|
||||||
Self::OExec if mode.contains(Self::Sticky) => 't',
|
|
||||||
Self::UExec | Self::GExec | Self::OExec => 'x',
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
'-'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
141
src/mode/mod.rs
141
src/mode/mod.rs
@ -1,141 +0,0 @@
|
|||||||
//! Functions for parsing and managing permissions
|
|
||||||
mod bit;
|
|
||||||
mod parser;
|
|
||||||
mod who;
|
|
||||||
use std::fmt::{self, Write};
|
|
||||||
|
|
||||||
pub use {
|
|
||||||
bit::Bit,
|
|
||||||
parser::{ParseError, Parser},
|
|
||||||
who::Who,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Gets the umask for the current user
|
|
||||||
#[must_use]
|
|
||||||
pub fn get_umask() -> u32 {
|
|
||||||
let mask = unsafe { libc::umask(0) };
|
|
||||||
let _mask = unsafe { libc::umask(mask) };
|
|
||||||
mask
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Functions for extracting information about Unix modes
|
|
||||||
pub trait Mode {
|
|
||||||
/// Returns a string representing permissions in symbolic format
|
|
||||||
/// including file type
|
|
||||||
fn mode_string_full(&self) -> Result<String, fmt::Error>;
|
|
||||||
|
|
||||||
/// Returns a string representing permissions in symbolic format
|
|
||||||
/// minus file type
|
|
||||||
fn mode_string(&self) -> Result<String, fmt::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mode for u32 {
|
|
||||||
fn mode_string_full(&self) -> Result<String, fmt::Error> {
|
|
||||||
let b = if self & 0o40000 != 0 && self & 0o20000 != 0 {
|
|
||||||
'b'
|
|
||||||
} else if self & 0o40000 != 0 {
|
|
||||||
'd'
|
|
||||||
} else if self & 0o20000 != 0 {
|
|
||||||
'c'
|
|
||||||
} else {
|
|
||||||
'-'
|
|
||||||
};
|
|
||||||
let mut s = String::new();
|
|
||||||
write!(s, "{b}")?;
|
|
||||||
[
|
|
||||||
Bit::URead,
|
|
||||||
Bit::UWrite,
|
|
||||||
Bit::UExec,
|
|
||||||
Bit::GRead,
|
|
||||||
Bit::GWrite,
|
|
||||||
Bit::GExec,
|
|
||||||
Bit::ORead,
|
|
||||||
Bit::OWrite,
|
|
||||||
Bit::OExec,
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.try_for_each(|b| write!(s, "{}", b.as_char(*self)))?;
|
|
||||||
Ok(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mode_string(&self) -> Result<String, fmt::Error> {
|
|
||||||
let mut s = String::new();
|
|
||||||
[
|
|
||||||
Bit::URead,
|
|
||||||
Bit::UWrite,
|
|
||||||
Bit::UExec,
|
|
||||||
Bit::GRead,
|
|
||||||
Bit::GWrite,
|
|
||||||
Bit::GExec,
|
|
||||||
Bit::ORead,
|
|
||||||
Bit::OWrite,
|
|
||||||
Bit::OExec,
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.try_for_each(|b| write!(s, "{}", b.as_char(*self)))?;
|
|
||||||
Ok(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn getumask() {
|
|
||||||
let mask = unsafe { libc::umask(0o22) };
|
|
||||||
assert_eq!(get_umask(), 0o022);
|
|
||||||
unsafe {
|
|
||||||
libc::umask(mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn display_bits_dir() {
|
|
||||||
let m: u32 = 0o40755;
|
|
||||||
let s = m.mode_string_full().unwrap();
|
|
||||||
assert_eq!(s.as_str(), "drwxr-xr-x")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn display_bits_char() {
|
|
||||||
let m: u32 = 0o20666;
|
|
||||||
let s = m.mode_string_full().unwrap();
|
|
||||||
assert_eq!(s.as_str(), "crw-rw-rw-")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn display_bits_block() {
|
|
||||||
let m: u32 = 0o60660;
|
|
||||||
let s = m.mode_string_full().unwrap();
|
|
||||||
assert_eq!(s.as_str(), "brw-rw----")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn display_bits_file() {
|
|
||||||
let m: u32 = 0o100644;
|
|
||||||
let s = m.mode_string_full().unwrap();
|
|
||||||
assert_eq!(s.as_str(), "-rw-r--r--")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn display_bits_suid() {
|
|
||||||
let m: u32 = 0o104755;
|
|
||||||
let s = m.mode_string_full().unwrap();
|
|
||||||
assert_eq!(s.as_str(), "-rwsr-xr-x")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn display_bits_sgid() {
|
|
||||||
let m: u32 = 0o102755;
|
|
||||||
let s = m.mode_string_full().unwrap();
|
|
||||||
assert_eq!(s.as_str(), "-rwxr-sr-x")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn display_bits_sticky() {
|
|
||||||
let m: u32 = 0o41777;
|
|
||||||
let s = m.mode_string_full().unwrap();
|
|
||||||
assert_eq!(s.as_str(), "drwxrwxrwt")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,386 +0,0 @@
|
|||||||
use super::{get_umask, Bit, Who};
|
|
||||||
use crate::bitflags::BitFlags;
|
|
||||||
use std::{error, fmt::Display, num::ParseIntError};
|
|
||||||
|
|
||||||
/// Errors which might occur when parsing Unix permissions from a string
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum ParseError {
|
|
||||||
/// the given `Bit` cannot be set for the given `Who`
|
|
||||||
InvalidBit,
|
|
||||||
/// the character is not recognized
|
|
||||||
InvalidChar,
|
|
||||||
/// the specified octal mode is invalid
|
|
||||||
OutsideRange,
|
|
||||||
ParseIntError(ParseIntError),
|
|
||||||
/// no `Op` is set when parsing a `Bit`
|
|
||||||
NoOpSet,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for ParseError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{self:?}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl error::Error for ParseError {}
|
|
||||||
|
|
||||||
impl From<ParseIntError> for ParseError {
|
|
||||||
fn from(value: ParseIntError) -> Self {
|
|
||||||
Self::ParseIntError(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
|
||||||
/// Operations which can be performed to add, remove, or set explicitly the given
|
|
||||||
/// `Bit` for the given `Who`
|
|
||||||
enum Op {
|
|
||||||
/// `Bit`s will be added for `Who`
|
|
||||||
Add,
|
|
||||||
/// `Bit`s will be remoed for `Who`
|
|
||||||
Remove,
|
|
||||||
/// `Bit`s will be set to exactly the specified arrangement
|
|
||||||
Equals,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A parser for octal and symbolic permissions. `Parser::default` creates an
|
|
||||||
/// instance which applies the given operations to the default setting for the
|
|
||||||
/// current user's umask. `Parser::new` creates a parser which applies the given
|
|
||||||
/// operations to the specified beginning set of permissions. Therefore, when
|
|
||||||
/// creating new files or directories use `Parser::default`, while `Parser::new`
|
|
||||||
/// should be used for setting permissions of already existing files or directories.
|
|
||||||
pub struct Parser {
|
|
||||||
mode: u32,
|
|
||||||
op: Option<Op>,
|
|
||||||
who: u32,
|
|
||||||
bits: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Parser {
|
|
||||||
fn default() -> Self {
|
|
||||||
let umask = get_umask();
|
|
||||||
let mut mode = 0o0666;
|
|
||||||
mode &= umask;
|
|
||||||
Self {
|
|
||||||
mode,
|
|
||||||
op: None,
|
|
||||||
who: 0,
|
|
||||||
bits: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parser {
|
|
||||||
#[must_use]
|
|
||||||
pub fn new(mode: u32) -> Self {
|
|
||||||
Self {
|
|
||||||
mode,
|
|
||||||
op: None,
|
|
||||||
who: 0,
|
|
||||||
bits: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_octal(value: &str) -> Result<u32, ParseError> {
|
|
||||||
let m = u32::from_str_radix(value, 8)?;
|
|
||||||
if m <= 0o7777 {
|
|
||||||
Ok(m)
|
|
||||||
} else {
|
|
||||||
Err(ParseError::OutsideRange)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_who(&mut self, who: Who) -> Result<(), ParseError> {
|
|
||||||
if self.op.is_some() || !self.bits == 0 {
|
|
||||||
Err(ParseError::InvalidChar)
|
|
||||||
} else {
|
|
||||||
self.who |= who;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_op(&mut self, op: Op) -> Result<(), ParseError> {
|
|
||||||
if self.op.is_some() || !self.bits == 0 {
|
|
||||||
Err(ParseError::InvalidChar)
|
|
||||||
} else {
|
|
||||||
self.op = Some(op);
|
|
||||||
if self.who == 0 {
|
|
||||||
self.who |= 0o111;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_read_bits(&mut self) -> Result<(), ParseError> {
|
|
||||||
if self.op.is_none() {
|
|
||||||
Err(ParseError::NoOpSet)
|
|
||||||
} else {
|
|
||||||
if self.who.contains(Who::User) {
|
|
||||||
self.bits |= Bit::URead;
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Group) {
|
|
||||||
self.bits |= Bit::GRead;
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Other) {
|
|
||||||
self.bits |= Bit::ORead;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_write_bits(&mut self) -> Result<(), ParseError> {
|
|
||||||
if self.op.is_none() {
|
|
||||||
Err(ParseError::NoOpSet)
|
|
||||||
} else {
|
|
||||||
if self.who.contains(Who::User) {
|
|
||||||
self.bits |= Bit::UWrite;
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Group) {
|
|
||||||
self.bits |= Bit::GWrite;
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Other) {
|
|
||||||
self.bits |= Bit::OWrite;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_exec_bits(&mut self) -> Result<(), ParseError> {
|
|
||||||
if self.op.is_none() {
|
|
||||||
Err(ParseError::NoOpSet)
|
|
||||||
} else {
|
|
||||||
if self.who.contains(Who::User) {
|
|
||||||
self.bits |= Bit::UExec;
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Group) {
|
|
||||||
self.bits |= Bit::GExec;
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Other) {
|
|
||||||
self.bits |= Bit::OExec;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_suid_sgid(&mut self) -> Result<(), ParseError> {
|
|
||||||
if self.who == 0 || self.who.contains(Who::Other) {
|
|
||||||
return Err(ParseError::InvalidBit);
|
|
||||||
} else if self.op.is_none() {
|
|
||||||
return Err(ParseError::NoOpSet);
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::User) {
|
|
||||||
self.bits |= Bit::Suid;
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Group) {
|
|
||||||
self.bits |= Bit::Sgid;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_sticky(&mut self) -> Result<(), ParseError> {
|
|
||||||
if self.who == 0 || self.who.contains(Who::User) || self.who.contains(Who::Group) {
|
|
||||||
return Err(ParseError::InvalidBit);
|
|
||||||
} else if self.op.is_none() {
|
|
||||||
return Err(ParseError::NoOpSet);
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Other) {
|
|
||||||
self.bits |= Bit::Sticky;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_bits(&mut self) {
|
|
||||||
self.mode |= self.bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_bits(&mut self) {
|
|
||||||
self.mode &= !self.bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_bits(&mut self) -> Result<(), ParseError> {
|
|
||||||
match self.op {
|
|
||||||
Some(Op::Add) => self.add_bits(),
|
|
||||||
Some(Op::Remove) => self.remove_bits(),
|
|
||||||
Some(Op::Equals) => {
|
|
||||||
if self.who.contains(Who::User) {
|
|
||||||
self.mode &= !(0o4700);
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Group) {
|
|
||||||
self.mode &= !(0o2070);
|
|
||||||
}
|
|
||||||
if self.who.contains(Who::Other) {
|
|
||||||
self.mode &= !(0o1007);
|
|
||||||
}
|
|
||||||
self.add_bits();
|
|
||||||
}
|
|
||||||
None => return Err(ParseError::NoOpSet),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reset(&mut self) {
|
|
||||||
self.who = 0;
|
|
||||||
self.op = None;
|
|
||||||
self.bits = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn mode(&self) -> u32 {
|
|
||||||
self.mode
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses a numerical mode from either an octal string or symbolic representation
|
|
||||||
/// and applies those permissions to the starting set of permissions.
|
|
||||||
/// # Errors
|
|
||||||
/// Returns `ParseError` if:
|
|
||||||
/// - invalid digit
|
|
||||||
/// - no operation specified
|
|
||||||
/// - more than one operation specified at a time (multiple operations can
|
|
||||||
/// be specified separated by comma)
|
|
||||||
/// - the specified bit cannot be applied to the specified `Who`
|
|
||||||
/// - bits are specified before operations
|
|
||||||
/// - the specified octal mode is greater than 0o7777
|
|
||||||
pub fn parse(&mut self, value: &str) -> Result<u32, ParseError> {
|
|
||||||
match Self::parse_octal(value) {
|
|
||||||
Ok(mode) => {
|
|
||||||
self.mode = mode;
|
|
||||||
return Ok(mode);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
if e == ParseError::OutsideRange {
|
|
||||||
return Err(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for c in value.chars() {
|
|
||||||
match c {
|
|
||||||
'u' => self.add_who(Who::User)?,
|
|
||||||
'g' => self.add_who(Who::Group)?,
|
|
||||||
'o' => self.add_who(Who::Other)?,
|
|
||||||
'a' => {
|
|
||||||
self.add_who(Who::User)?;
|
|
||||||
self.add_who(Who::Group)?;
|
|
||||||
self.add_who(Who::Other)?;
|
|
||||||
}
|
|
||||||
'-' => self.set_op(Op::Remove)?,
|
|
||||||
'+' => self.set_op(Op::Add)?,
|
|
||||||
'=' => self.set_op(Op::Equals)?,
|
|
||||||
'r' => self.push_read_bits()?,
|
|
||||||
'w' => self.push_write_bits()?,
|
|
||||||
'x' => self.push_exec_bits()?,
|
|
||||||
's' => self.push_suid_sgid()?,
|
|
||||||
't' => self.push_sticky()?,
|
|
||||||
',' => {
|
|
||||||
self.set_bits()?;
|
|
||||||
self.reset();
|
|
||||||
}
|
|
||||||
_ => return Err(ParseError::InvalidChar),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.set_bits()?;
|
|
||||||
self.reset();
|
|
||||||
Ok(self.mode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn add() {
|
|
||||||
let mut parser = Parser::new(0o644);
|
|
||||||
let mode = parser.parse("ug+x");
|
|
||||||
assert_eq!(mode, Ok(0o754));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn remove() {
|
|
||||||
let mut parser = Parser::new(0o777);
|
|
||||||
let mode = parser.parse("go-wx");
|
|
||||||
assert_eq!(mode, Ok(0o744));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn octal() {
|
|
||||||
let mut parser = Parser::default();
|
|
||||||
let mode = parser.parse("4755");
|
|
||||||
assert_eq!(mode, Ok(0o4755));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn equals() {
|
|
||||||
let mut parser = Parser::new(0o701);
|
|
||||||
let mode = parser.parse("ugo=rw");
|
|
||||||
assert_eq!(mode, Ok(0o666));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn o_equals() {
|
|
||||||
let mut parser = Parser::new(0o752);
|
|
||||||
let mode = parser.parse("o=rx");
|
|
||||||
assert_eq!(mode, Ok(0o755));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn empty_who() {
|
|
||||||
let mut parser = Parser::new(0o644);
|
|
||||||
let mode = parser.parse("+x");
|
|
||||||
assert_eq!(mode, Ok(0o755));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn compound_ops() {
|
|
||||||
let mut parser = Parser::new(0o666);
|
|
||||||
let mode = parser.parse("u+x,g-w,o-r");
|
|
||||||
assert_eq!(mode, Ok(0o742));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn compount_ops2() {
|
|
||||||
let mut parser = Parser::new(0o4444);
|
|
||||||
let mode = parser.parse("u+w,ug+x,o=rx,u-s");
|
|
||||||
assert_eq!(mode, Ok(0o755));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn invalid_sticky_bit() {
|
|
||||||
let mut parser = Parser::default();
|
|
||||||
let mode = parser.parse("u+t");
|
|
||||||
assert_eq!(mode, Err(ParseError::InvalidBit));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn invalid_s() {
|
|
||||||
let mut parser = Parser::default();
|
|
||||||
let mode = parser.parse("+s");
|
|
||||||
assert_eq!(mode, Err(ParseError::InvalidBit));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn outside_range() {
|
|
||||||
let mut parser = Parser::default();
|
|
||||||
let mode = parser.parse("10000");
|
|
||||||
assert_eq!(mode, Err(ParseError::OutsideRange))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_op() {
|
|
||||||
let mut parser = Parser::default();
|
|
||||||
let mode = parser.parse("rws");
|
|
||||||
assert_eq!(mode, Err(ParseError::NoOpSet));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ordering_error() {
|
|
||||||
let mut parser = Parser::default();
|
|
||||||
let mode = parser.parse("ux+s");
|
|
||||||
assert_eq!(mode, Err(ParseError::NoOpSet));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ordering_error1() {
|
|
||||||
let mut parser = Parser::default();
|
|
||||||
let mode = parser.parse("x+s");
|
|
||||||
assert_eq!(mode, Err(ParseError::NoOpSet));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
|
||||||
/// The granularity of the given permissions
|
|
||||||
pub enum Who {
|
|
||||||
/// applies for the current user
|
|
||||||
User = 0o100,
|
|
||||||
/// applies for the current group
|
|
||||||
Group = 0o10,
|
|
||||||
/// applies for everyone else
|
|
||||||
Other = 0o1,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitAnd<Who> for u32 {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn bitand(self, rhs: Who) -> Self::Output {
|
|
||||||
self & rhs as u32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitAnd<u32> for Who {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn bitand(self, rhs: u32) -> Self::Output {
|
|
||||||
self as u32 & rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitAndAssign<Who> for u32 {
|
|
||||||
fn bitand_assign(&mut self, rhs: Who) {
|
|
||||||
*self = *self & rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitOr<Who> for u32 {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn bitor(self, rhs: Who) -> Self::Output {
|
|
||||||
self | rhs as u32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitOrAssign<Who> for u32 {
|
|
||||||
fn bitor_assign(&mut self, rhs: Who) {
|
|
||||||
*self = *self | rhs;
|
|
||||||
}
|
|
||||||
}
|
|
10
unistd/Cargo.toml
Normal file
10
unistd/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "unistd"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = { workspace = true }
|
||||||
|
sc = { workspace = true }
|
1
unix-mode
Submodule
1
unix-mode
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 0bbf1aed9ad583017b90aa2c03d3f7870538a914
|
Loading…
Reference in New Issue
Block a user