├── .github
└── workflows
│ └── check.yml
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── dmesg
├── Cargo.toml
└── src
│ └── main.rs
├── fdisk
├── Cargo.toml
└── src
│ ├── crc32.rs
│ ├── disk.rs
│ ├── guid.rs
│ ├── lib.rs
│ ├── main.rs
│ └── partition.rs
├── insmod
├── Cargo.toml
└── src
│ └── main.rs
├── login
├── Cargo.toml
└── src
│ └── main.rs
├── lsmod
├── Cargo.toml
└── src
│ └── main.rs
├── mkfs
├── Cargo.toml
└── src
│ ├── ext2.rs
│ └── main.rs
├── mount
├── Cargo.toml
└── src
│ └── main.rs
├── nologin
├── Cargo.toml
└── src
│ └── main.rs
├── powerctl
├── Cargo.toml
└── src
│ ├── main.rs
│ └── power.rs
├── ps
├── Cargo.toml
└── src
│ ├── format.rs
│ ├── main.rs
│ ├── process
│ ├── mod.rs
│ └── status_parser.rs
│ └── util.rs
├── rmmod
├── Cargo.toml
└── src
│ └── main.rs
├── su
├── Cargo.toml
└── src
│ └── main.rs
├── umount
├── Cargo.toml
└── src
│ └── main.rs
├── usrgrp
├── Cargo.toml
└── src
│ └── main.rs
└── utils
├── Cargo.toml
└── src
├── disk.rs
├── lib.rs
├── prompt.rs
├── user.rs
└── util.rs
/.github/workflows/check.yml:
--------------------------------------------------------------------------------
1 | name: Check
2 | on: push
3 | jobs:
4 | build:
5 | runs-on: [self-hosted, linux]
6 | steps:
7 | - uses: actions/checkout@v3
8 | - name: Debug
9 | run: cargo +nightly build
10 | - name: Release
11 | run: cargo +nightly build --release
12 | test:
13 | runs-on: [self-hosted, linux]
14 | needs: build
15 | steps:
16 | - uses: actions/checkout@v3
17 | - name: Test
18 | run: cargo +nightly test
19 | format:
20 | runs-on: [self-hosted, linux]
21 | steps:
22 | - uses: actions/checkout@v3
23 | - run: cargo +nightly fmt --check
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "argon2"
7 | version = "0.5.2"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "17ba4cac0a46bc1d2912652a751c47f2a9f3a7fe89bcae2275d418f5270402f9"
10 | dependencies = [
11 | "base64ct",
12 | "blake2",
13 | "cpufeatures",
14 | "password-hash",
15 | ]
16 |
17 | [[package]]
18 | name = "base64ct"
19 | version = "1.6.0"
20 | source = "registry+https://github.com/rust-lang/crates.io-index"
21 | checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
22 |
23 | [[package]]
24 | name = "blake2"
25 | version = "0.10.6"
26 | source = "registry+https://github.com/rust-lang/crates.io-index"
27 | checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
28 | dependencies = [
29 | "digest",
30 | ]
31 |
32 | [[package]]
33 | name = "block-buffer"
34 | version = "0.10.4"
35 | source = "registry+https://github.com/rust-lang/crates.io-index"
36 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
37 | dependencies = [
38 | "generic-array",
39 | ]
40 |
41 | [[package]]
42 | name = "cfg-if"
43 | version = "1.0.0"
44 | source = "registry+https://github.com/rust-lang/crates.io-index"
45 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
46 |
47 | [[package]]
48 | name = "cpufeatures"
49 | version = "0.2.11"
50 | source = "registry+https://github.com/rust-lang/crates.io-index"
51 | checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
52 | dependencies = [
53 | "libc",
54 | ]
55 |
56 | [[package]]
57 | name = "crypto-common"
58 | version = "0.1.6"
59 | source = "registry+https://github.com/rust-lang/crates.io-index"
60 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
61 | dependencies = [
62 | "generic-array",
63 | "typenum",
64 | ]
65 |
66 | [[package]]
67 | name = "digest"
68 | version = "0.10.7"
69 | source = "registry+https://github.com/rust-lang/crates.io-index"
70 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
71 | dependencies = [
72 | "block-buffer",
73 | "crypto-common",
74 | "subtle",
75 | ]
76 |
77 | [[package]]
78 | name = "dmesg"
79 | version = "0.1.0"
80 |
81 | [[package]]
82 | name = "fdisk"
83 | version = "0.1.0"
84 | dependencies = [
85 | "libc",
86 | "utils",
87 | ]
88 |
89 | [[package]]
90 | name = "generic-array"
91 | version = "0.14.7"
92 | source = "registry+https://github.com/rust-lang/crates.io-index"
93 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
94 | dependencies = [
95 | "typenum",
96 | "version_check",
97 | ]
98 |
99 | [[package]]
100 | name = "getrandom"
101 | version = "0.2.11"
102 | source = "registry+https://github.com/rust-lang/crates.io-index"
103 | checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
104 | dependencies = [
105 | "cfg-if",
106 | "libc",
107 | "wasi",
108 | ]
109 |
110 | [[package]]
111 | name = "insmod"
112 | version = "0.1.0"
113 | dependencies = [
114 | "libc",
115 | "utils",
116 | ]
117 |
118 | [[package]]
119 | name = "libc"
120 | version = "0.2.150"
121 | source = "registry+https://github.com/rust-lang/crates.io-index"
122 | checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
123 |
124 | [[package]]
125 | name = "login"
126 | version = "0.1.0"
127 | dependencies = [
128 | "libc",
129 | "utils",
130 | ]
131 |
132 | [[package]]
133 | name = "lsmod"
134 | version = "0.1.0"
135 |
136 | [[package]]
137 | name = "mkfs"
138 | version = "0.1.0"
139 | dependencies = [
140 | "utils",
141 | ]
142 |
143 | [[package]]
144 | name = "mount"
145 | version = "0.1.0"
146 | dependencies = [
147 | "libc",
148 | ]
149 |
150 | [[package]]
151 | name = "nologin"
152 | version = "0.1.0"
153 |
154 | [[package]]
155 | name = "password-hash"
156 | version = "0.5.0"
157 | source = "registry+https://github.com/rust-lang/crates.io-index"
158 | checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
159 | dependencies = [
160 | "base64ct",
161 | "rand_core",
162 | "subtle",
163 | ]
164 |
165 | [[package]]
166 | name = "powerctl"
167 | version = "0.1.0"
168 | dependencies = [
169 | "libc",
170 | "utils",
171 | ]
172 |
173 | [[package]]
174 | name = "ps"
175 | version = "0.1.0"
176 | dependencies = [
177 | "utils",
178 | ]
179 |
180 | [[package]]
181 | name = "rand_core"
182 | version = "0.6.4"
183 | source = "registry+https://github.com/rust-lang/crates.io-index"
184 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
185 | dependencies = [
186 | "getrandom",
187 | ]
188 |
189 | [[package]]
190 | name = "rmmod"
191 | version = "0.1.0"
192 | dependencies = [
193 | "libc",
194 | "utils",
195 | ]
196 |
197 | [[package]]
198 | name = "su"
199 | version = "0.1.0"
200 | dependencies = [
201 | "utils",
202 | ]
203 |
204 | [[package]]
205 | name = "subtle"
206 | version = "2.5.0"
207 | source = "registry+https://github.com/rust-lang/crates.io-index"
208 | checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
209 |
210 | [[package]]
211 | name = "typenum"
212 | version = "1.17.0"
213 | source = "registry+https://github.com/rust-lang/crates.io-index"
214 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
215 |
216 | [[package]]
217 | name = "umount"
218 | version = "0.1.0"
219 | dependencies = [
220 | "libc",
221 | ]
222 |
223 | [[package]]
224 | name = "usrgrp"
225 | version = "0.1.0"
226 |
227 | [[package]]
228 | name = "utils"
229 | version = "0.1.0"
230 | dependencies = [
231 | "argon2",
232 | "libc",
233 | "rand_core",
234 | ]
235 |
236 | [[package]]
237 | name = "version_check"
238 | version = "0.9.4"
239 | source = "registry+https://github.com/rust-lang/crates.io-index"
240 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
241 |
242 | [[package]]
243 | name = "wasi"
244 | version = "0.11.0+wasi-snapshot-preview1"
245 | source = "registry+https://github.com/rust-lang/crates.io-index"
246 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
247 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 |
3 | resolver = "2"
4 |
5 | members = [
6 | "dmesg",
7 | "fdisk",
8 | "insmod",
9 | "login",
10 | "lsmod",
11 | "mkfs",
12 | "mount",
13 | "nologin",
14 | "powerctl",
15 | "ps",
16 | "rmmod",
17 | "su",
18 | "umount",
19 | "usrgrp",
20 | "utils",
21 | ]
22 |
23 | [profile.release]
24 | panic = "abort"
25 | strip = true
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Luc Lenôtre
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | [](./LICENSE)
9 | 
10 |
11 |
12 |
13 | # About
14 |
15 | maestro-utils provides utility commands for the Maestro operating system:
16 | - User management:
17 | - su
18 | - passwd
19 | - useradd
20 | - userdel
21 | - usermod
22 | - groupadd
23 | - groupdel
24 | - groupmod
25 | - login
26 | - nologin
27 | - Kernel utilities:
28 | - dmesg
29 | - mount
30 | - umount
31 | - insmod
32 | - rmmod
33 | - lsmod
34 | - Filesystem utilities:
35 | - fdisk
36 | - sfdisk
37 | - mkfs
38 | - fsck
39 | - System power:
40 | - halt
41 | - poweroff
42 | - shutdown
43 | - reboot
44 |
--------------------------------------------------------------------------------
/dmesg/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "dmesg"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 |
--------------------------------------------------------------------------------
/dmesg/src/main.rs:
--------------------------------------------------------------------------------
1 | //! The `dmesg` command allows to print the kernel's logs.
2 |
3 | use std::env;
4 |
5 | /// The path to the kmsg device file.
6 | const KMSG_PATH: &str = "/dev/kmsg";
7 |
8 | fn main() {
9 | let _args: Vec = env::args().collect();
10 | // TODO parse arguments
11 |
12 | // TODO read non blocking from file
13 | // TODO for each line:
14 | // - split once with `;`
15 | // - split left with `,`, then retrieve time, facility and level
16 | // - format and print
17 | }
18 |
--------------------------------------------------------------------------------
/fdisk/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "fdisk"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [lib]
7 | name = "fdisk"
8 | path = "src/lib.rs"
9 |
10 | [[bin]]
11 | name = "fdisk"
12 | path = "src/main.rs"
13 |
14 | [dependencies]
15 | libc = "*"
16 | utils = { path = "../utils" }
17 |
--------------------------------------------------------------------------------
/fdisk/src/crc32.rs:
--------------------------------------------------------------------------------
1 | //! TODO doc
2 |
3 | // TODO
4 |
5 | /// Computes the lookup table for the given generator polynomial.
6 | ///
7 | /// Arguments:
8 | /// - `table` is filled with the table's values.
9 | /// - `polynom` is the polynom.
10 | pub fn compute_lookuptable(table: &mut [u32; 256], polynom: u32) {
11 | // Little endian
12 | let mut i = table.len() / 2;
13 | let mut crc = 1;
14 |
15 | while i > 0 {
16 | if crc & 1 != 0 {
17 | crc = (crc >> 1) ^ polynom;
18 | } else {
19 | crc >>= 1;
20 | }
21 |
22 | for j in (0..table.len()).step_by(2 * i) {
23 | table[i ^ j] = crc ^ table[j];
24 | }
25 |
26 | i >>= 1;
27 | }
28 | }
29 |
30 | /// Computes the CRC32 checksum on the given data `data` with the given table
31 | /// `table` for the wanted generator polynomial.
32 | pub fn compute(data: &[u8], table: &[u32; 256]) -> u32 {
33 | // Sarwate algorithm
34 | let mut crc = !0u32;
35 |
36 | for b in data {
37 | let i = ((crc as usize) ^ (*b as usize)) & 0xff;
38 | crc = table[i] ^ (crc >> 8);
39 | }
40 |
41 | !crc
42 | }
43 |
44 | // TODO Test CRC32
45 |
--------------------------------------------------------------------------------
/fdisk/src/disk.rs:
--------------------------------------------------------------------------------
1 | //! TODO doc
2 |
3 | use crate::partition::PartitionTable;
4 | use libc::c_long;
5 | use libc::ioctl;
6 | use std::fmt;
7 | use std::fs;
8 | use std::fs::{File, OpenOptions};
9 | use std::io;
10 | use std::io::Error;
11 | use std::os::fd::AsRawFd;
12 | use std::path::Path;
13 | use std::path::PathBuf;
14 | use utils::util::ByteSize;
15 |
16 | /// ioctl command: Read a partitions table.
17 | const BLKRRPART: c_long = 0x125f;
18 |
19 | /// Structure representing a disk, containing partitions.
20 | pub struct Disk {
21 | /// The path to the disk's device file.
22 | dev_path: PathBuf,
23 | /// The size of the disk in number of sectors.
24 | size: u64,
25 | /// The open device.
26 | dev: File,
27 |
28 | /// The partition table.
29 | pub partition_table: PartitionTable,
30 | }
31 |
32 | impl Disk {
33 | /// Tells whether the device file at the given path is a valid disk.
34 | ///
35 | /// This function is meant to be used when listing disks.
36 | fn is_valid(path: &Path) -> bool {
37 | let Some(path_str) = path.as_os_str().to_str() else {
38 | return false;
39 | };
40 |
41 | if path_str.starts_with("/dev/sd") && !path_str.contains(|c: char| c.is_numeric()) {
42 | return true;
43 | }
44 | if path_str.starts_with("/dev/hd") && !path_str.contains(|c: char| c.is_numeric()) {
45 | return true;
46 | }
47 | if path_str.starts_with("/dev/nvme0n") && !path_str.contains('p') {
48 | // FIXME
49 | return true;
50 | }
51 |
52 | // TODO Add floppy, cdrom, etc...
53 |
54 | false
55 | }
56 |
57 | /// Reads a disk's informations from the given device path `dev_path`.
58 | ///
59 | /// If the path doesn't point to a valid device, the function returns None.
60 | pub fn read(dev_path: PathBuf) -> io::Result