├── .gitignore ├── src ├── lib.rs ├── config │ ├── package.rs │ ├── user.rs │ ├── file.rs │ ├── general.rs │ ├── file_impl.rs │ └── mod.rs ├── disk_wrapper.rs ├── bin │ ├── installer.rs │ └── installer_tui.rs └── installer.rs ├── config ├── minimal.toml └── default.toml ├── test.sh ├── res ├── update.sh └── test.toml ├── .gitlab-ci.yml ├── LICENSE ├── README.md ├── Cargo.toml └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | sysroot 3 | /target/ 4 | /test.bin 5 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate serde_derive; 3 | 4 | mod config; 5 | #[cfg(feature = "installer")] 6 | mod disk_wrapper; 7 | #[cfg(feature = "installer")] 8 | mod installer; 9 | #[cfg(feature = "installer")] 10 | pub use crate::installer::*; 11 | 12 | pub use crate::config::file::FileConfig; 13 | pub use crate::config::package::PackageConfig; 14 | pub use crate::config::Config; 15 | -------------------------------------------------------------------------------- /src/config/package.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone, Debug, Deserialize, Serialize)] 2 | #[serde(untagged)] 3 | pub enum PackageConfig { 4 | Empty, 5 | Build(String), 6 | 7 | // TODO: Sum type 8 | Spec { 9 | version: Option, 10 | git: Option, 11 | path: Option, 12 | }, 13 | } 14 | 15 | impl Default for PackageConfig { 16 | fn default() -> Self { 17 | Self::Empty 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/minimal.toml: -------------------------------------------------------------------------------- 1 | # This is the default configuration file 2 | 3 | # General settings 4 | [general] 5 | # Do not prompt if settings are not defined 6 | prompt = false 7 | 8 | # Package settings 9 | [packages] 10 | binutils = {} 11 | coreutils = {} 12 | extrautils = {} 13 | ion = {} 14 | netutils = {} 15 | pkgutils = {} 16 | userutils = {} 17 | 18 | # User settings 19 | [users.root] 20 | password = "password" 21 | uid = 0 22 | gid = 0 23 | name = "root" 24 | home = "/root" 25 | -------------------------------------------------------------------------------- /src/config/user.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone, Debug, Default, Deserialize, Serialize)] 2 | pub struct UserConfig { 3 | pub password: Option, 4 | pub uid: Option, 5 | pub gid: Option, 6 | pub name: Option, 7 | pub home: Option, 8 | pub shell: Option, 9 | } 10 | 11 | #[derive(Clone, Debug, Default, Deserialize, Serialize)] 12 | pub struct GroupConfig { 13 | pub gid: Option, 14 | // FIXME move this to the UserConfig struct as extra_groups 15 | pub members: Vec, 16 | } 17 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | IMAGE=test.bin 4 | 5 | QEMU_ARGS=( 6 | -cpu max 7 | -machine q35 8 | -m 2048 9 | -smp 4 10 | -serial mon:stdio 11 | -netdev user,id=net0 12 | -device e1000,netdev=net0 13 | ) 14 | 15 | if [ -e /dev/kvm ] 16 | then 17 | QEMU_ARGS+=(-accel kvm) 18 | fi 19 | 20 | set -ex 21 | 22 | cargo build --release 23 | 24 | rm -f "${IMAGE}" 25 | fallocate -l 1GiB "${IMAGE}" 26 | 27 | target/release/redox_installer -c res/test.toml "${IMAGE}" 28 | 29 | qemu-system-x86_64 "${QEMU_ARGS[@]}" -drive "file=${IMAGE},format=raw" 30 | -------------------------------------------------------------------------------- /res/update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | RES_PATH="$(dirname "$0")" 6 | 7 | if [ -d "$1" ] 8 | then 9 | REDOX_PATH="$1" 10 | else 11 | echo "$0 [path to redox repository]" >&2 12 | exit 1 13 | fi 14 | 15 | set -x 16 | 17 | # Update res/test.toml from the redoxer.toml template 18 | "${REDOX_PATH}/build/fstools/bin/redox_installer" \ 19 | --config="${REDOX_PATH}/config/x86_64/minimal-net.toml" \ 20 | --output-config="${RES_PATH}/test.toml" 21 | sed -i '1s/^/# Automatically generated by update.sh\n\n/' "${RES_PATH}/test.toml" 22 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: "rust:latest" 2 | 3 | stages: 4 | - lint 5 | - test 6 | 7 | workflow: 8 | rules: 9 | - if: '$CI_COMMIT_BRANCH == "master"' 10 | - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"' 11 | 12 | fmt: 13 | stage: lint 14 | script: 15 | - rustup component add rustfmt 16 | - cargo fmt -- --check 17 | 18 | cargo-test: 19 | stage: test 20 | script: 21 | - apt update && apt install -y fuse3 libfuse3-dev 22 | - cargo build --locked 23 | - cargo test 24 | - fallocate -l 256MiB test.bin 25 | - ./target/debug/redox_installer -c res/test.toml test.bin --no-mount 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Redox OS 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 | -------------------------------------------------------------------------------- /src/config/file.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone, Debug, Default, Deserialize, Serialize)] 2 | pub struct FileConfig { 3 | pub path: String, 4 | pub data: String, 5 | #[serde(default)] 6 | pub symlink: bool, 7 | #[serde(default)] 8 | pub directory: bool, 9 | pub mode: Option, 10 | pub uid: Option, 11 | pub gid: Option, 12 | #[serde(default)] 13 | pub recursive_chown: bool, 14 | #[serde(default)] 15 | pub postinstall: bool, 16 | } 17 | 18 | impl FileConfig { 19 | pub fn new_file(path: String, data: String) -> FileConfig { 20 | FileConfig { 21 | path, 22 | data, 23 | ..Default::default() 24 | } 25 | } 26 | 27 | pub fn new_directory(path: String) -> FileConfig { 28 | FileConfig { 29 | path, 30 | data: String::new(), 31 | directory: true, 32 | ..Default::default() 33 | } 34 | } 35 | 36 | pub fn with_mod(&mut self, mode: u32, uid: u32, gid: u32) -> &mut FileConfig { 37 | self.mode = Some(mode); 38 | self.uid = Some(uid); 39 | self.gid = Some(gid); 40 | self 41 | } 42 | 43 | pub fn with_recursive_mod(&mut self, mode: u32, uid: u32, gid: u32) -> &mut FileConfig { 44 | self.with_mod(mode, uid, gid); 45 | self.recursive_chown = true; 46 | self 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Redox OS installer 2 | 3 | The Redox installer will allow you to produce a Redox OS image. You will 4 | be able to specify: 5 | - Output device (raw image, ISO, QEMU, VirtualBox, drive) 6 | - Filesystem 7 | - Included packages 8 | - Method of installation (from source, from binary) 9 | - User accounts 10 | 11 | You will be prompted to install dependencies, based on your OS and method of 12 | installation. The easiest method is to install from binaries. 13 | 14 | ## Usage 15 | 16 | It is recommended to compile with `cargo`, in release mode: 17 | ```bash 18 | cargo build --release 19 | ``` 20 | 21 | By default, you will be prompted to supply configuration options. You can 22 | use the scripted mode by supplying a configuration file: 23 | ```bash 24 | cargo run --release -- config/example.toml 25 | ``` 26 | An example configuration can be found in [config/example.toml](./config/example.toml). 27 | Unsuplied configuration will use the default. You can use the `general.prompt` 28 | setting to prompt when configuration is not set. Multiple configurations can 29 | be specified, they will be built in order. 30 | 31 | ## Embedding 32 | 33 | The installer can also be used inside of other crates, as a library: 34 | 35 | ```toml 36 | # Cargo.toml 37 | [dependencies] 38 | redox_installer = "0.1" 39 | ``` 40 | 41 | ```rust 42 | // src/main.rs 43 | extern crate redox_installer; 44 | 45 | fn main() { 46 | let mut config = redox_installer::Config::default(); 47 | ... 48 | redox_installer::install(config); 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "redox_installer" 3 | version = "0.2.38" 4 | description = "A Redox filesystem builder" 5 | license = "MIT" 6 | authors = ["Jeremy Soller "] 7 | repository = "https://gitlab.redox-os.org/redox-os/installer" 8 | default-run = "redox_installer" 9 | edition = "2021" 10 | 11 | [[bin]] 12 | name = "redox_installer" 13 | path = "src/bin/installer.rs" 14 | required-features = ["installer"] 15 | 16 | [[bin]] 17 | name = "redox_installer_tui" 18 | path = "src/bin/installer_tui.rs" 19 | required-features = ["installer"] 20 | 21 | [lib] 22 | name = "redox_installer" 23 | path = "src/lib.rs" 24 | 25 | [dependencies] 26 | anyhow = "1" 27 | arg_parser = { version = "0.1.0", optional = true } 28 | fatfs = { version = "0.3.0", optional = true } 29 | fscommon = { version = "0.1.1", optional = true } 30 | gpt = { version = "3.0.0", optional = true } 31 | libc = "0.2.70" 32 | pkgar = { version = "0.1.19", optional = true } 33 | pkgar-core = { version = "0.1.19", optional = true } 34 | pkgar-keys = { version = "0.1.19", optional = true } 35 | rand = { version = "0.9", optional = true } 36 | redox-pkg = { version = "0.2.9", features = ["indicatif"], optional = true } 37 | redox_syscall = { version = "0.5.2", optional = true } 38 | redoxfs = { version = "0.8", optional = true } 39 | rust-argon2 = { version = "0.8.2", optional = true } 40 | serde = "1" 41 | serde_derive = "1.0" 42 | termion = { version = "4", optional = true } 43 | toml = "0.8" 44 | uuid = { version = "1.4", features = ["v4"], optional = true } 45 | 46 | [target.'cfg(target_os = "redox")'.dependencies] 47 | libredox = "0.1" 48 | 49 | [features] 50 | default = ["installer"] 51 | installer = [ 52 | "arg_parser", 53 | "fatfs", 54 | "fscommon", 55 | "gpt", 56 | "pkgar", 57 | "pkgar-core", 58 | "pkgar-keys", 59 | "rand", 60 | "redox-pkg", 61 | "redox_syscall", 62 | "redoxfs", 63 | "rust-argon2", 64 | "termion", 65 | "uuid", 66 | ] 67 | 68 | [patch.crates-io] 69 | # https://github.com/briansmith/ring/issues/1999 70 | ring = { git = "https://gitlab.redox-os.org/redox-os/ring.git", branch = "redox-0.17.8" } 71 | -------------------------------------------------------------------------------- /src/config/general.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone, Debug, Default, Deserialize, Serialize)] 2 | pub struct GeneralConfig { 3 | /// Specify a path where cookbook exists, all packages will be installed locally 4 | pub cookbook: Option, 5 | /// Allow prompts for missing information such as user password, true by default 6 | pub prompt: Option, 7 | /// Allow config to specify cookbook recipe or binary package as default 8 | /// note: Not read by installer anymore, exists only for legacy reasons 9 | pub repo_binary: Option, 10 | /// Total filesystem size in MB 11 | pub filesystem_size: Option, 12 | /// EFI partition size in MB, default to 2MB 13 | pub efi_partition_size: Option, 14 | /// Skip disk partitioning, assume whole disk is a partition 15 | pub skip_partitions: Option, 16 | /// Set a plain text password to encrypt the disk, or empty string to prompt 17 | pub encrypt_disk: Option, 18 | /// Use live disk for bootloader config, default is false 19 | pub live_disk: Option, 20 | /// If set, write bootloader disk into this path 21 | pub write_bootloader: Option, 22 | /// Use AR to write files instead of FUSE-based mount 23 | /// (bypasses FUSE, but slower and requires namespaced context such as "podman unshare") 24 | pub no_mount: Option, 25 | } 26 | 27 | impl GeneralConfig { 28 | /// Merge two config, "other" is more dominant 29 | pub(super) fn merge(&mut self, other: GeneralConfig) { 30 | if let Some(cookbook) = other.cookbook { 31 | self.cookbook = Some(cookbook); 32 | } 33 | self.prompt = other.prompt.or(self.prompt); 34 | self.repo_binary = other.repo_binary.or(self.repo_binary); 35 | self.filesystem_size = other.filesystem_size.or(self.filesystem_size); 36 | self.efi_partition_size = other.efi_partition_size.or(self.efi_partition_size); 37 | self.skip_partitions = other.skip_partitions.or(self.skip_partitions); 38 | if let Some(encrypt_disk) = other.encrypt_disk { 39 | self.encrypt_disk = Some(encrypt_disk); 40 | } 41 | self.live_disk = other.live_disk.or(self.live_disk); 42 | if let Some(write_bootloader) = other.write_bootloader { 43 | self.write_bootloader = Some(write_bootloader); 44 | } 45 | self.no_mount = other.no_mount.or(self.no_mount); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/config/file_impl.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use libc::{gid_t, uid_t}; 3 | 4 | use std::ffi::{CString, OsStr}; 5 | use std::fs::{self, File}; 6 | use std::io::{Error, Write}; 7 | use std::os::unix::ffi::OsStrExt; 8 | use std::os::unix::fs::{symlink, PermissionsExt}; 9 | use std::path::Path; 10 | 11 | fn chown>(path: P, uid: uid_t, gid: gid_t, recursive: bool) -> Result<()> { 12 | let path = path.as_ref(); 13 | 14 | let c_path = CString::new(path.as_os_str().as_bytes()).unwrap(); 15 | if unsafe { libc::chown(c_path.as_ptr(), uid, gid) } != 0 { 16 | return Err(Error::last_os_error().into()); 17 | } 18 | 19 | if recursive && path.is_dir() { 20 | for entry_res in fs::read_dir(path)? { 21 | let entry = entry_res?; 22 | chown(entry.path(), uid, gid, recursive)?; 23 | } 24 | } 25 | 26 | Ok(()) 27 | } 28 | 29 | // TODO: Rewrite impls 30 | impl crate::FileConfig { 31 | pub(crate) fn create>(&self, prefix: P) -> Result<()> { 32 | let path = self.path.trim_start_matches('/'); 33 | let target_file = prefix.as_ref().join(path); 34 | 35 | if self.directory { 36 | println!("Create directory {}", target_file.display()); 37 | fs::create_dir_all(&target_file)?; 38 | self.apply_perms(&target_file)?; 39 | return Ok(()); 40 | } else if let Some(parent) = target_file.parent() { 41 | println!("Create file parent {}", parent.display()); 42 | fs::create_dir_all(parent)?; 43 | } 44 | 45 | if self.symlink { 46 | println!("Create symlink {}", target_file.display()); 47 | symlink(&OsStr::new(&self.data), &target_file)?; 48 | Ok(()) 49 | } else { 50 | println!("Create file {}", target_file.display()); 51 | let mut file = File::create(&target_file)?; 52 | file.write_all(self.data.as_bytes())?; 53 | 54 | self.apply_perms(target_file) 55 | } 56 | } 57 | 58 | fn apply_perms>(&self, target: P) -> Result<()> { 59 | let path = target.as_ref(); 60 | let mode = self 61 | .mode 62 | .unwrap_or_else(|| if self.directory { 0o0755 } else { 0o0644 }); 63 | let uid = self.uid.unwrap_or(!0); 64 | let gid = self.gid.unwrap_or(!0); 65 | 66 | // chmod 67 | fs::set_permissions(path, fs::Permissions::from_mode(mode))?; 68 | 69 | // chown 70 | chown(path, uid, gid, self.recursive_chown) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/config/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeMap; 2 | use std::fs; 3 | use std::mem; 4 | use std::path::{Path, PathBuf}; 5 | 6 | use anyhow::bail; 7 | use anyhow::Result; 8 | 9 | pub mod file; 10 | #[cfg(feature = "installer")] 11 | pub mod file_impl; 12 | pub mod general; 13 | pub mod package; 14 | pub mod user; 15 | 16 | #[derive(Clone, Debug, Default, Deserialize, Serialize)] 17 | pub struct Config { 18 | #[serde(default)] 19 | pub include: Vec, 20 | #[serde(default)] 21 | pub general: general::GeneralConfig, 22 | #[serde(default)] 23 | pub packages: BTreeMap, 24 | #[serde(default)] 25 | pub files: Vec, 26 | #[serde(default)] 27 | pub users: BTreeMap, 28 | #[serde(default)] 29 | pub groups: BTreeMap, 30 | } 31 | 32 | impl Config { 33 | pub fn from_file(path: &Path) -> Result { 34 | let mut config: Config = match fs::read_to_string(&path) { 35 | Ok(config_data) => match toml::from_str(&config_data) { 36 | Ok(config) => config, 37 | Err(err) => { 38 | bail!("{}: failed to decode: {}", path.display(), err); 39 | } 40 | }, 41 | Err(err) => { 42 | bail!("{}: failed to read: {}", path.display(), err); 43 | } 44 | }; 45 | 46 | let config_dir = path.parent().unwrap(); 47 | 48 | let mut configs = mem::take(&mut config.include) 49 | .into_iter() 50 | .map(|path| Config::from_file(&config_dir.join(path))) 51 | .collect::>>()?; 52 | configs.push(config); // Put ourself last to ensure that it overwrites anything else. 53 | 54 | config = configs.remove(0); 55 | 56 | for other_config in configs { 57 | config.merge(other_config); 58 | } 59 | 60 | Ok(config) 61 | } 62 | 63 | pub fn merge(&mut self, other: Config) { 64 | assert!(self.include.is_empty()); 65 | assert!(other.include.is_empty()); 66 | 67 | let Config { 68 | include: _, 69 | general: other_general, 70 | packages: other_packages, 71 | files: other_files, 72 | users: other_users, 73 | groups: other_groups, 74 | } = other; 75 | 76 | self.general.merge(other_general); 77 | 78 | for (package, package_config) in other_packages { 79 | self.packages.insert(package, package_config); 80 | } 81 | 82 | self.files.extend(other_files); 83 | 84 | for (user, user_config) in other_users { 85 | self.users.insert(user, user_config); 86 | } 87 | 88 | for (group, group_config) in other_groups { 89 | self.groups.insert(group, group_config); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /config/default.toml: -------------------------------------------------------------------------------- 1 | # This is the default configuration file 2 | 3 | # General settings 4 | [general] 5 | # Do not prompt if settings are not defined 6 | prompt = false 7 | 8 | # Package settings 9 | [packages] 10 | #acid = {} 11 | #autoconf = {} 12 | #automake = {} 13 | #bash = {} 14 | #binutils = {} 15 | #ca-certificates = {} 16 | #cargo = {} 17 | #contain = {} 18 | coreutils = {} 19 | #curl = {} 20 | #dash = {} 21 | #diffutils = {} 22 | drivers = {} 23 | extrautils = {} 24 | findutils = {} 25 | #games = {} 26 | #gawk = {} 27 | #gcc = {} 28 | #git = {} 29 | #gnu-binutils = {} 30 | #gnu-make = {} 31 | #installer = {} 32 | ion = {} 33 | #lua = {} 34 | #nasm = {} 35 | netstack = {} 36 | netutils = {} 37 | #newlib = {} 38 | #openssl = {} 39 | orbdata = {} 40 | orbital = {} 41 | orbterm = {} 42 | orbutils = {} 43 | pastel = {} 44 | #patch = {} 45 | #pixelcannon = {} 46 | pkgutils = {} 47 | ptyd = {} 48 | #python = {} 49 | randd = {} 50 | #redoxfs = {} 51 | #rust = {} 52 | #rustual-boy = {} 53 | #sed = {} 54 | smith = {} 55 | sodium = {} 56 | userutils = {} 57 | uutils = {} 58 | #xz = {} 59 | 60 | # User settings 61 | [users.root] 62 | password = "password" 63 | uid = 0 64 | gid = 0 65 | name = "root" 66 | home = "/root" 67 | 68 | [users.user] 69 | # Password is unset 70 | password = "" 71 | 72 | [groups.sudo] 73 | gid = 1 74 | members = ["user"] 75 | 76 | [[files]] 77 | path = "/etc/init.d/00_base" 78 | data = """ 79 | pcid /etc/pcid/filesystem.toml 80 | randd 81 | ptyd 82 | """ 83 | 84 | [[files]] 85 | path = "/etc/init.d/10_net" 86 | data = """ 87 | ethernetd 88 | ipd 89 | icmpd 90 | tcpd 91 | udpd 92 | dhcpd -b 93 | """ 94 | 95 | [[files]] 96 | path = "/etc/init.d/20_orbital" 97 | data = """ 98 | orbital orblogin launcher 99 | """ 100 | 101 | [[files]] 102 | path = "/etc/init.d/30_console" 103 | data = """ 104 | getty display/vesa:2 105 | getty debug: -J 106 | """ 107 | 108 | [[files]] 109 | path = "/etc/net/dns" 110 | data = """ 111 | 208.67.222.222 112 | """ 113 | 114 | [[files]] 115 | path = "/etc/net/ip" 116 | data = """ 117 | 10.0.2.15 118 | """ 119 | 120 | [[files]] 121 | path = "/etc/net/ip_router" 122 | data = """ 123 | 10.0.2.2 124 | """ 125 | 126 | [[files]] 127 | path = "/etc/net/ip_subnet" 128 | data = """ 129 | 255.255.255.0 130 | """ 131 | 132 | [[files]] 133 | path = "/etc/net/mac" 134 | data = """ 135 | 54-52-00-ab-cd-ef 136 | """ 137 | 138 | [[files]] 139 | path = "/etc/pkg.d/50_redox" 140 | data = "https://static.redox-os.org/pkg" 141 | 142 | [[files]] 143 | path = "/etc/hostname" 144 | data = "redox" 145 | 146 | [[files]] 147 | path = "/etc/issue" 148 | data = """ 149 | ########## Redox OS ########## 150 | # Login with the following: # 151 | # `user` # 152 | # `root`:`password` # 153 | ############################## 154 | 155 | """ 156 | 157 | [[files]] 158 | path = "/etc/motd" 159 | data = """ 160 | Welcome to Redox OS! 161 | 162 | """ 163 | 164 | [[files]] 165 | path = "/usr" 166 | data = "/" 167 | symlink = true 168 | 169 | [[files]] 170 | path = "/tmp" 171 | data = "" 172 | directory = true 173 | # 0o1777 174 | mode = 1023 175 | -------------------------------------------------------------------------------- /src/disk_wrapper.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | cmp, 3 | convert::TryInto, 4 | fs::{File, OpenOptions}, 5 | io::{Read, Result, Seek, SeekFrom, Write}, 6 | path::Path, 7 | }; 8 | 9 | #[derive(Debug)] 10 | pub struct DiskWrapper { 11 | disk: File, 12 | size: u64, 13 | block: Box<[u8]>, 14 | seek: u64, 15 | } 16 | 17 | enum Buffer<'a> { 18 | Read(&'a mut [u8]), 19 | Write(&'a [u8]), 20 | } 21 | 22 | impl DiskWrapper { 23 | pub fn open>(path: P) -> Result { 24 | let disk = OpenOptions::new().read(true).write(true).open(path)?; 25 | let metadata = disk.metadata()?; 26 | let size = metadata.len(); 27 | // TODO: get real block size: disk_metadata.blksize() works on disks but not image files 28 | let block_size = 512; 29 | let block = vec![0u8; block_size].into_boxed_slice(); 30 | Ok(Self { 31 | disk, 32 | size, 33 | block, 34 | seek: 0, 35 | }) 36 | } 37 | 38 | pub fn block_size(&self) -> usize { 39 | self.block.len() 40 | } 41 | 42 | pub fn size(&self) -> u64 { 43 | self.size 44 | } 45 | 46 | fn io<'a>(&mut self, buf: &mut Buffer<'a>) -> Result { 47 | let buf_len = match buf { 48 | Buffer::Read(read) => read.len(), 49 | Buffer::Write(write) => write.len(), 50 | }; 51 | let block_len: u64 = self.block.len().try_into().unwrap(); 52 | 53 | // Do aligned I/O quickly 54 | if self.seek % block_len == 0 && buf_len as u64 % block_len == 0 { 55 | self.disk.seek(SeekFrom::Start(self.seek))?; 56 | match buf { 57 | Buffer::Read(read) => self.disk.read_exact(read)?, 58 | Buffer::Write(write) => self.disk.write_all(write)?, 59 | } 60 | self.seek = self.seek.checked_add(buf_len.try_into().unwrap()).unwrap(); 61 | return Ok(buf_len); 62 | } 63 | 64 | let mut i = 0; 65 | while i < buf_len { 66 | let block = self.seek / block_len; 67 | let offset: usize = (self.seek % block_len).try_into().unwrap(); 68 | let remaining = buf_len.checked_sub(i).unwrap(); 69 | let len = cmp::min(remaining, self.block.len().checked_sub(offset).unwrap()); 70 | 71 | self.disk 72 | .seek(SeekFrom::Start(block.checked_mul(block_len).unwrap()))?; 73 | self.disk.read_exact(&mut self.block)?; 74 | 75 | match buf { 76 | Buffer::Read(read) => { 77 | read[i..i.checked_add(len).unwrap()] 78 | .copy_from_slice(&self.block[offset..offset.checked_add(len).unwrap()]); 79 | } 80 | Buffer::Write(write) => { 81 | self.block[offset..offset.checked_add(len).unwrap()] 82 | .copy_from_slice(&write[i..i.checked_add(len).unwrap()]); 83 | 84 | self.disk 85 | .seek(SeekFrom::Start(block.checked_mul(block_len).unwrap()))?; 86 | self.disk.write_all(&mut self.block)?; 87 | } 88 | } 89 | 90 | i = i.checked_add(len).unwrap(); 91 | self.seek = self.seek.checked_add(len.try_into().unwrap()).unwrap(); 92 | } 93 | 94 | Ok(i) 95 | } 96 | } 97 | 98 | impl Read for DiskWrapper { 99 | fn read(&mut self, buf: &mut [u8]) -> Result { 100 | self.io(&mut Buffer::Read(buf)) 101 | } 102 | } 103 | 104 | impl Seek for DiskWrapper { 105 | fn seek(&mut self, pos: SeekFrom) -> Result { 106 | let current: i64 = self.seek.try_into().unwrap(); 107 | let end: i64 = self.size.try_into().unwrap(); 108 | self.seek = match pos { 109 | SeekFrom::Start(offset) => cmp::min(self.size, offset), 110 | SeekFrom::End(offset) => cmp::max(0, cmp::min(end, end.wrapping_add(offset))) as u64, 111 | SeekFrom::Current(offset) => { 112 | cmp::max(0, cmp::min(end, current.wrapping_add(offset))) as u64 113 | } 114 | }; 115 | Ok(self.seek) 116 | } 117 | } 118 | 119 | impl Write for DiskWrapper { 120 | fn write(&mut self, buf: &[u8]) -> Result { 121 | self.io(&mut Buffer::Write(buf)) 122 | } 123 | 124 | fn flush(&mut self) -> Result<()> { 125 | self.disk.flush() 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/bin/installer.rs: -------------------------------------------------------------------------------- 1 | extern crate arg_parser; 2 | extern crate redox_installer; 3 | extern crate serde; 4 | extern crate toml; 5 | 6 | use std::path::Path; 7 | use std::{env, fs, process}; 8 | 9 | use arg_parser::ArgParser; 10 | 11 | use redox_installer::{Config, PackageConfig}; 12 | 13 | fn main() { 14 | let mut parser = ArgParser::new(4) 15 | .add_opt("b", "cookbook") 16 | .add_opt("c", "config") 17 | .add_opt("o", "output-config") 18 | .add_opt("", "write-bootloader") 19 | .add_flag(&["filesystem-size"]) 20 | .add_flag(&["r", "repo-binary"]) 21 | .add_flag(&["l", "list-packages"]) 22 | .add_flag(&["live"]) 23 | .add_flag(&["no-mount"]); 24 | parser.parse(env::args()); 25 | 26 | // Use pre-built binaries for packages as the default. 27 | // If not set on the command line or the filesystem config, then build packages from source. 28 | let repo_binary = parser.found("repo-binary"); 29 | 30 | let mut config = if let Some(path) = parser.get_opt("config") { 31 | match Config::from_file(Path::new(&path)) { 32 | Ok(config) => config, 33 | Err(err) => { 34 | eprintln!("installer: {err}"); 35 | process::exit(1); 36 | } 37 | } 38 | } else { 39 | redox_installer::Config::default() 40 | }; 41 | 42 | // Get toml of merged config 43 | let merged_toml = toml::to_string_pretty(&config).unwrap(); 44 | 45 | // Just output merged config and exit 46 | if let Some(path) = parser.get_opt("output-config") { 47 | fs::write(path, merged_toml).unwrap(); 48 | return; 49 | } 50 | 51 | // Add filesystem.toml to config 52 | config.files.push(redox_installer::FileConfig { 53 | path: "filesystem.toml".to_string(), 54 | data: merged_toml, 55 | ..Default::default() 56 | }); 57 | 58 | // Add command line flags to config, command line takes priority 59 | if repo_binary { 60 | config.general.repo_binary = Some(true); 61 | } 62 | 63 | if parser.found("filesystem-size") { 64 | println!("{}", config.general.filesystem_size.unwrap_or(0)); 65 | } else if parser.found("list-packages") { 66 | // List the packages that should be fetched or built by the cookbook 67 | for (packagename, package) in &config.packages { 68 | match package { 69 | PackageConfig::Build(rule) if rule == "ignore" => { 70 | // skip this package 71 | } 72 | _ => { 73 | println!("{}", packagename); 74 | } 75 | } 76 | } 77 | } else { 78 | let cookbook = if let Some(path) = parser.get_opt("cookbook") { 79 | if !Path::new(&path).is_dir() { 80 | eprintln!("installer: {}: cookbook not found", path); 81 | process::exit(1); 82 | } 83 | 84 | // Add cookbook key to config 85 | let key_path = Path::new(&path).join("build/id_ed25519.pub.toml"); 86 | match fs::read_to_string(&key_path) { 87 | Ok(data) => { 88 | config.files.push(redox_installer::FileConfig { 89 | path: "pkg/id_ed25519.pub.toml".to_string(), 90 | data, 91 | ..Default::default() 92 | }); 93 | Some(path) 94 | } 95 | Err(err) => { 96 | // if there are no recipes coming from the cookbook, this is not a fatal error 97 | if config 98 | .packages 99 | .clone() 100 | .into_iter() 101 | .any(|(_packagename, package)| match package { 102 | PackageConfig::Empty => false, 103 | PackageConfig::Spec { 104 | version: None, 105 | git: None, 106 | path: None, 107 | } => false, 108 | _ => true, 109 | }) 110 | { 111 | eprintln!( 112 | "installer: {}: failed to read cookbook key: {}", 113 | key_path.display(), 114 | err 115 | ); 116 | process::exit(1); 117 | } else { 118 | eprintln!( 119 | "installer: {}: (non-fatal) missing cookbook key: {}", 120 | key_path.display(), 121 | err 122 | ); 123 | None 124 | } 125 | } 126 | } 127 | } else { 128 | None 129 | }; 130 | 131 | if cookbook.is_some() { 132 | config.general.cookbook = cookbook; 133 | } 134 | if parser.found("live") { 135 | config.general.live_disk = Some(true); 136 | } 137 | if parser.found("no-mount") { 138 | config.general.no_mount = Some(true); 139 | } 140 | let write_bootloader = parser.get_opt("write-bootloader"); 141 | if write_bootloader.is_some() { 142 | config.general.write_bootloader = write_bootloader; 143 | } 144 | 145 | if let Some(path) = parser.args.first() { 146 | if let Err(err) = redox_installer::install(config, path) { 147 | eprintln!("installer: failed to install: {}", err); 148 | process::exit(1); 149 | } 150 | } else { 151 | eprintln!("installer: output or list-packages not found"); 152 | process::exit(1); 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /res/test.toml: -------------------------------------------------------------------------------- 1 | # Automatically generated by update.sh 2 | 3 | include = [] 4 | 5 | [general] 6 | prompt = false 7 | filesystem_size = 256 8 | 9 | [packages.base] 10 | 11 | [packages.base-initfs] 12 | 13 | [packages.bootloader] 14 | 15 | [packages.ca-certificates] 16 | 17 | [packages.coreutils] 18 | 19 | [packages.extrautils] 20 | 21 | [packages.findutils] 22 | 23 | [packages.ion] 24 | 25 | [packages.kernel] 26 | 27 | [packages.kibi] 28 | 29 | [packages.libgcc] 30 | 31 | [packages.libstdcxx] 32 | 33 | [packages.netdb] 34 | 35 | [packages.netutils] 36 | 37 | [packages.pkgutils] 38 | 39 | [packages.relibc] 40 | 41 | [packages.userutils] 42 | 43 | [packages.uutils] 44 | 45 | [[files]] 46 | path = "/usr/lib/init.d/00_base" 47 | data = """ 48 | # clear and recreate tmpdir with 0o1777 permission 49 | rm -rf /tmp 50 | mkdir -m a=rwxt /tmp 51 | 52 | ipcd 53 | ptyd 54 | nowait sudo --daemon 55 | """ 56 | symlink = false 57 | directory = false 58 | recursive_chown = false 59 | postinstall = false 60 | 61 | [[files]] 62 | path = "/usr/lib/init.d/00_drivers" 63 | data = """ 64 | pcid-spawner /etc/pcid.d/ 65 | """ 66 | symlink = false 67 | directory = false 68 | recursive_chown = false 69 | postinstall = false 70 | 71 | [[files]] 72 | path = "/etc/hostname" 73 | data = "redox" 74 | symlink = false 75 | directory = false 76 | recursive_chown = false 77 | postinstall = false 78 | 79 | [[files]] 80 | path = "/usr/lib/os-release" 81 | data = """ 82 | PRETTY_NAME="Redox OS 0.9.0" 83 | NAME="Redox OS" 84 | VERSION_ID="0.9.0" 85 | VERSION="0.9.0" 86 | ID="redox-os" 87 | 88 | HOME_URL="https://redox-os.org/" 89 | DOCUMENTATION_URL="https://redox-os.org/docs/" 90 | SUPPORT_URL="https://redox-os.org/community/" 91 | """ 92 | symlink = false 93 | directory = false 94 | recursive_chown = false 95 | postinstall = false 96 | 97 | [[files]] 98 | path = "/etc/os-release" 99 | data = "../usr/lib/os-release" 100 | symlink = true 101 | directory = false 102 | recursive_chown = false 103 | postinstall = false 104 | 105 | [[files]] 106 | path = "/etc/pkg.d/50_redox" 107 | data = "https://static.redox-os.org/pkg" 108 | symlink = false 109 | directory = false 110 | recursive_chown = false 111 | postinstall = false 112 | 113 | [[files]] 114 | path = "/usr" 115 | data = "" 116 | symlink = false 117 | directory = true 118 | mode = 493 119 | recursive_chown = false 120 | postinstall = false 121 | 122 | [[files]] 123 | path = "/usr/bin" 124 | data = "" 125 | symlink = false 126 | directory = true 127 | mode = 493 128 | recursive_chown = false 129 | postinstall = false 130 | 131 | [[files]] 132 | path = "/bin" 133 | data = "usr/bin" 134 | symlink = true 135 | directory = false 136 | recursive_chown = false 137 | postinstall = false 138 | 139 | [[files]] 140 | path = "/usr/include" 141 | data = "" 142 | symlink = false 143 | directory = true 144 | mode = 493 145 | recursive_chown = false 146 | postinstall = false 147 | 148 | [[files]] 149 | path = "/include" 150 | data = "usr/include" 151 | symlink = true 152 | directory = false 153 | recursive_chown = false 154 | postinstall = false 155 | 156 | [[files]] 157 | path = "/usr/lib" 158 | data = "" 159 | symlink = false 160 | directory = true 161 | mode = 493 162 | recursive_chown = false 163 | postinstall = false 164 | 165 | [[files]] 166 | path = "/lib" 167 | data = "usr/lib" 168 | symlink = true 169 | directory = false 170 | recursive_chown = false 171 | postinstall = false 172 | 173 | [[files]] 174 | path = "/usr/libexec" 175 | data = "" 176 | symlink = false 177 | directory = true 178 | mode = 493 179 | recursive_chown = false 180 | postinstall = false 181 | 182 | [[files]] 183 | path = "/usr/share" 184 | data = "" 185 | symlink = false 186 | directory = true 187 | mode = 493 188 | recursive_chown = false 189 | postinstall = false 190 | 191 | [[files]] 192 | path = "/share" 193 | data = "usr/share" 194 | symlink = true 195 | directory = false 196 | recursive_chown = false 197 | postinstall = false 198 | 199 | [[files]] 200 | path = "/usr/share/fonts" 201 | data = "../../ui/fonts" 202 | symlink = true 203 | directory = false 204 | recursive_chown = false 205 | postinstall = false 206 | 207 | [[files]] 208 | path = "/var" 209 | data = "" 210 | symlink = false 211 | directory = true 212 | mode = 493 213 | recursive_chown = false 214 | postinstall = false 215 | 216 | [[files]] 217 | path = "/var/cache" 218 | data = "" 219 | symlink = false 220 | directory = true 221 | mode = 493 222 | recursive_chown = false 223 | postinstall = false 224 | 225 | [[files]] 226 | path = "/var/lib" 227 | data = "" 228 | symlink = false 229 | directory = true 230 | mode = 493 231 | recursive_chown = false 232 | postinstall = false 233 | 234 | [[files]] 235 | path = "/var/lock" 236 | data = "" 237 | symlink = false 238 | directory = true 239 | mode = 1023 240 | recursive_chown = false 241 | postinstall = false 242 | 243 | [[files]] 244 | path = "/var/log" 245 | data = "" 246 | symlink = false 247 | directory = true 248 | mode = 493 249 | recursive_chown = false 250 | postinstall = false 251 | 252 | [[files]] 253 | path = "/var/run" 254 | data = "" 255 | symlink = false 256 | directory = true 257 | mode = 493 258 | recursive_chown = false 259 | postinstall = false 260 | 261 | [[files]] 262 | path = "/var/tmp" 263 | data = "" 264 | symlink = false 265 | directory = true 266 | mode = 1023 267 | recursive_chown = false 268 | postinstall = false 269 | 270 | [[files]] 271 | path = "/dev/null" 272 | data = "/scheme/null" 273 | symlink = true 274 | directory = false 275 | recursive_chown = false 276 | postinstall = false 277 | 278 | [[files]] 279 | path = "/dev/random" 280 | data = "/scheme/rand" 281 | symlink = true 282 | directory = false 283 | recursive_chown = false 284 | postinstall = false 285 | 286 | [[files]] 287 | path = "/dev/urandom" 288 | data = "/scheme/rand" 289 | symlink = true 290 | directory = false 291 | recursive_chown = false 292 | postinstall = false 293 | 294 | [[files]] 295 | path = "/dev/zero" 296 | data = "/scheme/zero" 297 | symlink = true 298 | directory = false 299 | recursive_chown = false 300 | postinstall = false 301 | 302 | [[files]] 303 | path = "/dev/tty" 304 | data = "libc:tty" 305 | symlink = true 306 | directory = false 307 | recursive_chown = false 308 | postinstall = false 309 | 310 | [[files]] 311 | path = "/dev/stdin" 312 | data = "libc:stdin" 313 | symlink = true 314 | directory = false 315 | recursive_chown = false 316 | postinstall = false 317 | 318 | [[files]] 319 | path = "/dev/stdout" 320 | data = "libc:stdout" 321 | symlink = true 322 | directory = false 323 | recursive_chown = false 324 | postinstall = false 325 | 326 | [[files]] 327 | path = "/dev/stderr" 328 | data = "libc:stderr" 329 | symlink = true 330 | directory = false 331 | recursive_chown = false 332 | postinstall = false 333 | 334 | [[files]] 335 | path = "/usr/lib/init.d/10_net" 336 | data = """ 337 | smolnetd 338 | nowait dhcpd 339 | """ 340 | symlink = false 341 | directory = false 342 | recursive_chown = false 343 | postinstall = false 344 | 345 | [[files]] 346 | path = "/etc/net/dns" 347 | data = """ 348 | 9.9.9.9 349 | """ 350 | symlink = false 351 | directory = false 352 | recursive_chown = false 353 | postinstall = false 354 | 355 | [[files]] 356 | path = "/etc/net/ip" 357 | data = """ 358 | 10.0.2.15 359 | """ 360 | symlink = false 361 | directory = false 362 | recursive_chown = false 363 | postinstall = false 364 | 365 | [[files]] 366 | path = "/etc/net/ip_router" 367 | data = """ 368 | 10.0.2.2 369 | """ 370 | symlink = false 371 | directory = false 372 | recursive_chown = false 373 | postinstall = false 374 | 375 | [[files]] 376 | path = "/etc/net/ip_subnet" 377 | data = """ 378 | 255.255.255.0 379 | """ 380 | symlink = false 381 | directory = false 382 | recursive_chown = false 383 | postinstall = false 384 | 385 | [[files]] 386 | path = "/usr/lib/init.d/30_console" 387 | data = """ 388 | inputd -A 2 389 | nowait getty 2 390 | nowait getty /scheme/debug -J 391 | """ 392 | symlink = false 393 | directory = false 394 | recursive_chown = false 395 | postinstall = false 396 | 397 | [users.root] 398 | password = "password" 399 | uid = 0 400 | gid = 0 401 | name = "root" 402 | home = "/root" 403 | shell = "/usr/bin/ion" 404 | 405 | [users.user] 406 | password = "" 407 | shell = "/usr/bin/ion" 408 | 409 | [groups.sudo] 410 | gid = 1 411 | members = ["user"] 412 | -------------------------------------------------------------------------------- /src/bin/installer_tui.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, bail, Result}; 2 | use pkgar::{ext::EntryExt, PackageHead}; 3 | use pkgar_core::PackageSrc; 4 | use pkgar_keys::PublicKeyFile; 5 | use redox_installer::{try_fast_install, with_redoxfs_mount, with_whole_disk, Config, DiskOption}; 6 | use std::{ 7 | ffi::OsStr, 8 | fs, 9 | io::{self, Read, Write}, 10 | os::unix::fs::{symlink, MetadataExt, OpenOptionsExt}, 11 | path::{Path, PathBuf}, 12 | process, 13 | }; 14 | use termion::input::TermRead; 15 | 16 | #[cfg(not(target_os = "redox"))] 17 | fn disk_paths(_paths: &mut Vec<(PathBuf, u64)>) {} 18 | 19 | #[cfg(target_os = "redox")] 20 | fn disk_paths(paths: &mut Vec<(PathBuf, u64)>) { 21 | let mut schemes = Vec::new(); 22 | match fs::read_dir("/scheme") { 23 | Ok(entries) => { 24 | for entry_res in entries { 25 | if let Ok(entry) = entry_res { 26 | if let Ok(file_name) = entry.file_name().into_string() { 27 | if file_name.starts_with("disk") { 28 | schemes.push(entry.path()); 29 | } 30 | } 31 | } 32 | } 33 | } 34 | Err(err) => { 35 | eprintln!("installer_tui: failed to list schemes: {}", err); 36 | } 37 | } 38 | 39 | for scheme in schemes { 40 | if scheme.is_dir() { 41 | match fs::read_dir(&scheme) { 42 | Ok(entries) => { 43 | for entry_res in entries { 44 | if let Ok(entry) = entry_res { 45 | if let Ok(file_name) = entry.file_name().into_string() { 46 | if file_name.contains('p') { 47 | // Skip partitions 48 | continue; 49 | } 50 | 51 | if let Ok(metadata) = entry.metadata() { 52 | let size = metadata.len(); 53 | if size > 0 { 54 | paths.push((entry.path(), size)); 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | Err(err) => { 62 | eprintln!( 63 | "installer_tui: failed to list '{}': {}", 64 | scheme.display(), 65 | err 66 | ); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | 73 | const KIB: u64 = 1024; 74 | const MIB: u64 = 1024 * KIB; 75 | const GIB: u64 = 1024 * MIB; 76 | const TIB: u64 = 1024 * GIB; 77 | 78 | fn format_size(size: u64) -> String { 79 | if size >= 4 * TIB { 80 | format!("{:.1} TiB", size as f64 / TIB as f64) 81 | } else if size >= GIB { 82 | format!("{:.1} GiB", size as f64 / GIB as f64) 83 | } else if size >= MIB { 84 | format!("{:.1} MiB", size as f64 / MIB as f64) 85 | } else if size >= KIB { 86 | format!("{:.1} KiB", size as f64 / KIB as f64) 87 | } else { 88 | format!("{} B", size) 89 | } 90 | } 91 | 92 | fn copy_file(src: &Path, dest: &Path, buf: &mut [u8]) -> Result<()> { 93 | if let Some(parent) = dest.parent() { 94 | // Parent may be a symlink 95 | if !parent.is_symlink() { 96 | match fs::create_dir_all(&parent) { 97 | Ok(()) => (), 98 | Err(err) => { 99 | bail!("failed to create directory {}: {}", parent.display(), err); 100 | } 101 | } 102 | } 103 | } 104 | 105 | let metadata = match fs::symlink_metadata(&src) { 106 | Ok(ok) => ok, 107 | Err(err) => { 108 | bail!("failed to read metadata of {}: {}", src.display(), err); 109 | } 110 | }; 111 | 112 | if metadata.file_type().is_symlink() { 113 | let real_src = match fs::read_link(&src) { 114 | Ok(ok) => ok, 115 | Err(err) => { 116 | bail!("failed to read link {}: {}", src.display(), err); 117 | } 118 | }; 119 | 120 | match symlink(&real_src, &dest) { 121 | Ok(()) => (), 122 | Err(err) => { 123 | bail!( 124 | "failed to copy link {} ({}) to {}: {}", 125 | src.display(), 126 | real_src.display(), 127 | dest.display(), 128 | err 129 | ); 130 | } 131 | } 132 | } else { 133 | let mut src_file = match fs::File::open(&src) { 134 | Ok(ok) => ok, 135 | Err(err) => { 136 | bail!("failed to open file {}: {}", src.display(), err); 137 | } 138 | }; 139 | 140 | let mut dest_file = match fs::OpenOptions::new() 141 | .write(true) 142 | .create_new(true) 143 | .mode(metadata.mode()) 144 | .open(&dest) 145 | { 146 | Ok(ok) => ok, 147 | Err(err) => { 148 | bail!("failed to create file {}: {}", dest.display(), err); 149 | } 150 | }; 151 | 152 | loop { 153 | let count = match src_file.read(buf) { 154 | Ok(ok) => ok, 155 | Err(err) => { 156 | bail!("failed to read file {}: {}", src.display(), err); 157 | } 158 | }; 159 | 160 | if count == 0 { 161 | break; 162 | } 163 | 164 | match dest_file.write_all(&buf[..count]) { 165 | Ok(()) => (), 166 | Err(err) => { 167 | bail!("failed to write file {}: {}", dest.display(), err); 168 | } 169 | } 170 | } 171 | } 172 | 173 | Ok(()) 174 | } 175 | 176 | fn package_files( 177 | root_path: &Path, 178 | config: &mut Config, 179 | files: &mut Vec, 180 | ) -> Result<(), anyhow::Error> { 181 | //TODO: Remove packages from config where all files are located (and have valid shasum?) 182 | config.packages.clear(); 183 | 184 | let pkey_path = "pkg/id_ed25519.pub.toml"; 185 | let pkey = PublicKeyFile::open(&root_path.join(pkey_path))?.pkey; 186 | files.push(pkey_path.to_string()); 187 | 188 | for item_res in fs::read_dir(&root_path.join("pkg"))? { 189 | let item = item_res?; 190 | let pkg_path = item.path(); 191 | if pkg_path.extension() == Some(OsStr::new("pkgar_head")) { 192 | let mut pkg = PackageHead::new(&pkg_path, &root_path, &pkey)?; 193 | for entry in pkg.read_entries()? { 194 | files.push(entry.check_path()?.to_str().unwrap().to_string()); 195 | } 196 | files.push( 197 | pkg_path 198 | .strip_prefix(root_path) 199 | .unwrap() 200 | .to_str() 201 | .unwrap() 202 | .to_string(), 203 | ); 204 | } 205 | } 206 | 207 | Ok(()) 208 | } 209 | 210 | fn choose_disk() -> PathBuf { 211 | let mut paths = Vec::new(); 212 | disk_paths(&mut paths); 213 | loop { 214 | for (i, (path, size)) in paths.iter().enumerate() { 215 | eprintln!( 216 | "\x1B[1m{}\x1B[0m: {}: {}", 217 | i + 1, 218 | path.display(), 219 | format_size(*size) 220 | ); 221 | } 222 | 223 | if paths.is_empty() { 224 | eprintln!("installer_tui: no drives found"); 225 | process::exit(1); 226 | } else { 227 | eprint!("Select a drive from 1 to {}: ", paths.len()); 228 | 229 | let mut line = String::new(); 230 | match io::stdin().read_line(&mut line) { 231 | Ok(0) => { 232 | eprintln!("installer_tui: failed to read line: end of input"); 233 | process::exit(1); 234 | } 235 | Ok(_) => (), 236 | Err(err) => { 237 | eprintln!("installer_tui: failed to read line: {}", err); 238 | process::exit(1); 239 | } 240 | } 241 | 242 | match line.trim().parse::() { 243 | Ok(i) => { 244 | if i >= 1 && i <= paths.len() { 245 | break paths[i - 1].0.clone(); 246 | } else { 247 | eprintln!("{} not from 1 to {}", i, paths.len()); 248 | } 249 | } 250 | Err(err) => { 251 | eprintln!("invalid input: {}", err); 252 | } 253 | } 254 | } 255 | } 256 | } 257 | 258 | fn choose_password() -> Option { 259 | eprint!("installer_tui: redoxfs password (empty for none): "); 260 | 261 | let password = io::stdin() 262 | .read_passwd(&mut io::stderr()) 263 | .unwrap() 264 | .unwrap_or(String::new()); 265 | 266 | eprintln!(); 267 | 268 | if password.is_empty() { 269 | return None; 270 | } 271 | 272 | Some(password) 273 | } 274 | 275 | fn main() { 276 | let root_path = Path::new("/"); 277 | 278 | let disk_path = choose_disk(); 279 | 280 | let password_opt = choose_password(); 281 | 282 | let instant = std::time::Instant::now(); 283 | 284 | let bootloader_bios = { 285 | let path = root_path.join("boot").join("bootloader.bios"); 286 | if path.exists() { 287 | match fs::read(&path) { 288 | Ok(ok) => ok, 289 | Err(err) => { 290 | eprintln!("installer_tui: {}: failed to read: {}", path.display(), err); 291 | process::exit(1); 292 | } 293 | } 294 | } else { 295 | Vec::new() 296 | } 297 | }; 298 | 299 | let bootloader_efi = { 300 | let path = root_path.join("boot").join("bootloader.efi"); 301 | if path.exists() { 302 | match fs::read(&path) { 303 | Ok(ok) => ok, 304 | Err(err) => { 305 | eprintln!("installer_tui: {}: failed to read: {}", path.display(), err); 306 | process::exit(1); 307 | } 308 | } 309 | } else { 310 | Vec::new() 311 | } 312 | }; 313 | 314 | let disk_option = DiskOption { 315 | bootloader_bios: &bootloader_bios, 316 | bootloader_efi: &bootloader_efi, 317 | password_opt: password_opt.as_ref().map(|x| x.as_bytes()), 318 | efi_partition_size: None, 319 | skip_partitions: false, // TODO? 320 | }; 321 | let res = with_whole_disk(&disk_path, &disk_option, |mut fs| { 322 | // Fast install method via filesystem clone 323 | let mut last_percent = 0; 324 | if try_fast_install(&mut fs, move |used, used_old| { 325 | let percent = (used * 100) / used_old; 326 | if percent != last_percent { 327 | eprint!( 328 | "\r{}%: {} MB/{} MB", 329 | percent, 330 | used / 1000 / 1000, 331 | used_old / 1000 / 1000 332 | ); 333 | last_percent = percent; 334 | } 335 | })? { 336 | eprintln!("\rfinished installing using fast mode"); 337 | return Ok(()); 338 | } 339 | 340 | // Slow install method via file copy 341 | with_redoxfs_mount(fs, None, |mount_path| { 342 | let mut config: Config = Config::from_file(&root_path.join("filesystem.toml"))?; 343 | 344 | // Copy filesystem.toml, which is not packaged 345 | let mut files = vec!["filesystem.toml".to_string()]; 346 | 347 | // Copy files from locally installed packages 348 | package_files(&root_path, &mut config, &mut files) 349 | // TODO: implement Error trait 350 | .map_err(|err| anyhow!("failed to read package files: {err}"))?; 351 | 352 | // Perform config install (after packages have been converted to files) 353 | eprintln!("configuring system"); 354 | let cookbook: Option<&'static str> = None; 355 | redox_installer::install_dir(config, mount_path, cookbook) 356 | .map_err(|err| io::Error::other(err))?; 357 | 358 | // Sort and remove duplicates 359 | files.sort(); 360 | files.dedup(); 361 | 362 | // Install files 363 | let mut buf = vec![0; 4 * MIB as usize]; 364 | for (i, name) in files.iter().enumerate() { 365 | eprintln!("copy {} [{}/{}]", name, i, files.len()); 366 | 367 | let src = root_path.join(name); 368 | let dest = mount_path.join(name); 369 | copy_file(&src, &dest, &mut buf)?; 370 | } 371 | 372 | eprintln!("finished installing, unmounting filesystem"); 373 | 374 | Ok(()) 375 | }) 376 | }); 377 | 378 | match res { 379 | Ok(()) => { 380 | eprintln!( 381 | "installer_tui: installed successfully in {:?}", 382 | instant.elapsed() 383 | ); 384 | process::exit(0); 385 | } 386 | Err(err) => { 387 | eprintln!("installer_tui: failed to install: {}", err); 388 | process::exit(1); 389 | } 390 | } 391 | } 392 | -------------------------------------------------------------------------------- /src/installer.rs: -------------------------------------------------------------------------------- 1 | #[cfg(target_os = "redox")] 2 | use anyhow::{anyhow, Context}; 3 | use anyhow::{bail, Result}; 4 | use pkg::Library; 5 | use rand::{rngs::OsRng, TryRngCore}; 6 | use redoxfs::{unmount_path, Disk, DiskIo, FileSystem, BLOCK_SIZE}; 7 | use termion::input::TermRead; 8 | 9 | use crate::config::file::FileConfig; 10 | use crate::config::package::PackageConfig; 11 | use crate::config::Config; 12 | use crate::disk_wrapper::DiskWrapper; 13 | 14 | use std::{ 15 | cell::RefCell, 16 | collections::BTreeMap, 17 | env, fs, 18 | io::{self, Seek, SeekFrom, Write}, 19 | path::{Path, PathBuf}, 20 | process, 21 | rc::Rc, 22 | sync::mpsc::channel, 23 | thread, 24 | time::{SystemTime, UNIX_EPOCH}, 25 | }; 26 | 27 | pub struct DiskOption<'a> { 28 | pub bootloader_bios: &'a [u8], 29 | pub bootloader_efi: &'a [u8], 30 | pub password_opt: Option<&'a [u8]>, 31 | pub efi_partition_size: Option, //MiB 32 | pub skip_partitions: bool, 33 | } 34 | 35 | fn get_target() -> String { 36 | env::var("TARGET").unwrap_or( 37 | option_env!("TARGET").map_or("x86_64-unknown-redox".to_string(), |x| x.to_string()), 38 | ) 39 | } 40 | 41 | /// Converts a password to a serialized argon2rs hash, understandable 42 | /// by redox_users. If the password is blank, the hash is blank. 43 | fn hash_password(password: &str) -> Result { 44 | if !password.is_empty() { 45 | let salt = format!("{:X}", OsRng.try_next_u64()?); 46 | let config = argon2::Config::default(); 47 | let hash = argon2::hash_encoded(password.as_bytes(), salt.as_bytes(), &config)?; 48 | Ok(hash) 49 | } else { 50 | Ok("".into()) 51 | } 52 | } 53 | 54 | fn syscall_error(err: syscall::Error) -> io::Error { 55 | io::Error::from_raw_os_error(err.errno) 56 | } 57 | 58 | /// Returns a password collected from the user (plaintext) 59 | fn prompt_password(prompt: &str, confirm_prompt: &str) -> Result { 60 | let stdin = io::stdin(); 61 | let mut stdin = stdin.lock(); 62 | let stdout = io::stdout(); 63 | let mut stdout = stdout.lock(); 64 | 65 | print!("{}", prompt); 66 | let password = stdin.read_passwd(&mut stdout)?; 67 | 68 | print!("\n{}", confirm_prompt); 69 | let confirm_password = stdin.read_passwd(&mut stdout)?; 70 | 71 | // Note: Actually comparing two Option values 72 | if confirm_password != password { 73 | bail!("passwords do not match"); 74 | } 75 | Ok(password.unwrap_or("".to_string())) 76 | } 77 | 78 | fn install_local_pkgar(cookbook: &str, target: &str, packagename: &str, dest: &Path) -> Result<()> { 79 | let head_path = get_head_path(packagename, dest); 80 | 81 | let public_path = format!("{cookbook}/build/id_ed25519.pub.toml",); 82 | let pkgar_path = format!("{cookbook}/repo/{target}/{packagename}.pkgar"); 83 | 84 | let pkginfo_path = format!("{cookbook}/repo/{target}/{packagename}.toml"); 85 | let pkginfo = pkg::Package::from_toml(&fs::read_to_string(pkginfo_path)?)?; 86 | 87 | if pkginfo.version != "" { 88 | pkgar::extract(&public_path, &pkgar_path, dest)?; 89 | pkgar::split(&public_path, &pkgar_path, head_path, Option::<&str>::None)?; 90 | } 91 | 92 | // Recursively install any runtime dependencies. 93 | for dep in pkginfo.depends.iter() { 94 | let depname = dep.as_str(); 95 | if !get_head_path(depname, dest).exists() { 96 | println!("Installing runtime dependency for {packagename} from local repo: {depname}"); 97 | install_local_pkgar(cookbook, target, depname, dest)?; 98 | } 99 | } 100 | 101 | Ok(()) 102 | } 103 | 104 | fn get_head_path(packagename: &str, dest: &Path) -> PathBuf { 105 | dest.join(format!("pkg/packages/{packagename}.pkgar_head")) 106 | } 107 | 108 | fn install_packages(config: &Config, dest: &Path, cookbook: Option<&str>) -> anyhow::Result<()> { 109 | let target = &get_target(); 110 | 111 | let callback = pkg::callback::IndicatifCallback::new(); 112 | 113 | let packages: Vec<&String> = config 114 | .packages 115 | .iter() 116 | .filter_map(|(packagename, package)| match package { 117 | PackageConfig::Build(rule) if rule == "ignore" => None, 118 | _ => Some(packagename), 119 | }) 120 | .collect(); 121 | 122 | if let Some(cookbook) = cookbook { 123 | let dest_pkg = dest.join("pkg/packages"); 124 | if !Path::new(&dest_pkg).is_dir() { 125 | fs::create_dir_all(&dest_pkg)?; 126 | } 127 | for packagename in packages { 128 | if !get_head_path(packagename, dest).exists() { 129 | println!("Installing package from local repo: {}", packagename); 130 | install_local_pkgar(cookbook, target, packagename, dest)?; 131 | } 132 | } 133 | } else { 134 | let mut library = Library::new(dest, target, Rc::new(RefCell::new(callback)))?; 135 | for packagename in packages { 136 | if !get_head_path(packagename, dest).exists() { 137 | println!("Installing package from remote: {packagename}"); 138 | library.install(vec![pkg::PackageName::new(packagename)?])?; 139 | } 140 | } 141 | library.apply()?; 142 | } 143 | 144 | Ok(()) 145 | } 146 | 147 | pub fn install_dir( 148 | config: Config, 149 | output_dir: impl AsRef, 150 | cookbook: Option<&str>, 151 | ) -> Result<()> { 152 | //let mut context = liner::Context::new(); 153 | 154 | macro_rules! prompt { 155 | ($dst:expr, $def:expr, $($arg:tt)*) => { 156 | if config.general.prompt.unwrap_or(true) { 157 | Err(io::Error::new( 158 | io::ErrorKind::Other, 159 | "prompt not currently supported", 160 | )) 161 | // match unwrap_or_prompt($dst, &mut context, &format!($($arg)*)) { 162 | // Ok(res) => if res.is_empty() { 163 | // Ok($def) 164 | // } else { 165 | // Ok(res) 166 | // }, 167 | // Err(err) => Err(err) 168 | // } 169 | } else { 170 | Ok($dst.unwrap_or($def)) 171 | } 172 | }; 173 | } 174 | 175 | let output_dir = output_dir.as_ref(); 176 | 177 | let output_dir = output_dir.to_owned(); 178 | 179 | for file in &config.files { 180 | if !file.postinstall { 181 | file.create(&output_dir)?; 182 | } 183 | } 184 | 185 | install_packages(&config, &output_dir, cookbook)?; 186 | 187 | for file in &config.files { 188 | if file.postinstall { 189 | file.create(&output_dir)?; 190 | } 191 | } 192 | 193 | let mut passwd = String::new(); 194 | let mut shadow = String::new(); 195 | let mut next_uid = 1000; 196 | let mut next_gid = 1000; 197 | 198 | let mut groups = vec![]; 199 | 200 | for (username, user) in config.users { 201 | // plaintext 202 | let password = if let Some(password) = user.password { 203 | password 204 | } else if config.general.prompt.unwrap_or(true) { 205 | prompt_password( 206 | &format!("{}: enter password: ", username), 207 | &format!("{}: confirm password: ", username), 208 | )? 209 | } else { 210 | String::new() 211 | }; 212 | 213 | let uid = user.uid.unwrap_or(next_uid); 214 | 215 | if uid >= next_uid { 216 | next_uid = uid + 1; 217 | } 218 | 219 | let gid = user.gid.unwrap_or(next_gid); 220 | 221 | if gid >= next_gid { 222 | next_gid = gid + 1; 223 | } 224 | 225 | let name = prompt!( 226 | user.name, 227 | username.clone(), 228 | "{}: name (GECOS) [{}]: ", 229 | username, 230 | username 231 | )?; 232 | let home = prompt!( 233 | user.home, 234 | format!("/home/{}", username), 235 | "{}: home [/home/{}]: ", 236 | username, 237 | username 238 | )?; 239 | let shell = prompt!( 240 | user.shell, 241 | "/bin/ion".to_string(), 242 | "{}: shell [/bin/ion]: ", 243 | username 244 | )?; 245 | 246 | println!("Adding user {username}:"); 247 | println!("\tPassword: {password}"); 248 | println!("\tUID: {uid}"); 249 | println!("\tGID: {gid}"); 250 | println!("\tName: {name}"); 251 | println!("\tHome: {home}"); 252 | println!("\tShell: {shell}"); 253 | 254 | FileConfig::new_directory(home.clone()) 255 | .with_recursive_mod(0o777, uid, gid) 256 | .create(&output_dir)?; 257 | 258 | if uid >= 1000 { 259 | // Create XDG user dirs 260 | //TODO: move to some autostart program? 261 | for xdg_folder in &[ 262 | "Desktop", 263 | "Documents", 264 | "Downloads", 265 | "Music", 266 | "Pictures", 267 | "Public", 268 | "Templates", 269 | "Videos", 270 | ".config", 271 | ".local", 272 | ".local/share", 273 | ".local/share/Trash", 274 | ".local/share/Trash/info", 275 | ] { 276 | FileConfig::new_directory(format!("{}/{}", home, xdg_folder)) 277 | .with_mod(0o0700, uid, gid) 278 | .create(&output_dir)?; 279 | } 280 | 281 | FileConfig::new_file( 282 | format!("{}/.config/user-dirs.dirs", home), 283 | r#"# Produced by redox installer 284 | XDG_DESKTOP_DIR="$HOME/Desktop" 285 | XDG_DOCUMENTS_DIR="$HOME/Documents" 286 | XDG_DOWNLOAD_DIR="$HOME/Downloads" 287 | XDG_MUSIC_DIR="$HOME/Music" 288 | XDG_PICTURES_DIR="$HOME/Pictures" 289 | XDG_PUBLICSHARE_DIR="$HOME/Public" 290 | XDG_TEMPLATES_DIR="$HOME/Templates" 291 | XDG_VIDEOS_DIR="$HOME/Videos" 292 | "# 293 | .to_string(), 294 | ) 295 | .with_mod(0o0600, uid, gid) 296 | .create(&output_dir)?; 297 | } 298 | 299 | let password = hash_password(&password)?; 300 | 301 | passwd.push_str(&format!("{username};{uid};{gid};{name};{home};{shell}\n",)); 302 | shadow.push_str(&format!("{username};{password}\n")); 303 | groups.push((username.clone(), gid, vec![username])); 304 | } 305 | 306 | for (group, group_config) in config.groups { 307 | // FIXME this assumes there is no overlap between auto-created groups for users 308 | // and explicitly specified groups. 309 | let gid = group_config.gid.unwrap_or(next_gid); 310 | 311 | if gid >= next_gid { 312 | next_gid = gid + 1; 313 | } 314 | 315 | groups.push((group, gid, group_config.members)); 316 | } 317 | 318 | if !passwd.is_empty() { 319 | FileConfig::new_file("/etc/passwd".to_string(), passwd).create(&output_dir)?; 320 | } 321 | 322 | if !shadow.is_empty() { 323 | FileConfig::new_file("/etc/shadow".to_string(), shadow) 324 | .with_mod(0o0600, 0, 0) 325 | .create(&output_dir)?; 326 | } 327 | 328 | if !groups.is_empty() { 329 | let mut groups_data = String::new(); 330 | 331 | for (name, gid, members) in groups { 332 | use std::fmt::Write; 333 | writeln!(groups_data, "{name};x;{gid};{}", members.join(","))?; 334 | 335 | println!("Adding group {name}:"); 336 | println!("\tGID: {gid}"); 337 | println!("\tMembers: {}", members.join(", ")); 338 | } 339 | 340 | FileConfig::new_file("/etc/group".to_string(), groups_data) 341 | .with_mod(0o0600, 0, 0) 342 | .create(&output_dir)?; 343 | } 344 | 345 | Ok(()) 346 | } 347 | 348 | pub fn with_redoxfs(disk: D, password_opt: Option<&[u8]>, callback: F) -> Result 349 | where 350 | D: Disk + Send + 'static, 351 | F: FnOnce(FileSystem) -> Result, 352 | { 353 | let ctime = SystemTime::now().duration_since(UNIX_EPOCH)?; 354 | let fs = FileSystem::create(disk, password_opt, ctime.as_secs(), ctime.subsec_nanos()) 355 | .map_err(syscall_error)?; 356 | callback(fs) 357 | } 358 | 359 | fn decide_mount_path(mount_path: Option<&Path>) -> PathBuf { 360 | let mount_path = mount_path.map(|p| p.to_path_buf()).unwrap_or_else(|| { 361 | PathBuf::from(if cfg!(target_os = "redox") { 362 | format!("file.redox_installer_{}", process::id()) 363 | } else { 364 | format!("/tmp/redox_installer_{}", process::id()) 365 | }) 366 | }); 367 | mount_path 368 | } 369 | 370 | pub fn with_redoxfs_mount( 371 | fs: FileSystem, 372 | mount_path: Option<&Path>, 373 | callback: F, 374 | ) -> Result 375 | where 376 | D: Disk + Send + 'static, 377 | F: FnOnce(&Path) -> Result, 378 | { 379 | let mount_path = decide_mount_path(mount_path); 380 | 381 | if cfg!(not(target_os = "redox")) && !mount_path.exists() { 382 | fs::create_dir(&mount_path)?; 383 | } 384 | 385 | let (tx, rx) = channel(); 386 | let join_handle = { 387 | let mount_path = mount_path.clone(); 388 | thread::spawn(move || { 389 | let res = redoxfs::mount(fs, &mount_path, |real_path| { 390 | tx.send(Ok(real_path.to_owned())).unwrap(); 391 | }); 392 | match res { 393 | Ok(()) => (), 394 | Err(err) => { 395 | tx.send(Err(err)).unwrap(); 396 | } 397 | }; 398 | }) 399 | }; 400 | 401 | let res = match rx.recv() { 402 | Ok(ok) => match ok { 403 | Ok(real_path) => callback(&real_path), 404 | Err(err) => return Err(err.into()), 405 | }, 406 | Err(_) => { 407 | return Err(io::Error::new( 408 | io::ErrorKind::NotConnected, 409 | "redoxfs thread did not send a result", 410 | ) 411 | .into()) 412 | } 413 | }; 414 | 415 | unmount_path(&mount_path.as_os_str().to_str().unwrap())?; 416 | 417 | join_handle.join().unwrap(); 418 | 419 | if cfg!(not(target_os = "redox")) { 420 | fs::remove_dir_all(&mount_path)?; 421 | } 422 | 423 | res 424 | } 425 | 426 | pub fn with_redoxfs_ar( 427 | mut fs: FileSystem, 428 | mount_path: Option<&Path>, 429 | callback: F, 430 | ) -> Result 431 | where 432 | D: Disk + Send + 'static, 433 | F: FnOnce(&Path) -> Result, 434 | { 435 | let mount_path = decide_mount_path(mount_path); 436 | 437 | let res = callback(Path::new(&mount_path)); 438 | 439 | if res.is_ok() { 440 | let _end_block = fs 441 | .tx(|tx| { 442 | // Archive_at root node 443 | redoxfs::archive_at(tx, Path::new(&mount_path), redoxfs::TreePtr::root()) 444 | .map_err(|err| syscall::Error::new(err.raw_os_error().unwrap()))?; 445 | 446 | // Squash alloc log 447 | tx.sync(true)?; 448 | 449 | let end_block = tx.header.size() / BLOCK_SIZE; 450 | /* TODO: Cut off any free blocks at the end of the filesystem 451 | let mut end_changed = true; 452 | while end_changed { 453 | end_changed = false; 454 | 455 | let allocator = fs.allocator(); 456 | let levels = allocator.levels(); 457 | for level in 0..levels.len() { 458 | let level_size = 1 << level; 459 | for &block in levels[level].iter() { 460 | if block < end_block && block + level_size >= end_block { 461 | end_block = block; 462 | end_changed = true; 463 | } 464 | } 465 | } 466 | } 467 | */ 468 | 469 | // Update header 470 | tx.header.size = (end_block * BLOCK_SIZE).into(); 471 | tx.header_changed = true; 472 | tx.sync(false)?; 473 | 474 | Ok(end_block) 475 | }) 476 | .map_err(syscall_error)?; 477 | 478 | // let size = (fs.block + end_block) * BLOCK_SIZE; 479 | // fs.disk.file.set_len(size)?; 480 | } 481 | 482 | fs::remove_dir_all(&mount_path)?; 483 | 484 | res 485 | } 486 | 487 | pub fn fetch_bootloaders( 488 | config: &Config, 489 | cookbook: Option<&str>, 490 | live: bool, 491 | ) -> Result<(Vec, Vec)> { 492 | let bootloader_dir = 493 | PathBuf::from(format!("/tmp/redox_installer_bootloader_{}", process::id())); 494 | 495 | if bootloader_dir.exists() { 496 | fs::remove_dir_all(&bootloader_dir)?; 497 | } 498 | 499 | fs::create_dir(&bootloader_dir)?; 500 | 501 | let mut bootloader_config = Config::default(); 502 | bootloader_config.general = config.general.clone(); 503 | // Ensure a pkgar remote is available 504 | FileConfig { 505 | path: "/etc/pkg.d/50_redox".to_string(), 506 | data: "https://static.redox-os.org/pkg".to_string(), 507 | ..Default::default() 508 | } 509 | .create(&bootloader_dir)?; 510 | bootloader_config 511 | .packages 512 | .insert("bootloader".to_string(), PackageConfig::default()); 513 | install_packages(&bootloader_config, &bootloader_dir, cookbook)?; 514 | 515 | let boot_dir = bootloader_dir.join("boot"); 516 | let bios_path = boot_dir.join(if live { 517 | "bootloader-live.bios" 518 | } else { 519 | "bootloader.bios" 520 | }); 521 | let efi_path = boot_dir.join(if live { 522 | "bootloader-live.efi" 523 | } else { 524 | "bootloader.efi" 525 | }); 526 | 527 | let bios_data = if bios_path.exists() { 528 | fs::read(bios_path)? 529 | } else { 530 | Vec::new() 531 | }; 532 | let efi_data = if efi_path.exists() { 533 | fs::read(efi_path)? 534 | } else { 535 | Vec::new() 536 | }; 537 | 538 | fs::remove_dir_all(&bootloader_dir)?; 539 | 540 | Ok((bios_data, efi_data)) 541 | } 542 | 543 | //TODO: make bootloaders use Option, dynamically create BIOS and EFI partitions 544 | pub fn with_whole_disk(disk_path: P, disk_option: &DiskOption, callback: F) -> Result 545 | where 546 | P: AsRef, 547 | F: FnOnce(FileSystem>>) -> Result, 548 | { 549 | let target = get_target(); 550 | 551 | let bootloader_efi_name = match target.as_str() { 552 | "aarch64-unknown-redox" => "BOOTAA64.EFI", 553 | "i586-unknown-redox" | "i686-unknown-redox" => "BOOTIA32.EFI", 554 | "x86_64-unknown-redox" => "BOOTX64.EFI", 555 | "riscv64gc-unknown-redox" => "BOOTRISCV64.EFI", 556 | _ => { 557 | bail!("target '{target}' not supported"); 558 | } 559 | }; 560 | // Open disk and read metadata 561 | eprintln!("Opening disk {}", disk_path.as_ref().display()); 562 | let mut disk_file = DiskWrapper::open(disk_path.as_ref())?; 563 | let disk_size = disk_file.size(); 564 | let block_size = disk_file.block_size() as u64; 565 | 566 | if disk_option.skip_partitions { 567 | return with_redoxfs( 568 | DiskIo(fscommon::StreamSlice::new( 569 | disk_file, 570 | 0, 571 | disk_size.next_multiple_of(block_size), 572 | )?), 573 | disk_option.password_opt, 574 | callback, 575 | ); 576 | } 577 | 578 | let gpt_block_size = match block_size { 579 | 512 => gpt::disk::LogicalBlockSize::Lb512, 580 | _ => { 581 | // TODO: support (and test) other block sizes 582 | bail!("block size {block_size} not supported"); 583 | } 584 | }; 585 | 586 | // Calculate partition offsets 587 | let gpt_reserved = 34 * 512; // GPT always reserves 34 512-byte sectors 588 | let mibi = 1024 * 1024; 589 | 590 | // First megabyte of the disk is reserved for BIOS partition, wich includes GPT tables 591 | let bios_start = gpt_reserved / block_size; 592 | let bios_end = (mibi / block_size) - 1; 593 | 594 | // Second megabyte of the disk is reserved for EFI partition 595 | let efi_start = bios_end + 1; 596 | let efi_size = if let Some(size) = disk_option.efi_partition_size { 597 | size as u64 598 | } else { 599 | 1 600 | }; 601 | let efi_end = efi_start + (efi_size * mibi / block_size) - 1; 602 | 603 | // The rest of the disk is RedoxFS, reserving the GPT table mirror at the end of disk 604 | let redoxfs_start = efi_end + 1; 605 | let redoxfs_end = ((((disk_size - gpt_reserved) / mibi) * mibi) / block_size) - 1; 606 | 607 | // Format and install BIOS partition 608 | { 609 | // Write BIOS bootloader to disk 610 | eprintln!( 611 | "Write bootloader with size {:#x}", 612 | disk_option.bootloader_bios.len() 613 | ); 614 | disk_file.seek(SeekFrom::Start(0))?; 615 | disk_file.write_all(&disk_option.bootloader_bios)?; 616 | 617 | // Replace MBR tables with protective MBR 618 | // TODO: div_ceil 619 | let mbr_blocks = ((disk_size + block_size - 1) / block_size) - 1; 620 | eprintln!("Writing protective MBR with disk blocks {mbr_blocks:#x}"); 621 | gpt::mbr::ProtectiveMBR::with_lb_size(mbr_blocks as u32) 622 | .update_conservative(&mut disk_file)?; 623 | 624 | // Open disk, mark it as not initialized 625 | let mut gpt_disk = gpt::GptConfig::new() 626 | .initialized(false) 627 | .writable(true) 628 | .logical_block_size(gpt_block_size) 629 | .create_from_device(Box::new(&mut disk_file), None)?; 630 | 631 | // Add BIOS boot partition 632 | let mut partitions = BTreeMap::new(); 633 | let mut partition_id = 1; 634 | partitions.insert( 635 | partition_id, 636 | gpt::partition::Partition { 637 | part_type_guid: gpt::partition_types::BIOS, 638 | part_guid: uuid::Uuid::new_v4(), 639 | first_lba: bios_start, 640 | last_lba: bios_end, 641 | flags: 0, // TODO 642 | name: "BIOS".to_string(), 643 | }, 644 | ); 645 | partition_id += 1; 646 | 647 | // Add EFI boot partition 648 | partitions.insert( 649 | partition_id, 650 | gpt::partition::Partition { 651 | part_type_guid: gpt::partition_types::EFI, 652 | part_guid: uuid::Uuid::new_v4(), 653 | first_lba: efi_start, 654 | last_lba: efi_end, 655 | flags: 0, // TODO 656 | name: "EFI".to_string(), 657 | }, 658 | ); 659 | partition_id += 1; 660 | 661 | // Add RedoxFS partition 662 | partitions.insert( 663 | partition_id, 664 | gpt::partition::Partition { 665 | //TODO: Use REDOX_REDOXFS type (needs GPT crate changes) 666 | part_type_guid: gpt::partition_types::LINUX_FS, 667 | part_guid: uuid::Uuid::new_v4(), 668 | first_lba: redoxfs_start, 669 | last_lba: redoxfs_end, 670 | flags: 0, 671 | name: "REDOX".to_string(), 672 | }, 673 | ); 674 | 675 | eprintln!("Writing GPT tables: {partitions:#?}"); 676 | 677 | // Initialize GPT table 678 | gpt_disk.update_partitions(partitions)?; 679 | 680 | // Write partition layout, returning disk file 681 | gpt_disk.write()?; 682 | } 683 | 684 | // Format and install EFI partition 685 | { 686 | let disk_efi_start = efi_start * block_size; 687 | let disk_efi_end = (efi_end + 1) * block_size; 688 | let mut disk_efi = 689 | fscommon::StreamSlice::new(&mut disk_file, disk_efi_start, disk_efi_end)?; 690 | 691 | eprintln!( 692 | "Formatting EFI partition with size {:#x}", 693 | disk_efi_end - disk_efi_start 694 | ); 695 | fatfs::format_volume(&mut disk_efi, fatfs::FormatVolumeOptions::new())?; 696 | 697 | eprintln!("Opening EFI partition"); 698 | let fs = fatfs::FileSystem::new(&mut disk_efi, fatfs::FsOptions::new())?; 699 | 700 | eprintln!("Creating EFI directory"); 701 | let root_dir = fs.root_dir(); 702 | root_dir.create_dir("EFI")?; 703 | 704 | eprintln!("Creating EFI/BOOT directory"); 705 | let efi_dir = root_dir.open_dir("EFI")?; 706 | efi_dir.create_dir("BOOT")?; 707 | 708 | eprintln!( 709 | "Writing EFI/BOOT/{} file with size {:#x}", 710 | bootloader_efi_name, 711 | disk_option.bootloader_efi.len() 712 | ); 713 | let boot_dir = efi_dir.open_dir("BOOT")?; 714 | let mut file = boot_dir.create_file(bootloader_efi_name)?; 715 | file.truncate()?; 716 | file.write_all(&disk_option.bootloader_efi)?; 717 | } 718 | 719 | // Format and install RedoxFS partition 720 | eprintln!( 721 | "Installing to RedoxFS partition with size {:#x}", 722 | (redoxfs_end - redoxfs_start) * block_size 723 | ); 724 | let disk_redoxfs = DiskIo(fscommon::StreamSlice::new( 725 | disk_file, 726 | redoxfs_start * block_size, 727 | (redoxfs_end + 1) * block_size, 728 | )?); 729 | with_redoxfs(disk_redoxfs, disk_option.password_opt, callback) 730 | } 731 | 732 | #[cfg(not(target_os = "redox"))] 733 | pub fn try_fast_install( 734 | _fs: &mut redoxfs::FileSystem, 735 | _progress: F, 736 | ) -> Result { 737 | Ok(false) 738 | } 739 | 740 | /// Try fast install using live disk memory 741 | #[cfg(target_os = "redox")] 742 | pub fn try_fast_install( 743 | fs: &mut redoxfs::FileSystem, 744 | mut progress: F, 745 | ) -> Result { 746 | use libredox::{call::MmapArgs, flag}; 747 | use std::os::fd::AsRawFd; 748 | use syscall::PAGE_SIZE; 749 | 750 | let phys = env::var("DISK_LIVE_ADDR") 751 | .ok() 752 | .and_then(|x| usize::from_str_radix(&x, 16).ok()) 753 | .unwrap_or(0); 754 | let size = env::var("DISK_LIVE_SIZE") 755 | .ok() 756 | .and_then(|x| usize::from_str_radix(&x, 16).ok()) 757 | .unwrap_or(0); 758 | if phys == 0 || size == 0 { 759 | return Ok(false); 760 | } 761 | 762 | let start = (phys / PAGE_SIZE) * PAGE_SIZE; 763 | let end = phys 764 | .checked_add(size) 765 | .context("phys + size overflow")? 766 | .next_multiple_of(PAGE_SIZE); 767 | let size = end - start; 768 | 769 | let original = unsafe { 770 | //TODO: unmap this memory 771 | let file = fs::File::open("/scheme/memory/physical")?; 772 | let base = libredox::call::mmap(MmapArgs { 773 | fd: file.as_raw_fd() as usize, 774 | addr: core::ptr::null_mut(), 775 | offset: start as u64, 776 | length: size, 777 | prot: flag::PROT_READ, 778 | flags: flag::MAP_SHARED, 779 | }) 780 | .map_err(|err| anyhow!("failed to mmap livedisk: {}", err))?; 781 | 782 | std::slice::from_raw_parts(base as *const u8, size) 783 | }; 784 | 785 | struct DiskLive { 786 | original: &'static [u8], 787 | } 788 | 789 | impl redoxfs::Disk for DiskLive { 790 | unsafe fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result { 791 | let offset = (block * redoxfs::BLOCK_SIZE) as usize; 792 | if offset + buffer.len() > self.original.len() { 793 | return Err(syscall::Error::new(syscall::EINVAL)); 794 | } 795 | buffer.copy_from_slice(&self.original[offset..offset + buffer.len()]); 796 | Ok(buffer.len()) 797 | } 798 | 799 | unsafe fn write_at(&mut self, _block: u64, _buffer: &[u8]) -> syscall::Result { 800 | Err(syscall::Error::new(syscall::EINVAL)) 801 | } 802 | 803 | fn size(&mut self) -> syscall::Result { 804 | Ok(self.original.len() as u64) 805 | } 806 | } 807 | 808 | let mut fs_old = redoxfs::FileSystem::open(DiskLive { original }, None, None, false)?; 809 | let size_old = fs_old.header.size(); 810 | let free_old = fs_old.allocator().free() * redoxfs::BLOCK_SIZE; 811 | let used_old = size_old - free_old; 812 | redoxfs::clone(&mut fs_old, fs, move |used| { 813 | progress(used, used_old); 814 | })?; 815 | 816 | Ok(true) 817 | } 818 | 819 | fn install_inner(config: Config, output: &Path) -> Result<()> { 820 | println!("Install {config:#?} to {}", output.display()); 821 | let cookbook = config.general.cookbook.clone(); 822 | let cookbook = cookbook.as_ref().map(|p| p.as_str()); 823 | if output.is_dir() { 824 | install_dir(config, output, cookbook) 825 | } else { 826 | let live = config.general.live_disk.unwrap_or(false); 827 | let password_opt = config.general.encrypt_disk.clone(); 828 | let password_opt = password_opt.as_ref().map(|p| p.as_bytes()); 829 | let (bootloader_bios, bootloader_efi) = fetch_bootloaders(&config, cookbook, live)?; 830 | if let Some(write_bootloader) = &config.general.write_bootloader { 831 | std::fs::write(write_bootloader, &bootloader_efi)?; 832 | } 833 | let disk_option = DiskOption { 834 | bootloader_bios: &bootloader_bios, 835 | bootloader_efi: &bootloader_efi, 836 | password_opt: password_opt, 837 | efi_partition_size: config.general.efi_partition_size, 838 | skip_partitions: config.general.skip_partitions.unwrap_or(false), 839 | }; 840 | with_whole_disk(output, &disk_option, move |fs| { 841 | if config.general.no_mount.unwrap_or(false) { 842 | with_redoxfs_ar(fs, None, move |mount_path| { 843 | install_dir(config, mount_path, cookbook) 844 | }) 845 | } else { 846 | with_redoxfs_mount(fs, None, move |mount_path| { 847 | install_dir(config, mount_path, cookbook) 848 | }) 849 | } 850 | }) 851 | } 852 | } 853 | 854 | /// Install RedoxFS into a new disk file, or a sysroot directory. 855 | /// This function assumes all interactive prompts resolved by the caller, 856 | /// so "prompt" option is ignored from this function onward. 857 | pub fn install(config: Config, output: impl AsRef) -> Result<()> { 858 | install_inner(config, output.as_ref()) 859 | } 860 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.25.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.1" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" 19 | 20 | [[package]] 21 | name = "aes" 22 | version = "0.8.4" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" 25 | dependencies = [ 26 | "cfg-if 1.0.3", 27 | "cipher", 28 | "cpufeatures", 29 | ] 30 | 31 | [[package]] 32 | name = "aho-corasick" 33 | version = "1.1.3" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 36 | dependencies = [ 37 | "memchr", 38 | ] 39 | 40 | [[package]] 41 | name = "alloc-no-stdlib" 42 | version = "2.0.4" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 45 | 46 | [[package]] 47 | name = "alloc-stdlib" 48 | version = "0.2.2" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 51 | dependencies = [ 52 | "alloc-no-stdlib", 53 | ] 54 | 55 | [[package]] 56 | name = "android_system_properties" 57 | version = "0.1.5" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 60 | dependencies = [ 61 | "libc", 62 | ] 63 | 64 | [[package]] 65 | name = "ansi_term" 66 | version = "0.12.1" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 69 | dependencies = [ 70 | "winapi", 71 | ] 72 | 73 | [[package]] 74 | name = "anstream" 75 | version = "0.6.20" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" 78 | dependencies = [ 79 | "anstyle", 80 | "anstyle-parse", 81 | "anstyle-query", 82 | "anstyle-wincon", 83 | "colorchoice", 84 | "is_terminal_polyfill", 85 | "utf8parse", 86 | ] 87 | 88 | [[package]] 89 | name = "anstyle" 90 | version = "1.0.11" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" 93 | 94 | [[package]] 95 | name = "anstyle-parse" 96 | version = "0.2.7" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" 99 | dependencies = [ 100 | "utf8parse", 101 | ] 102 | 103 | [[package]] 104 | name = "anstyle-query" 105 | version = "1.1.4" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" 108 | dependencies = [ 109 | "windows-sys 0.60.2", 110 | ] 111 | 112 | [[package]] 113 | name = "anstyle-wincon" 114 | version = "3.0.10" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" 117 | dependencies = [ 118 | "anstyle", 119 | "once_cell_polyfill", 120 | "windows-sys 0.60.2", 121 | ] 122 | 123 | [[package]] 124 | name = "anyhow" 125 | version = "1.0.100" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" 128 | 129 | [[package]] 130 | name = "arg_parser" 131 | version = "0.1.0" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "e9bcdf9185a4ea0d8afa7c8ad387cc3a93c3ecfa918125e000a57a42e71268d7" 134 | 135 | [[package]] 136 | name = "argon2" 137 | version = "0.4.1" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "db4ce4441f99dbd377ca8a8f57b698c44d0d6e712d8329b5040da5a64aa1ce73" 140 | dependencies = [ 141 | "base64ct", 142 | "blake2", 143 | ] 144 | 145 | [[package]] 146 | name = "arrayref" 147 | version = "0.3.9" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" 150 | 151 | [[package]] 152 | name = "arrayvec" 153 | version = "0.5.2" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 156 | 157 | [[package]] 158 | name = "async-compression" 159 | version = "0.4.32" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "5a89bce6054c720275ac2432fbba080a66a2106a44a1b804553930ca6909f4e0" 162 | dependencies = [ 163 | "compression-codecs", 164 | "compression-core", 165 | "futures-core", 166 | "pin-project-lite", 167 | "tokio", 168 | ] 169 | 170 | [[package]] 171 | name = "atomic-waker" 172 | version = "1.1.2" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 175 | 176 | [[package]] 177 | name = "atty" 178 | version = "0.2.14" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 181 | dependencies = [ 182 | "hermit-abi", 183 | "libc", 184 | "winapi", 185 | ] 186 | 187 | [[package]] 188 | name = "autocfg" 189 | version = "1.5.0" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 192 | 193 | [[package]] 194 | name = "backtrace" 195 | version = "0.3.76" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" 198 | dependencies = [ 199 | "addr2line", 200 | "cfg-if 1.0.3", 201 | "libc", 202 | "miniz_oxide", 203 | "object", 204 | "rustc-demangle", 205 | "windows-link", 206 | ] 207 | 208 | [[package]] 209 | name = "base64" 210 | version = "0.13.1" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 213 | 214 | [[package]] 215 | name = "base64" 216 | version = "0.22.1" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 219 | 220 | [[package]] 221 | name = "base64ct" 222 | version = "1.8.0" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" 225 | 226 | [[package]] 227 | name = "bitflags" 228 | version = "1.3.2" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 231 | 232 | [[package]] 233 | name = "bitflags" 234 | version = "2.9.4" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" 237 | 238 | [[package]] 239 | name = "blake2" 240 | version = "0.10.6" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" 243 | dependencies = [ 244 | "digest 0.10.7", 245 | ] 246 | 247 | [[package]] 248 | name = "blake2b_simd" 249 | version = "0.5.11" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" 252 | dependencies = [ 253 | "arrayref", 254 | "arrayvec", 255 | "constant_time_eq", 256 | ] 257 | 258 | [[package]] 259 | name = "blake3" 260 | version = "0.3.8" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" 263 | dependencies = [ 264 | "arrayref", 265 | "arrayvec", 266 | "cc", 267 | "cfg-if 0.1.10", 268 | "constant_time_eq", 269 | "crypto-mac", 270 | "digest 0.9.0", 271 | "rayon", 272 | ] 273 | 274 | [[package]] 275 | name = "block-buffer" 276 | version = "0.10.4" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 279 | dependencies = [ 280 | "generic-array", 281 | ] 282 | 283 | [[package]] 284 | name = "brotli" 285 | version = "8.0.2" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" 288 | dependencies = [ 289 | "alloc-no-stdlib", 290 | "alloc-stdlib", 291 | "brotli-decompressor", 292 | ] 293 | 294 | [[package]] 295 | name = "brotli-decompressor" 296 | version = "5.0.0" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" 299 | dependencies = [ 300 | "alloc-no-stdlib", 301 | "alloc-stdlib", 302 | ] 303 | 304 | [[package]] 305 | name = "bstr" 306 | version = "1.12.0" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" 309 | dependencies = [ 310 | "memchr", 311 | "serde", 312 | ] 313 | 314 | [[package]] 315 | name = "bumpalo" 316 | version = "3.19.0" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 319 | 320 | [[package]] 321 | name = "bytemuck" 322 | version = "1.23.2" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" 325 | dependencies = [ 326 | "bytemuck_derive", 327 | ] 328 | 329 | [[package]] 330 | name = "bytemuck_derive" 331 | version = "1.10.1" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29" 334 | dependencies = [ 335 | "proc-macro2", 336 | "quote", 337 | "syn", 338 | ] 339 | 340 | [[package]] 341 | name = "byteorder" 342 | version = "1.5.0" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 345 | 346 | [[package]] 347 | name = "bytes" 348 | version = "1.10.1" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 351 | 352 | [[package]] 353 | name = "cc" 354 | version = "1.2.47" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07" 357 | dependencies = [ 358 | "find-msvc-tools", 359 | "shlex", 360 | ] 361 | 362 | [[package]] 363 | name = "cfg-if" 364 | version = "0.1.10" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 367 | 368 | [[package]] 369 | name = "cfg-if" 370 | version = "1.0.3" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" 373 | 374 | [[package]] 375 | name = "cfg_aliases" 376 | version = "0.2.1" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 379 | 380 | [[package]] 381 | name = "chacha20" 382 | version = "0.9.1" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" 385 | dependencies = [ 386 | "cfg-if 1.0.3", 387 | "cipher", 388 | "cpufeatures", 389 | ] 390 | 391 | [[package]] 392 | name = "chrono" 393 | version = "0.4.42" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" 396 | dependencies = [ 397 | "iana-time-zone", 398 | "js-sys", 399 | "num-traits", 400 | "wasm-bindgen", 401 | "windows-link", 402 | ] 403 | 404 | [[package]] 405 | name = "cipher" 406 | version = "0.4.4" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" 409 | dependencies = [ 410 | "crypto-common", 411 | "inout", 412 | "zeroize", 413 | ] 414 | 415 | [[package]] 416 | name = "clap" 417 | version = "2.34.0" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" 420 | dependencies = [ 421 | "ansi_term", 422 | "atty", 423 | "bitflags 1.3.2", 424 | "strsim", 425 | "textwrap", 426 | "unicode-width 0.1.14", 427 | "vec_map", 428 | ] 429 | 430 | [[package]] 431 | name = "colorchoice" 432 | version = "1.0.4" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 435 | 436 | [[package]] 437 | name = "compression-codecs" 438 | version = "0.4.31" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23" 441 | dependencies = [ 442 | "brotli", 443 | "compression-core", 444 | ] 445 | 446 | [[package]] 447 | name = "compression-core" 448 | version = "0.4.29" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb" 451 | 452 | [[package]] 453 | name = "console" 454 | version = "0.15.11" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" 457 | dependencies = [ 458 | "encode_unicode", 459 | "libc", 460 | "once_cell", 461 | "unicode-width 0.2.1", 462 | "windows-sys 0.59.0", 463 | ] 464 | 465 | [[package]] 466 | name = "constant_time_eq" 467 | version = "0.1.5" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" 470 | 471 | [[package]] 472 | name = "core-foundation-sys" 473 | version = "0.8.7" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 476 | 477 | [[package]] 478 | name = "cpufeatures" 479 | version = "0.2.17" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 482 | dependencies = [ 483 | "libc", 484 | ] 485 | 486 | [[package]] 487 | name = "crc" 488 | version = "3.3.0" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" 491 | dependencies = [ 492 | "crc-catalog", 493 | ] 494 | 495 | [[package]] 496 | name = "crc-catalog" 497 | version = "2.4.0" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" 500 | 501 | [[package]] 502 | name = "crossbeam-deque" 503 | version = "0.8.6" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 506 | dependencies = [ 507 | "crossbeam-epoch", 508 | "crossbeam-utils", 509 | ] 510 | 511 | [[package]] 512 | name = "crossbeam-epoch" 513 | version = "0.9.18" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 516 | dependencies = [ 517 | "crossbeam-utils", 518 | ] 519 | 520 | [[package]] 521 | name = "crossbeam-utils" 522 | version = "0.8.21" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 525 | 526 | [[package]] 527 | name = "crypto-common" 528 | version = "0.1.6" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 531 | dependencies = [ 532 | "generic-array", 533 | "typenum", 534 | ] 535 | 536 | [[package]] 537 | name = "crypto-mac" 538 | version = "0.8.0" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" 541 | dependencies = [ 542 | "generic-array", 543 | "subtle", 544 | ] 545 | 546 | [[package]] 547 | name = "curve25519-dalek" 548 | version = "4.1.3" 549 | source = "registry+https://github.com/rust-lang/crates.io-index" 550 | checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" 551 | dependencies = [ 552 | "cfg-if 1.0.3", 553 | "cpufeatures", 554 | "curve25519-dalek-derive", 555 | "fiat-crypto", 556 | "rustc_version", 557 | "subtle", 558 | "zeroize", 559 | ] 560 | 561 | [[package]] 562 | name = "curve25519-dalek-derive" 563 | version = "0.1.1" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" 566 | dependencies = [ 567 | "proc-macro2", 568 | "quote", 569 | "syn", 570 | ] 571 | 572 | [[package]] 573 | name = "digest" 574 | version = "0.9.0" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 577 | dependencies = [ 578 | "generic-array", 579 | ] 580 | 581 | [[package]] 582 | name = "digest" 583 | version = "0.10.7" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 586 | dependencies = [ 587 | "block-buffer", 588 | "crypto-common", 589 | "subtle", 590 | ] 591 | 592 | [[package]] 593 | name = "dirs" 594 | version = "3.0.2" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" 597 | dependencies = [ 598 | "dirs-sys", 599 | ] 600 | 601 | [[package]] 602 | name = "dirs-sys" 603 | version = "0.3.7" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" 606 | dependencies = [ 607 | "libc", 608 | "redox_users", 609 | "winapi", 610 | ] 611 | 612 | [[package]] 613 | name = "displaydoc" 614 | version = "0.2.5" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 617 | dependencies = [ 618 | "proc-macro2", 619 | "quote", 620 | "syn", 621 | ] 622 | 623 | [[package]] 624 | name = "dryoc" 625 | version = "0.6.2" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "6e73e0fee365832cd9b9a53ea62f944cc0d7a4c71f2b9c96a28fc74749517afa" 628 | dependencies = [ 629 | "bitflags 2.9.4", 630 | "chacha20", 631 | "curve25519-dalek", 632 | "generic-array", 633 | "lazy_static", 634 | "libc", 635 | "rand_core 0.6.4", 636 | "salsa20", 637 | "sha2", 638 | "subtle", 639 | "winapi", 640 | "zeroize", 641 | ] 642 | 643 | [[package]] 644 | name = "either" 645 | version = "1.15.0" 646 | source = "registry+https://github.com/rust-lang/crates.io-index" 647 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 648 | 649 | [[package]] 650 | name = "encode_unicode" 651 | version = "1.0.0" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" 654 | 655 | [[package]] 656 | name = "endian-num" 657 | version = "0.1.2" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "f8f59926911ef34d1efb9ea1ee8ca78385df62ce700ccf2bcb149011bd226888" 660 | 661 | [[package]] 662 | name = "env_filter" 663 | version = "0.1.3" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" 666 | dependencies = [ 667 | "log", 668 | "regex", 669 | ] 670 | 671 | [[package]] 672 | name = "env_logger" 673 | version = "0.11.8" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" 676 | dependencies = [ 677 | "anstream", 678 | "anstyle", 679 | "env_filter", 680 | "jiff", 681 | "log", 682 | ] 683 | 684 | [[package]] 685 | name = "equivalent" 686 | version = "1.0.2" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 689 | 690 | [[package]] 691 | name = "fatfs" 692 | version = "0.3.6" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "05669f8e7e2d7badc545c513710f0eba09c2fbef683eb859fd79c46c355048e0" 695 | dependencies = [ 696 | "bitflags 1.3.2", 697 | "byteorder", 698 | "chrono", 699 | "log", 700 | ] 701 | 702 | [[package]] 703 | name = "fiat-crypto" 704 | version = "0.2.9" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" 707 | 708 | [[package]] 709 | name = "find-msvc-tools" 710 | version = "0.1.5" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" 713 | 714 | [[package]] 715 | name = "fnv" 716 | version = "1.0.7" 717 | source = "registry+https://github.com/rust-lang/crates.io-index" 718 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 719 | 720 | [[package]] 721 | name = "form_urlencoded" 722 | version = "1.2.2" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" 725 | dependencies = [ 726 | "percent-encoding", 727 | ] 728 | 729 | [[package]] 730 | name = "fscommon" 731 | version = "0.1.1" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "315ce685aca5ddcc5a3e7e436ef47d4a5d0064462849b6f0f628c28140103531" 734 | dependencies = [ 735 | "log", 736 | ] 737 | 738 | [[package]] 739 | name = "fuser" 740 | version = "0.14.0" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | checksum = "2e697f6f62c20b6fad1ba0f84ae909f25971cf16e735273524e3977c94604cf8" 743 | dependencies = [ 744 | "libc", 745 | "log", 746 | "memchr", 747 | "page_size", 748 | "pkg-config", 749 | "smallvec", 750 | "zerocopy 0.7.35", 751 | ] 752 | 753 | [[package]] 754 | name = "futures-channel" 755 | version = "0.3.31" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 758 | dependencies = [ 759 | "futures-core", 760 | "futures-sink", 761 | ] 762 | 763 | [[package]] 764 | name = "futures-core" 765 | version = "0.3.31" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 768 | 769 | [[package]] 770 | name = "futures-io" 771 | version = "0.3.31" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 774 | 775 | [[package]] 776 | name = "futures-sink" 777 | version = "0.3.31" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 780 | 781 | [[package]] 782 | name = "futures-task" 783 | version = "0.3.31" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 786 | 787 | [[package]] 788 | name = "futures-util" 789 | version = "0.3.31" 790 | source = "registry+https://github.com/rust-lang/crates.io-index" 791 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 792 | dependencies = [ 793 | "futures-core", 794 | "futures-io", 795 | "futures-sink", 796 | "futures-task", 797 | "memchr", 798 | "pin-project-lite", 799 | "pin-utils", 800 | "slab", 801 | ] 802 | 803 | [[package]] 804 | name = "generic-array" 805 | version = "0.14.7" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 808 | dependencies = [ 809 | "typenum", 810 | "version_check", 811 | ] 812 | 813 | [[package]] 814 | name = "getrandom" 815 | version = "0.1.16" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 818 | dependencies = [ 819 | "cfg-if 1.0.3", 820 | "libc", 821 | "wasi 0.9.0+wasi-snapshot-preview1", 822 | ] 823 | 824 | [[package]] 825 | name = "getrandom" 826 | version = "0.2.16" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 829 | dependencies = [ 830 | "cfg-if 1.0.3", 831 | "js-sys", 832 | "libc", 833 | "wasi 0.11.1+wasi-snapshot-preview1", 834 | "wasm-bindgen", 835 | ] 836 | 837 | [[package]] 838 | name = "getrandom" 839 | version = "0.3.3" 840 | source = "registry+https://github.com/rust-lang/crates.io-index" 841 | checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 842 | dependencies = [ 843 | "cfg-if 1.0.3", 844 | "js-sys", 845 | "libc", 846 | "r-efi", 847 | "wasi 0.14.7+wasi-0.2.4", 848 | "wasm-bindgen", 849 | ] 850 | 851 | [[package]] 852 | name = "gimli" 853 | version = "0.32.3" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" 856 | 857 | [[package]] 858 | name = "globset" 859 | version = "0.4.16" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" 862 | dependencies = [ 863 | "aho-corasick", 864 | "bstr", 865 | "log", 866 | "regex-automata", 867 | "regex-syntax", 868 | ] 869 | 870 | [[package]] 871 | name = "gpt" 872 | version = "3.1.0" 873 | source = "registry+https://github.com/rust-lang/crates.io-index" 874 | checksum = "8283e7331b8c93b9756e0cfdbcfb90312852f953c6faf9bf741e684cc3b6ad69" 875 | dependencies = [ 876 | "bitflags 2.9.4", 877 | "crc", 878 | "log", 879 | "uuid", 880 | ] 881 | 882 | [[package]] 883 | name = "hashbrown" 884 | version = "0.16.0" 885 | source = "registry+https://github.com/rust-lang/crates.io-index" 886 | checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" 887 | 888 | [[package]] 889 | name = "hermit-abi" 890 | version = "0.1.19" 891 | source = "registry+https://github.com/rust-lang/crates.io-index" 892 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 893 | dependencies = [ 894 | "libc", 895 | ] 896 | 897 | [[package]] 898 | name = "hex" 899 | version = "0.4.3" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 902 | dependencies = [ 903 | "serde", 904 | ] 905 | 906 | [[package]] 907 | name = "http" 908 | version = "1.3.1" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 911 | dependencies = [ 912 | "bytes", 913 | "fnv", 914 | "itoa", 915 | ] 916 | 917 | [[package]] 918 | name = "http-body" 919 | version = "1.0.1" 920 | source = "registry+https://github.com/rust-lang/crates.io-index" 921 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 922 | dependencies = [ 923 | "bytes", 924 | "http", 925 | ] 926 | 927 | [[package]] 928 | name = "http-body-util" 929 | version = "0.1.3" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 932 | dependencies = [ 933 | "bytes", 934 | "futures-core", 935 | "http", 936 | "http-body", 937 | "pin-project-lite", 938 | ] 939 | 940 | [[package]] 941 | name = "httparse" 942 | version = "1.10.1" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 945 | 946 | [[package]] 947 | name = "humansize" 948 | version = "2.1.3" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" 951 | dependencies = [ 952 | "libm", 953 | ] 954 | 955 | [[package]] 956 | name = "hyper" 957 | version = "1.7.0" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" 960 | dependencies = [ 961 | "atomic-waker", 962 | "bytes", 963 | "futures-channel", 964 | "futures-core", 965 | "http", 966 | "http-body", 967 | "httparse", 968 | "itoa", 969 | "pin-project-lite", 970 | "pin-utils", 971 | "smallvec", 972 | "tokio", 973 | "want", 974 | ] 975 | 976 | [[package]] 977 | name = "hyper-rustls" 978 | version = "0.27.7" 979 | source = "registry+https://github.com/rust-lang/crates.io-index" 980 | checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" 981 | dependencies = [ 982 | "http", 983 | "hyper", 984 | "hyper-util", 985 | "rustls", 986 | "rustls-pki-types", 987 | "tokio", 988 | "tokio-rustls", 989 | "tower-service", 990 | "webpki-roots", 991 | ] 992 | 993 | [[package]] 994 | name = "hyper-util" 995 | version = "0.1.17" 996 | source = "registry+https://github.com/rust-lang/crates.io-index" 997 | checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" 998 | dependencies = [ 999 | "base64 0.22.1", 1000 | "bytes", 1001 | "futures-channel", 1002 | "futures-core", 1003 | "futures-util", 1004 | "http", 1005 | "http-body", 1006 | "hyper", 1007 | "ipnet", 1008 | "libc", 1009 | "percent-encoding", 1010 | "pin-project-lite", 1011 | "socket2", 1012 | "tokio", 1013 | "tower-service", 1014 | "tracing", 1015 | ] 1016 | 1017 | [[package]] 1018 | name = "iana-time-zone" 1019 | version = "0.1.64" 1020 | source = "registry+https://github.com/rust-lang/crates.io-index" 1021 | checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" 1022 | dependencies = [ 1023 | "android_system_properties", 1024 | "core-foundation-sys", 1025 | "iana-time-zone-haiku", 1026 | "js-sys", 1027 | "log", 1028 | "wasm-bindgen", 1029 | "windows-core", 1030 | ] 1031 | 1032 | [[package]] 1033 | name = "iana-time-zone-haiku" 1034 | version = "0.1.2" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 1037 | dependencies = [ 1038 | "cc", 1039 | ] 1040 | 1041 | [[package]] 1042 | name = "icu_collections" 1043 | version = "2.0.0" 1044 | source = "registry+https://github.com/rust-lang/crates.io-index" 1045 | checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" 1046 | dependencies = [ 1047 | "displaydoc", 1048 | "potential_utf", 1049 | "yoke", 1050 | "zerofrom", 1051 | "zerovec", 1052 | ] 1053 | 1054 | [[package]] 1055 | name = "icu_locale_core" 1056 | version = "2.0.0" 1057 | source = "registry+https://github.com/rust-lang/crates.io-index" 1058 | checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" 1059 | dependencies = [ 1060 | "displaydoc", 1061 | "litemap", 1062 | "tinystr", 1063 | "writeable", 1064 | "zerovec", 1065 | ] 1066 | 1067 | [[package]] 1068 | name = "icu_normalizer" 1069 | version = "2.0.0" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" 1072 | dependencies = [ 1073 | "displaydoc", 1074 | "icu_collections", 1075 | "icu_normalizer_data", 1076 | "icu_properties", 1077 | "icu_provider", 1078 | "smallvec", 1079 | "zerovec", 1080 | ] 1081 | 1082 | [[package]] 1083 | name = "icu_normalizer_data" 1084 | version = "2.0.0" 1085 | source = "registry+https://github.com/rust-lang/crates.io-index" 1086 | checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" 1087 | 1088 | [[package]] 1089 | name = "icu_properties" 1090 | version = "2.0.1" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" 1093 | dependencies = [ 1094 | "displaydoc", 1095 | "icu_collections", 1096 | "icu_locale_core", 1097 | "icu_properties_data", 1098 | "icu_provider", 1099 | "potential_utf", 1100 | "zerotrie", 1101 | "zerovec", 1102 | ] 1103 | 1104 | [[package]] 1105 | name = "icu_properties_data" 1106 | version = "2.0.1" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" 1109 | 1110 | [[package]] 1111 | name = "icu_provider" 1112 | version = "2.0.0" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" 1115 | dependencies = [ 1116 | "displaydoc", 1117 | "icu_locale_core", 1118 | "stable_deref_trait", 1119 | "tinystr", 1120 | "writeable", 1121 | "yoke", 1122 | "zerofrom", 1123 | "zerotrie", 1124 | "zerovec", 1125 | ] 1126 | 1127 | [[package]] 1128 | name = "idna" 1129 | version = "1.1.0" 1130 | source = "registry+https://github.com/rust-lang/crates.io-index" 1131 | checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" 1132 | dependencies = [ 1133 | "idna_adapter", 1134 | "smallvec", 1135 | "utf8_iter", 1136 | ] 1137 | 1138 | [[package]] 1139 | name = "idna_adapter" 1140 | version = "1.2.1" 1141 | source = "registry+https://github.com/rust-lang/crates.io-index" 1142 | checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" 1143 | dependencies = [ 1144 | "icu_normalizer", 1145 | "icu_properties", 1146 | ] 1147 | 1148 | [[package]] 1149 | name = "ignore" 1150 | version = "0.4.23" 1151 | source = "registry+https://github.com/rust-lang/crates.io-index" 1152 | checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" 1153 | dependencies = [ 1154 | "crossbeam-deque", 1155 | "globset", 1156 | "log", 1157 | "memchr", 1158 | "regex-automata", 1159 | "same-file", 1160 | "walkdir", 1161 | "winapi-util", 1162 | ] 1163 | 1164 | [[package]] 1165 | name = "indexmap" 1166 | version = "2.11.4" 1167 | source = "registry+https://github.com/rust-lang/crates.io-index" 1168 | checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" 1169 | dependencies = [ 1170 | "equivalent", 1171 | "hashbrown", 1172 | ] 1173 | 1174 | [[package]] 1175 | name = "indicatif" 1176 | version = "0.17.11" 1177 | source = "registry+https://github.com/rust-lang/crates.io-index" 1178 | checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" 1179 | dependencies = [ 1180 | "console", 1181 | "number_prefix", 1182 | "portable-atomic", 1183 | "unicode-width 0.2.1", 1184 | "web-time", 1185 | ] 1186 | 1187 | [[package]] 1188 | name = "inout" 1189 | version = "0.1.4" 1190 | source = "registry+https://github.com/rust-lang/crates.io-index" 1191 | checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" 1192 | dependencies = [ 1193 | "generic-array", 1194 | ] 1195 | 1196 | [[package]] 1197 | name = "io-uring" 1198 | version = "0.7.10" 1199 | source = "registry+https://github.com/rust-lang/crates.io-index" 1200 | checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" 1201 | dependencies = [ 1202 | "bitflags 2.9.4", 1203 | "cfg-if 1.0.3", 1204 | "libc", 1205 | ] 1206 | 1207 | [[package]] 1208 | name = "ipnet" 1209 | version = "2.11.0" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 1212 | 1213 | [[package]] 1214 | name = "iri-string" 1215 | version = "0.7.8" 1216 | source = "registry+https://github.com/rust-lang/crates.io-index" 1217 | checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" 1218 | dependencies = [ 1219 | "memchr", 1220 | "serde", 1221 | ] 1222 | 1223 | [[package]] 1224 | name = "is_terminal_polyfill" 1225 | version = "1.70.1" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 1228 | 1229 | [[package]] 1230 | name = "itoa" 1231 | version = "1.0.15" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 1234 | 1235 | [[package]] 1236 | name = "jiff" 1237 | version = "0.2.15" 1238 | source = "registry+https://github.com/rust-lang/crates.io-index" 1239 | checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" 1240 | dependencies = [ 1241 | "jiff-static", 1242 | "log", 1243 | "portable-atomic", 1244 | "portable-atomic-util", 1245 | "serde", 1246 | ] 1247 | 1248 | [[package]] 1249 | name = "jiff-static" 1250 | version = "0.2.15" 1251 | source = "registry+https://github.com/rust-lang/crates.io-index" 1252 | checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" 1253 | dependencies = [ 1254 | "proc-macro2", 1255 | "quote", 1256 | "syn", 1257 | ] 1258 | 1259 | [[package]] 1260 | name = "js-sys" 1261 | version = "0.3.81" 1262 | source = "registry+https://github.com/rust-lang/crates.io-index" 1263 | checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" 1264 | dependencies = [ 1265 | "once_cell", 1266 | "wasm-bindgen", 1267 | ] 1268 | 1269 | [[package]] 1270 | name = "lazy_static" 1271 | version = "1.5.0" 1272 | source = "registry+https://github.com/rust-lang/crates.io-index" 1273 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1274 | 1275 | [[package]] 1276 | name = "libc" 1277 | version = "0.2.176" 1278 | source = "registry+https://github.com/rust-lang/crates.io-index" 1279 | checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" 1280 | 1281 | [[package]] 1282 | name = "libm" 1283 | version = "0.2.15" 1284 | source = "registry+https://github.com/rust-lang/crates.io-index" 1285 | checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" 1286 | 1287 | [[package]] 1288 | name = "libredox" 1289 | version = "0.1.10" 1290 | source = "registry+https://github.com/rust-lang/crates.io-index" 1291 | checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" 1292 | dependencies = [ 1293 | "bitflags 2.9.4", 1294 | "libc", 1295 | "redox_syscall", 1296 | ] 1297 | 1298 | [[package]] 1299 | name = "litemap" 1300 | version = "0.8.0" 1301 | source = "registry+https://github.com/rust-lang/crates.io-index" 1302 | checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" 1303 | 1304 | [[package]] 1305 | name = "log" 1306 | version = "0.4.28" 1307 | source = "registry+https://github.com/rust-lang/crates.io-index" 1308 | checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" 1309 | 1310 | [[package]] 1311 | name = "lru-slab" 1312 | version = "0.1.2" 1313 | source = "registry+https://github.com/rust-lang/crates.io-index" 1314 | checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" 1315 | 1316 | [[package]] 1317 | name = "lz4_flex" 1318 | version = "0.11.5" 1319 | source = "registry+https://github.com/rust-lang/crates.io-index" 1320 | checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" 1321 | 1322 | [[package]] 1323 | name = "memchr" 1324 | version = "2.7.6" 1325 | source = "registry+https://github.com/rust-lang/crates.io-index" 1326 | checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" 1327 | 1328 | [[package]] 1329 | name = "memsec" 1330 | version = "0.6.3" 1331 | source = "registry+https://github.com/rust-lang/crates.io-index" 1332 | checksum = "0fa0916b001582d253822171bd23f4a0229d32b9507fae236f5da8cad515ba7c" 1333 | dependencies = [ 1334 | "getrandom 0.2.16", 1335 | "libc", 1336 | "windows-sys 0.45.0", 1337 | ] 1338 | 1339 | [[package]] 1340 | name = "miniz_oxide" 1341 | version = "0.8.9" 1342 | source = "registry+https://github.com/rust-lang/crates.io-index" 1343 | checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" 1344 | dependencies = [ 1345 | "adler2", 1346 | ] 1347 | 1348 | [[package]] 1349 | name = "mio" 1350 | version = "1.0.4" 1351 | source = "registry+https://github.com/rust-lang/crates.io-index" 1352 | checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 1353 | dependencies = [ 1354 | "libc", 1355 | "wasi 0.11.1+wasi-snapshot-preview1", 1356 | "windows-sys 0.59.0", 1357 | ] 1358 | 1359 | [[package]] 1360 | name = "num-traits" 1361 | version = "0.2.19" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1364 | dependencies = [ 1365 | "autocfg", 1366 | ] 1367 | 1368 | [[package]] 1369 | name = "number_prefix" 1370 | version = "0.4.0" 1371 | source = "registry+https://github.com/rust-lang/crates.io-index" 1372 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" 1373 | 1374 | [[package]] 1375 | name = "numtoa" 1376 | version = "0.2.4" 1377 | source = "registry+https://github.com/rust-lang/crates.io-index" 1378 | checksum = "6aa2c4e539b869820a2b82e1aef6ff40aa85e65decdd5185e83fb4b1249cd00f" 1379 | 1380 | [[package]] 1381 | name = "object" 1382 | version = "0.37.3" 1383 | source = "registry+https://github.com/rust-lang/crates.io-index" 1384 | checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" 1385 | dependencies = [ 1386 | "memchr", 1387 | ] 1388 | 1389 | [[package]] 1390 | name = "once_cell" 1391 | version = "1.21.3" 1392 | source = "registry+https://github.com/rust-lang/crates.io-index" 1393 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 1394 | 1395 | [[package]] 1396 | name = "once_cell_polyfill" 1397 | version = "1.70.1" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" 1400 | 1401 | [[package]] 1402 | name = "page_size" 1403 | version = "0.6.0" 1404 | source = "registry+https://github.com/rust-lang/crates.io-index" 1405 | checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" 1406 | dependencies = [ 1407 | "libc", 1408 | "winapi", 1409 | ] 1410 | 1411 | [[package]] 1412 | name = "parse-size" 1413 | version = "1.1.0" 1414 | source = "registry+https://github.com/rust-lang/crates.io-index" 1415 | checksum = "487f2ccd1e17ce8c1bfab3a65c89525af41cfad4c8659021a1e9a2aacd73b89b" 1416 | 1417 | [[package]] 1418 | name = "percent-encoding" 1419 | version = "2.3.2" 1420 | source = "registry+https://github.com/rust-lang/crates.io-index" 1421 | checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" 1422 | 1423 | [[package]] 1424 | name = "pin-project-lite" 1425 | version = "0.2.16" 1426 | source = "registry+https://github.com/rust-lang/crates.io-index" 1427 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1428 | 1429 | [[package]] 1430 | name = "pin-utils" 1431 | version = "0.1.0" 1432 | source = "registry+https://github.com/rust-lang/crates.io-index" 1433 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1434 | 1435 | [[package]] 1436 | name = "pkg-config" 1437 | version = "0.3.32" 1438 | source = "registry+https://github.com/rust-lang/crates.io-index" 1439 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 1440 | 1441 | [[package]] 1442 | name = "pkgar" 1443 | version = "0.1.19" 1444 | source = "registry+https://github.com/rust-lang/crates.io-index" 1445 | checksum = "dab99cb7a6d62ca2667eca54ffab93fc77e3f4d19e67a2dce7d65c22adaa7324" 1446 | dependencies = [ 1447 | "anyhow", 1448 | "blake3", 1449 | "bytemuck", 1450 | "clap", 1451 | "pkgar-core", 1452 | "pkgar-keys", 1453 | "thiserror 2.0.16", 1454 | ] 1455 | 1456 | [[package]] 1457 | name = "pkgar-core" 1458 | version = "0.1.19" 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" 1460 | checksum = "cc0f6069f730523018711e77c41b642cf922ef7f4b5505bbf28e7070da4de206" 1461 | dependencies = [ 1462 | "bitflags 1.3.2", 1463 | "blake3", 1464 | "bytemuck", 1465 | "dryoc", 1466 | ] 1467 | 1468 | [[package]] 1469 | name = "pkgar-keys" 1470 | version = "0.1.19" 1471 | source = "registry+https://github.com/rust-lang/crates.io-index" 1472 | checksum = "928cd21d644eb3c0a687bc5b76c07a2ace4e96a8f3c948538e4d4e6a5b8aeabf" 1473 | dependencies = [ 1474 | "anyhow", 1475 | "clap", 1476 | "dirs", 1477 | "hex", 1478 | "lazy_static", 1479 | "pkgar-core", 1480 | "seckey", 1481 | "serde", 1482 | "termion", 1483 | "thiserror 2.0.16", 1484 | "toml", 1485 | ] 1486 | 1487 | [[package]] 1488 | name = "portable-atomic" 1489 | version = "1.11.1" 1490 | source = "registry+https://github.com/rust-lang/crates.io-index" 1491 | checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" 1492 | 1493 | [[package]] 1494 | name = "portable-atomic-util" 1495 | version = "0.2.4" 1496 | source = "registry+https://github.com/rust-lang/crates.io-index" 1497 | checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" 1498 | dependencies = [ 1499 | "portable-atomic", 1500 | ] 1501 | 1502 | [[package]] 1503 | name = "potential_utf" 1504 | version = "0.1.3" 1505 | source = "registry+https://github.com/rust-lang/crates.io-index" 1506 | checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" 1507 | dependencies = [ 1508 | "zerovec", 1509 | ] 1510 | 1511 | [[package]] 1512 | name = "ppv-lite86" 1513 | version = "0.2.21" 1514 | source = "registry+https://github.com/rust-lang/crates.io-index" 1515 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 1516 | dependencies = [ 1517 | "zerocopy 0.8.27", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "proc-macro2" 1522 | version = "1.0.101" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" 1525 | dependencies = [ 1526 | "unicode-ident", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "quinn" 1531 | version = "0.11.9" 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" 1533 | checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" 1534 | dependencies = [ 1535 | "bytes", 1536 | "cfg_aliases", 1537 | "pin-project-lite", 1538 | "quinn-proto", 1539 | "quinn-udp", 1540 | "rustc-hash", 1541 | "rustls", 1542 | "socket2", 1543 | "thiserror 2.0.16", 1544 | "tokio", 1545 | "tracing", 1546 | "web-time", 1547 | ] 1548 | 1549 | [[package]] 1550 | name = "quinn-proto" 1551 | version = "0.11.13" 1552 | source = "registry+https://github.com/rust-lang/crates.io-index" 1553 | checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" 1554 | dependencies = [ 1555 | "bytes", 1556 | "getrandom 0.3.3", 1557 | "lru-slab", 1558 | "rand", 1559 | "ring", 1560 | "rustc-hash", 1561 | "rustls", 1562 | "rustls-pki-types", 1563 | "slab", 1564 | "thiserror 2.0.16", 1565 | "tinyvec", 1566 | "tracing", 1567 | "web-time", 1568 | ] 1569 | 1570 | [[package]] 1571 | name = "quinn-udp" 1572 | version = "0.5.14" 1573 | source = "registry+https://github.com/rust-lang/crates.io-index" 1574 | checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" 1575 | dependencies = [ 1576 | "cfg_aliases", 1577 | "libc", 1578 | "once_cell", 1579 | "socket2", 1580 | "tracing", 1581 | "windows-sys 0.52.0", 1582 | ] 1583 | 1584 | [[package]] 1585 | name = "quote" 1586 | version = "1.0.40" 1587 | source = "registry+https://github.com/rust-lang/crates.io-index" 1588 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 1589 | dependencies = [ 1590 | "proc-macro2", 1591 | ] 1592 | 1593 | [[package]] 1594 | name = "r-efi" 1595 | version = "5.3.0" 1596 | source = "registry+https://github.com/rust-lang/crates.io-index" 1597 | checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 1598 | 1599 | [[package]] 1600 | name = "rand" 1601 | version = "0.9.2" 1602 | source = "registry+https://github.com/rust-lang/crates.io-index" 1603 | checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" 1604 | dependencies = [ 1605 | "rand_chacha", 1606 | "rand_core 0.9.3", 1607 | ] 1608 | 1609 | [[package]] 1610 | name = "rand_chacha" 1611 | version = "0.9.0" 1612 | source = "registry+https://github.com/rust-lang/crates.io-index" 1613 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 1614 | dependencies = [ 1615 | "ppv-lite86", 1616 | "rand_core 0.9.3", 1617 | ] 1618 | 1619 | [[package]] 1620 | name = "rand_core" 1621 | version = "0.6.4" 1622 | source = "registry+https://github.com/rust-lang/crates.io-index" 1623 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1624 | dependencies = [ 1625 | "getrandom 0.2.16", 1626 | ] 1627 | 1628 | [[package]] 1629 | name = "rand_core" 1630 | version = "0.9.3" 1631 | source = "registry+https://github.com/rust-lang/crates.io-index" 1632 | checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 1633 | dependencies = [ 1634 | "getrandom 0.3.3", 1635 | ] 1636 | 1637 | [[package]] 1638 | name = "range-tree" 1639 | version = "0.1.0" 1640 | source = "registry+https://github.com/rust-lang/crates.io-index" 1641 | checksum = "384c2842d4e069d5ccacf5fe1dca4ef8d07a5444329715f0fc3c61813502d4d1" 1642 | 1643 | [[package]] 1644 | name = "rayon" 1645 | version = "1.11.0" 1646 | source = "registry+https://github.com/rust-lang/crates.io-index" 1647 | checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" 1648 | dependencies = [ 1649 | "either", 1650 | "rayon-core", 1651 | ] 1652 | 1653 | [[package]] 1654 | name = "rayon-core" 1655 | version = "1.13.0" 1656 | source = "registry+https://github.com/rust-lang/crates.io-index" 1657 | checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" 1658 | dependencies = [ 1659 | "crossbeam-deque", 1660 | "crossbeam-utils", 1661 | ] 1662 | 1663 | [[package]] 1664 | name = "redox-path" 1665 | version = "0.3.1" 1666 | source = "registry+https://github.com/rust-lang/crates.io-index" 1667 | checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717" 1668 | 1669 | [[package]] 1670 | name = "redox-pkg" 1671 | version = "0.2.9" 1672 | source = "registry+https://github.com/rust-lang/crates.io-index" 1673 | checksum = "0a18d9b020d0fd3fa4e613bc7ffc3c789fba16f4e74c484cc7e63f6ffb71bc09" 1674 | dependencies = [ 1675 | "anyhow", 1676 | "ignore", 1677 | "indicatif", 1678 | "pkgar", 1679 | "pkgar-core", 1680 | "pkgar-keys", 1681 | "reqwest", 1682 | "serde", 1683 | "serde_derive", 1684 | "thiserror 1.0.69", 1685 | "toml", 1686 | ] 1687 | 1688 | [[package]] 1689 | name = "redox-scheme" 1690 | version = "0.7.0" 1691 | source = "registry+https://github.com/rust-lang/crates.io-index" 1692 | checksum = "4da6a0251965958189cdfd5ebb66f99754db4aa165394300aa2b958525d94b64" 1693 | dependencies = [ 1694 | "libredox", 1695 | "redox_syscall", 1696 | ] 1697 | 1698 | [[package]] 1699 | name = "redox_installer" 1700 | version = "0.2.38" 1701 | dependencies = [ 1702 | "anyhow", 1703 | "arg_parser", 1704 | "fatfs", 1705 | "fscommon", 1706 | "gpt", 1707 | "libc", 1708 | "libredox", 1709 | "pkgar", 1710 | "pkgar-core", 1711 | "pkgar-keys", 1712 | "rand", 1713 | "redox-pkg", 1714 | "redox_syscall", 1715 | "redoxfs", 1716 | "rust-argon2", 1717 | "serde", 1718 | "serde_derive", 1719 | "termion", 1720 | "toml", 1721 | "uuid", 1722 | ] 1723 | 1724 | [[package]] 1725 | name = "redox_syscall" 1726 | version = "0.5.17" 1727 | source = "registry+https://github.com/rust-lang/crates.io-index" 1728 | checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" 1729 | dependencies = [ 1730 | "bitflags 2.9.4", 1731 | ] 1732 | 1733 | [[package]] 1734 | name = "redox_termios" 1735 | version = "0.1.3" 1736 | source = "registry+https://github.com/rust-lang/crates.io-index" 1737 | checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb" 1738 | 1739 | [[package]] 1740 | name = "redox_users" 1741 | version = "0.4.6" 1742 | source = "registry+https://github.com/rust-lang/crates.io-index" 1743 | checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" 1744 | dependencies = [ 1745 | "getrandom 0.2.16", 1746 | "libredox", 1747 | "thiserror 1.0.69", 1748 | ] 1749 | 1750 | [[package]] 1751 | name = "redoxfs" 1752 | version = "0.8.3" 1753 | source = "registry+https://github.com/rust-lang/crates.io-index" 1754 | checksum = "0216ac4a3e423d54309b2d342bb585183add9b25eef8cc801029a4ff955bef63" 1755 | dependencies = [ 1756 | "aes", 1757 | "argon2", 1758 | "base64ct", 1759 | "bitflags 2.9.4", 1760 | "endian-num", 1761 | "env_logger", 1762 | "fuser", 1763 | "getrandom 0.2.16", 1764 | "humansize", 1765 | "libc", 1766 | "libredox", 1767 | "log", 1768 | "lz4_flex", 1769 | "parse-size", 1770 | "range-tree", 1771 | "redox-path", 1772 | "redox-scheme", 1773 | "redox_syscall", 1774 | "seahash", 1775 | "termion", 1776 | "uuid", 1777 | "xts-mode", 1778 | ] 1779 | 1780 | [[package]] 1781 | name = "regex" 1782 | version = "1.11.3" 1783 | source = "registry+https://github.com/rust-lang/crates.io-index" 1784 | checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c" 1785 | dependencies = [ 1786 | "aho-corasick", 1787 | "memchr", 1788 | "regex-automata", 1789 | "regex-syntax", 1790 | ] 1791 | 1792 | [[package]] 1793 | name = "regex-automata" 1794 | version = "0.4.11" 1795 | source = "registry+https://github.com/rust-lang/crates.io-index" 1796 | checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad" 1797 | dependencies = [ 1798 | "aho-corasick", 1799 | "memchr", 1800 | "regex-syntax", 1801 | ] 1802 | 1803 | [[package]] 1804 | name = "regex-syntax" 1805 | version = "0.8.6" 1806 | source = "registry+https://github.com/rust-lang/crates.io-index" 1807 | checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" 1808 | 1809 | [[package]] 1810 | name = "reqwest" 1811 | version = "0.12.23" 1812 | source = "registry+https://github.com/rust-lang/crates.io-index" 1813 | checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" 1814 | dependencies = [ 1815 | "async-compression", 1816 | "base64 0.22.1", 1817 | "bytes", 1818 | "futures-channel", 1819 | "futures-core", 1820 | "futures-util", 1821 | "http", 1822 | "http-body", 1823 | "http-body-util", 1824 | "hyper", 1825 | "hyper-rustls", 1826 | "hyper-util", 1827 | "js-sys", 1828 | "log", 1829 | "percent-encoding", 1830 | "pin-project-lite", 1831 | "quinn", 1832 | "rustls", 1833 | "rustls-pki-types", 1834 | "serde", 1835 | "serde_json", 1836 | "serde_urlencoded", 1837 | "sync_wrapper", 1838 | "tokio", 1839 | "tokio-rustls", 1840 | "tokio-util", 1841 | "tower", 1842 | "tower-http", 1843 | "tower-service", 1844 | "url", 1845 | "wasm-bindgen", 1846 | "wasm-bindgen-futures", 1847 | "web-sys", 1848 | "webpki-roots", 1849 | ] 1850 | 1851 | [[package]] 1852 | name = "ring" 1853 | version = "0.17.8" 1854 | source = "git+https://gitlab.redox-os.org/redox-os/ring.git?branch=redox-0.17.8#fce20f12b6aad164a1a7e13ae1dcb46422b171c0" 1855 | dependencies = [ 1856 | "cc", 1857 | "cfg-if 1.0.3", 1858 | "getrandom 0.2.16", 1859 | "libc", 1860 | "spin", 1861 | "untrusted", 1862 | "windows-sys 0.52.0", 1863 | ] 1864 | 1865 | [[package]] 1866 | name = "rust-argon2" 1867 | version = "0.8.3" 1868 | source = "registry+https://github.com/rust-lang/crates.io-index" 1869 | checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" 1870 | dependencies = [ 1871 | "base64 0.13.1", 1872 | "blake2b_simd", 1873 | "constant_time_eq", 1874 | "crossbeam-utils", 1875 | ] 1876 | 1877 | [[package]] 1878 | name = "rustc-demangle" 1879 | version = "0.1.26" 1880 | source = "registry+https://github.com/rust-lang/crates.io-index" 1881 | checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" 1882 | 1883 | [[package]] 1884 | name = "rustc-hash" 1885 | version = "2.1.1" 1886 | source = "registry+https://github.com/rust-lang/crates.io-index" 1887 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 1888 | 1889 | [[package]] 1890 | name = "rustc_version" 1891 | version = "0.4.1" 1892 | source = "registry+https://github.com/rust-lang/crates.io-index" 1893 | checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" 1894 | dependencies = [ 1895 | "semver", 1896 | ] 1897 | 1898 | [[package]] 1899 | name = "rustls" 1900 | version = "0.23.32" 1901 | source = "registry+https://github.com/rust-lang/crates.io-index" 1902 | checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" 1903 | dependencies = [ 1904 | "once_cell", 1905 | "ring", 1906 | "rustls-pki-types", 1907 | "rustls-webpki", 1908 | "subtle", 1909 | "zeroize", 1910 | ] 1911 | 1912 | [[package]] 1913 | name = "rustls-pki-types" 1914 | version = "1.12.0" 1915 | source = "registry+https://github.com/rust-lang/crates.io-index" 1916 | checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" 1917 | dependencies = [ 1918 | "web-time", 1919 | "zeroize", 1920 | ] 1921 | 1922 | [[package]] 1923 | name = "rustls-webpki" 1924 | version = "0.103.6" 1925 | source = "registry+https://github.com/rust-lang/crates.io-index" 1926 | checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" 1927 | dependencies = [ 1928 | "ring", 1929 | "rustls-pki-types", 1930 | "untrusted", 1931 | ] 1932 | 1933 | [[package]] 1934 | name = "rustversion" 1935 | version = "1.0.22" 1936 | source = "registry+https://github.com/rust-lang/crates.io-index" 1937 | checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 1938 | 1939 | [[package]] 1940 | name = "ryu" 1941 | version = "1.0.20" 1942 | source = "registry+https://github.com/rust-lang/crates.io-index" 1943 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 1944 | 1945 | [[package]] 1946 | name = "salsa20" 1947 | version = "0.10.2" 1948 | source = "registry+https://github.com/rust-lang/crates.io-index" 1949 | checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" 1950 | dependencies = [ 1951 | "cipher", 1952 | ] 1953 | 1954 | [[package]] 1955 | name = "same-file" 1956 | version = "1.0.6" 1957 | source = "registry+https://github.com/rust-lang/crates.io-index" 1958 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1959 | dependencies = [ 1960 | "winapi-util", 1961 | ] 1962 | 1963 | [[package]] 1964 | name = "seahash" 1965 | version = "4.1.0" 1966 | source = "registry+https://github.com/rust-lang/crates.io-index" 1967 | checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" 1968 | 1969 | [[package]] 1970 | name = "seckey" 1971 | version = "0.11.2" 1972 | source = "registry+https://github.com/rust-lang/crates.io-index" 1973 | checksum = "33b371a3e46636d13277af1daacbecb6f5acbe653bd378a4822ecd1c67790fbb" 1974 | dependencies = [ 1975 | "getrandom 0.1.16", 1976 | "memsec", 1977 | ] 1978 | 1979 | [[package]] 1980 | name = "semver" 1981 | version = "1.0.27" 1982 | source = "registry+https://github.com/rust-lang/crates.io-index" 1983 | checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" 1984 | 1985 | [[package]] 1986 | name = "serde" 1987 | version = "1.0.227" 1988 | source = "registry+https://github.com/rust-lang/crates.io-index" 1989 | checksum = "80ece43fc6fbed4eb5392ab50c07334d3e577cbf40997ee896fe7af40bba4245" 1990 | dependencies = [ 1991 | "serde_core", 1992 | "serde_derive", 1993 | ] 1994 | 1995 | [[package]] 1996 | name = "serde_core" 1997 | version = "1.0.227" 1998 | source = "registry+https://github.com/rust-lang/crates.io-index" 1999 | checksum = "7a576275b607a2c86ea29e410193df32bc680303c82f31e275bbfcafe8b33be5" 2000 | dependencies = [ 2001 | "serde_derive", 2002 | ] 2003 | 2004 | [[package]] 2005 | name = "serde_derive" 2006 | version = "1.0.227" 2007 | source = "registry+https://github.com/rust-lang/crates.io-index" 2008 | checksum = "51e694923b8824cf0e9b382adf0f60d4e05f348f357b38833a3fa5ed7c2ede04" 2009 | dependencies = [ 2010 | "proc-macro2", 2011 | "quote", 2012 | "syn", 2013 | ] 2014 | 2015 | [[package]] 2016 | name = "serde_json" 2017 | version = "1.0.145" 2018 | source = "registry+https://github.com/rust-lang/crates.io-index" 2019 | checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" 2020 | dependencies = [ 2021 | "itoa", 2022 | "memchr", 2023 | "ryu", 2024 | "serde", 2025 | "serde_core", 2026 | ] 2027 | 2028 | [[package]] 2029 | name = "serde_spanned" 2030 | version = "0.6.9" 2031 | source = "registry+https://github.com/rust-lang/crates.io-index" 2032 | checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" 2033 | dependencies = [ 2034 | "serde", 2035 | ] 2036 | 2037 | [[package]] 2038 | name = "serde_urlencoded" 2039 | version = "0.7.1" 2040 | source = "registry+https://github.com/rust-lang/crates.io-index" 2041 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2042 | dependencies = [ 2043 | "form_urlencoded", 2044 | "itoa", 2045 | "ryu", 2046 | "serde", 2047 | ] 2048 | 2049 | [[package]] 2050 | name = "sha2" 2051 | version = "0.10.9" 2052 | source = "registry+https://github.com/rust-lang/crates.io-index" 2053 | checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" 2054 | dependencies = [ 2055 | "cfg-if 1.0.3", 2056 | "cpufeatures", 2057 | "digest 0.10.7", 2058 | ] 2059 | 2060 | [[package]] 2061 | name = "shlex" 2062 | version = "1.3.0" 2063 | source = "registry+https://github.com/rust-lang/crates.io-index" 2064 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 2065 | 2066 | [[package]] 2067 | name = "slab" 2068 | version = "0.4.11" 2069 | source = "registry+https://github.com/rust-lang/crates.io-index" 2070 | checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" 2071 | 2072 | [[package]] 2073 | name = "smallvec" 2074 | version = "1.15.1" 2075 | source = "registry+https://github.com/rust-lang/crates.io-index" 2076 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 2077 | 2078 | [[package]] 2079 | name = "socket2" 2080 | version = "0.6.0" 2081 | source = "registry+https://github.com/rust-lang/crates.io-index" 2082 | checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" 2083 | dependencies = [ 2084 | "libc", 2085 | "windows-sys 0.59.0", 2086 | ] 2087 | 2088 | [[package]] 2089 | name = "spin" 2090 | version = "0.9.8" 2091 | source = "registry+https://github.com/rust-lang/crates.io-index" 2092 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 2093 | 2094 | [[package]] 2095 | name = "stable_deref_trait" 2096 | version = "1.2.0" 2097 | source = "registry+https://github.com/rust-lang/crates.io-index" 2098 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 2099 | 2100 | [[package]] 2101 | name = "strsim" 2102 | version = "0.8.0" 2103 | source = "registry+https://github.com/rust-lang/crates.io-index" 2104 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 2105 | 2106 | [[package]] 2107 | name = "subtle" 2108 | version = "2.6.1" 2109 | source = "registry+https://github.com/rust-lang/crates.io-index" 2110 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 2111 | 2112 | [[package]] 2113 | name = "syn" 2114 | version = "2.0.106" 2115 | source = "registry+https://github.com/rust-lang/crates.io-index" 2116 | checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" 2117 | dependencies = [ 2118 | "proc-macro2", 2119 | "quote", 2120 | "unicode-ident", 2121 | ] 2122 | 2123 | [[package]] 2124 | name = "sync_wrapper" 2125 | version = "1.0.2" 2126 | source = "registry+https://github.com/rust-lang/crates.io-index" 2127 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 2128 | dependencies = [ 2129 | "futures-core", 2130 | ] 2131 | 2132 | [[package]] 2133 | name = "synstructure" 2134 | version = "0.13.2" 2135 | source = "registry+https://github.com/rust-lang/crates.io-index" 2136 | checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 2137 | dependencies = [ 2138 | "proc-macro2", 2139 | "quote", 2140 | "syn", 2141 | ] 2142 | 2143 | [[package]] 2144 | name = "termion" 2145 | version = "4.0.5" 2146 | source = "registry+https://github.com/rust-lang/crates.io-index" 2147 | checksum = "3669a69de26799d6321a5aa713f55f7e2cd37bd47be044b50f2acafc42c122bb" 2148 | dependencies = [ 2149 | "libc", 2150 | "libredox", 2151 | "numtoa", 2152 | "redox_termios", 2153 | ] 2154 | 2155 | [[package]] 2156 | name = "textwrap" 2157 | version = "0.11.0" 2158 | source = "registry+https://github.com/rust-lang/crates.io-index" 2159 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 2160 | dependencies = [ 2161 | "unicode-width 0.1.14", 2162 | ] 2163 | 2164 | [[package]] 2165 | name = "thiserror" 2166 | version = "1.0.69" 2167 | source = "registry+https://github.com/rust-lang/crates.io-index" 2168 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 2169 | dependencies = [ 2170 | "thiserror-impl 1.0.69", 2171 | ] 2172 | 2173 | [[package]] 2174 | name = "thiserror" 2175 | version = "2.0.16" 2176 | source = "registry+https://github.com/rust-lang/crates.io-index" 2177 | checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" 2178 | dependencies = [ 2179 | "thiserror-impl 2.0.16", 2180 | ] 2181 | 2182 | [[package]] 2183 | name = "thiserror-impl" 2184 | version = "1.0.69" 2185 | source = "registry+https://github.com/rust-lang/crates.io-index" 2186 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 2187 | dependencies = [ 2188 | "proc-macro2", 2189 | "quote", 2190 | "syn", 2191 | ] 2192 | 2193 | [[package]] 2194 | name = "thiserror-impl" 2195 | version = "2.0.16" 2196 | source = "registry+https://github.com/rust-lang/crates.io-index" 2197 | checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" 2198 | dependencies = [ 2199 | "proc-macro2", 2200 | "quote", 2201 | "syn", 2202 | ] 2203 | 2204 | [[package]] 2205 | name = "tinystr" 2206 | version = "0.8.1" 2207 | source = "registry+https://github.com/rust-lang/crates.io-index" 2208 | checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" 2209 | dependencies = [ 2210 | "displaydoc", 2211 | "zerovec", 2212 | ] 2213 | 2214 | [[package]] 2215 | name = "tinyvec" 2216 | version = "1.10.0" 2217 | source = "registry+https://github.com/rust-lang/crates.io-index" 2218 | checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" 2219 | dependencies = [ 2220 | "tinyvec_macros", 2221 | ] 2222 | 2223 | [[package]] 2224 | name = "tinyvec_macros" 2225 | version = "0.1.1" 2226 | source = "registry+https://github.com/rust-lang/crates.io-index" 2227 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 2228 | 2229 | [[package]] 2230 | name = "tokio" 2231 | version = "1.47.1" 2232 | source = "registry+https://github.com/rust-lang/crates.io-index" 2233 | checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" 2234 | dependencies = [ 2235 | "backtrace", 2236 | "bytes", 2237 | "io-uring", 2238 | "libc", 2239 | "mio", 2240 | "pin-project-lite", 2241 | "slab", 2242 | "socket2", 2243 | "windows-sys 0.59.0", 2244 | ] 2245 | 2246 | [[package]] 2247 | name = "tokio-rustls" 2248 | version = "0.26.4" 2249 | source = "registry+https://github.com/rust-lang/crates.io-index" 2250 | checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" 2251 | dependencies = [ 2252 | "rustls", 2253 | "tokio", 2254 | ] 2255 | 2256 | [[package]] 2257 | name = "tokio-util" 2258 | version = "0.7.16" 2259 | source = "registry+https://github.com/rust-lang/crates.io-index" 2260 | checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" 2261 | dependencies = [ 2262 | "bytes", 2263 | "futures-core", 2264 | "futures-sink", 2265 | "pin-project-lite", 2266 | "tokio", 2267 | ] 2268 | 2269 | [[package]] 2270 | name = "toml" 2271 | version = "0.8.23" 2272 | source = "registry+https://github.com/rust-lang/crates.io-index" 2273 | checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" 2274 | dependencies = [ 2275 | "serde", 2276 | "serde_spanned", 2277 | "toml_datetime", 2278 | "toml_edit", 2279 | ] 2280 | 2281 | [[package]] 2282 | name = "toml_datetime" 2283 | version = "0.6.11" 2284 | source = "registry+https://github.com/rust-lang/crates.io-index" 2285 | checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" 2286 | dependencies = [ 2287 | "serde", 2288 | ] 2289 | 2290 | [[package]] 2291 | name = "toml_edit" 2292 | version = "0.22.27" 2293 | source = "registry+https://github.com/rust-lang/crates.io-index" 2294 | checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" 2295 | dependencies = [ 2296 | "indexmap", 2297 | "serde", 2298 | "serde_spanned", 2299 | "toml_datetime", 2300 | "toml_write", 2301 | "winnow", 2302 | ] 2303 | 2304 | [[package]] 2305 | name = "toml_write" 2306 | version = "0.1.2" 2307 | source = "registry+https://github.com/rust-lang/crates.io-index" 2308 | checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" 2309 | 2310 | [[package]] 2311 | name = "tower" 2312 | version = "0.5.2" 2313 | source = "registry+https://github.com/rust-lang/crates.io-index" 2314 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 2315 | dependencies = [ 2316 | "futures-core", 2317 | "futures-util", 2318 | "pin-project-lite", 2319 | "sync_wrapper", 2320 | "tokio", 2321 | "tower-layer", 2322 | "tower-service", 2323 | ] 2324 | 2325 | [[package]] 2326 | name = "tower-http" 2327 | version = "0.6.6" 2328 | source = "registry+https://github.com/rust-lang/crates.io-index" 2329 | checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" 2330 | dependencies = [ 2331 | "bitflags 2.9.4", 2332 | "bytes", 2333 | "futures-util", 2334 | "http", 2335 | "http-body", 2336 | "iri-string", 2337 | "pin-project-lite", 2338 | "tower", 2339 | "tower-layer", 2340 | "tower-service", 2341 | ] 2342 | 2343 | [[package]] 2344 | name = "tower-layer" 2345 | version = "0.3.3" 2346 | source = "registry+https://github.com/rust-lang/crates.io-index" 2347 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 2348 | 2349 | [[package]] 2350 | name = "tower-service" 2351 | version = "0.3.3" 2352 | source = "registry+https://github.com/rust-lang/crates.io-index" 2353 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 2354 | 2355 | [[package]] 2356 | name = "tracing" 2357 | version = "0.1.41" 2358 | source = "registry+https://github.com/rust-lang/crates.io-index" 2359 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 2360 | dependencies = [ 2361 | "pin-project-lite", 2362 | "tracing-core", 2363 | ] 2364 | 2365 | [[package]] 2366 | name = "tracing-core" 2367 | version = "0.1.34" 2368 | source = "registry+https://github.com/rust-lang/crates.io-index" 2369 | checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" 2370 | dependencies = [ 2371 | "once_cell", 2372 | ] 2373 | 2374 | [[package]] 2375 | name = "try-lock" 2376 | version = "0.2.5" 2377 | source = "registry+https://github.com/rust-lang/crates.io-index" 2378 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2379 | 2380 | [[package]] 2381 | name = "typenum" 2382 | version = "1.18.0" 2383 | source = "registry+https://github.com/rust-lang/crates.io-index" 2384 | checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 2385 | 2386 | [[package]] 2387 | name = "unicode-ident" 2388 | version = "1.0.19" 2389 | source = "registry+https://github.com/rust-lang/crates.io-index" 2390 | checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" 2391 | 2392 | [[package]] 2393 | name = "unicode-width" 2394 | version = "0.1.14" 2395 | source = "registry+https://github.com/rust-lang/crates.io-index" 2396 | checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" 2397 | 2398 | [[package]] 2399 | name = "unicode-width" 2400 | version = "0.2.1" 2401 | source = "registry+https://github.com/rust-lang/crates.io-index" 2402 | checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" 2403 | 2404 | [[package]] 2405 | name = "untrusted" 2406 | version = "0.9.0" 2407 | source = "registry+https://github.com/rust-lang/crates.io-index" 2408 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 2409 | 2410 | [[package]] 2411 | name = "url" 2412 | version = "2.5.7" 2413 | source = "registry+https://github.com/rust-lang/crates.io-index" 2414 | checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" 2415 | dependencies = [ 2416 | "form_urlencoded", 2417 | "idna", 2418 | "percent-encoding", 2419 | "serde", 2420 | ] 2421 | 2422 | [[package]] 2423 | name = "utf8_iter" 2424 | version = "1.0.4" 2425 | source = "registry+https://github.com/rust-lang/crates.io-index" 2426 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2427 | 2428 | [[package]] 2429 | name = "utf8parse" 2430 | version = "0.2.2" 2431 | source = "registry+https://github.com/rust-lang/crates.io-index" 2432 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 2433 | 2434 | [[package]] 2435 | name = "uuid" 2436 | version = "1.18.1" 2437 | source = "registry+https://github.com/rust-lang/crates.io-index" 2438 | checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" 2439 | dependencies = [ 2440 | "getrandom 0.3.3", 2441 | "js-sys", 2442 | "wasm-bindgen", 2443 | ] 2444 | 2445 | [[package]] 2446 | name = "vec_map" 2447 | version = "0.8.2" 2448 | source = "registry+https://github.com/rust-lang/crates.io-index" 2449 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 2450 | 2451 | [[package]] 2452 | name = "version_check" 2453 | version = "0.9.5" 2454 | source = "registry+https://github.com/rust-lang/crates.io-index" 2455 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 2456 | 2457 | [[package]] 2458 | name = "walkdir" 2459 | version = "2.5.0" 2460 | source = "registry+https://github.com/rust-lang/crates.io-index" 2461 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 2462 | dependencies = [ 2463 | "same-file", 2464 | "winapi-util", 2465 | ] 2466 | 2467 | [[package]] 2468 | name = "want" 2469 | version = "0.3.1" 2470 | source = "registry+https://github.com/rust-lang/crates.io-index" 2471 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2472 | dependencies = [ 2473 | "try-lock", 2474 | ] 2475 | 2476 | [[package]] 2477 | name = "wasi" 2478 | version = "0.9.0+wasi-snapshot-preview1" 2479 | source = "registry+https://github.com/rust-lang/crates.io-index" 2480 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 2481 | 2482 | [[package]] 2483 | name = "wasi" 2484 | version = "0.11.1+wasi-snapshot-preview1" 2485 | source = "registry+https://github.com/rust-lang/crates.io-index" 2486 | checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 2487 | 2488 | [[package]] 2489 | name = "wasi" 2490 | version = "0.14.7+wasi-0.2.4" 2491 | source = "registry+https://github.com/rust-lang/crates.io-index" 2492 | checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" 2493 | dependencies = [ 2494 | "wasip2", 2495 | ] 2496 | 2497 | [[package]] 2498 | name = "wasip2" 2499 | version = "1.0.1+wasi-0.2.4" 2500 | source = "registry+https://github.com/rust-lang/crates.io-index" 2501 | checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" 2502 | dependencies = [ 2503 | "wit-bindgen", 2504 | ] 2505 | 2506 | [[package]] 2507 | name = "wasm-bindgen" 2508 | version = "0.2.104" 2509 | source = "registry+https://github.com/rust-lang/crates.io-index" 2510 | checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" 2511 | dependencies = [ 2512 | "cfg-if 1.0.3", 2513 | "once_cell", 2514 | "rustversion", 2515 | "wasm-bindgen-macro", 2516 | "wasm-bindgen-shared", 2517 | ] 2518 | 2519 | [[package]] 2520 | name = "wasm-bindgen-backend" 2521 | version = "0.2.104" 2522 | source = "registry+https://github.com/rust-lang/crates.io-index" 2523 | checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" 2524 | dependencies = [ 2525 | "bumpalo", 2526 | "log", 2527 | "proc-macro2", 2528 | "quote", 2529 | "syn", 2530 | "wasm-bindgen-shared", 2531 | ] 2532 | 2533 | [[package]] 2534 | name = "wasm-bindgen-futures" 2535 | version = "0.4.54" 2536 | source = "registry+https://github.com/rust-lang/crates.io-index" 2537 | checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" 2538 | dependencies = [ 2539 | "cfg-if 1.0.3", 2540 | "js-sys", 2541 | "once_cell", 2542 | "wasm-bindgen", 2543 | "web-sys", 2544 | ] 2545 | 2546 | [[package]] 2547 | name = "wasm-bindgen-macro" 2548 | version = "0.2.104" 2549 | source = "registry+https://github.com/rust-lang/crates.io-index" 2550 | checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" 2551 | dependencies = [ 2552 | "quote", 2553 | "wasm-bindgen-macro-support", 2554 | ] 2555 | 2556 | [[package]] 2557 | name = "wasm-bindgen-macro-support" 2558 | version = "0.2.104" 2559 | source = "registry+https://github.com/rust-lang/crates.io-index" 2560 | checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" 2561 | dependencies = [ 2562 | "proc-macro2", 2563 | "quote", 2564 | "syn", 2565 | "wasm-bindgen-backend", 2566 | "wasm-bindgen-shared", 2567 | ] 2568 | 2569 | [[package]] 2570 | name = "wasm-bindgen-shared" 2571 | version = "0.2.104" 2572 | source = "registry+https://github.com/rust-lang/crates.io-index" 2573 | checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" 2574 | dependencies = [ 2575 | "unicode-ident", 2576 | ] 2577 | 2578 | [[package]] 2579 | name = "web-sys" 2580 | version = "0.3.81" 2581 | source = "registry+https://github.com/rust-lang/crates.io-index" 2582 | checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" 2583 | dependencies = [ 2584 | "js-sys", 2585 | "wasm-bindgen", 2586 | ] 2587 | 2588 | [[package]] 2589 | name = "web-time" 2590 | version = "1.1.0" 2591 | source = "registry+https://github.com/rust-lang/crates.io-index" 2592 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 2593 | dependencies = [ 2594 | "js-sys", 2595 | "wasm-bindgen", 2596 | ] 2597 | 2598 | [[package]] 2599 | name = "webpki-roots" 2600 | version = "1.0.2" 2601 | source = "registry+https://github.com/rust-lang/crates.io-index" 2602 | checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" 2603 | dependencies = [ 2604 | "rustls-pki-types", 2605 | ] 2606 | 2607 | [[package]] 2608 | name = "winapi" 2609 | version = "0.3.9" 2610 | source = "registry+https://github.com/rust-lang/crates.io-index" 2611 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2612 | dependencies = [ 2613 | "winapi-i686-pc-windows-gnu", 2614 | "winapi-x86_64-pc-windows-gnu", 2615 | ] 2616 | 2617 | [[package]] 2618 | name = "winapi-i686-pc-windows-gnu" 2619 | version = "0.4.0" 2620 | source = "registry+https://github.com/rust-lang/crates.io-index" 2621 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2622 | 2623 | [[package]] 2624 | name = "winapi-util" 2625 | version = "0.1.11" 2626 | source = "registry+https://github.com/rust-lang/crates.io-index" 2627 | checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" 2628 | dependencies = [ 2629 | "windows-sys 0.52.0", 2630 | ] 2631 | 2632 | [[package]] 2633 | name = "winapi-x86_64-pc-windows-gnu" 2634 | version = "0.4.0" 2635 | source = "registry+https://github.com/rust-lang/crates.io-index" 2636 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2637 | 2638 | [[package]] 2639 | name = "windows-core" 2640 | version = "0.62.1" 2641 | source = "registry+https://github.com/rust-lang/crates.io-index" 2642 | checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9" 2643 | dependencies = [ 2644 | "windows-implement", 2645 | "windows-interface", 2646 | "windows-link", 2647 | "windows-result", 2648 | "windows-strings", 2649 | ] 2650 | 2651 | [[package]] 2652 | name = "windows-implement" 2653 | version = "0.60.1" 2654 | source = "registry+https://github.com/rust-lang/crates.io-index" 2655 | checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0" 2656 | dependencies = [ 2657 | "proc-macro2", 2658 | "quote", 2659 | "syn", 2660 | ] 2661 | 2662 | [[package]] 2663 | name = "windows-interface" 2664 | version = "0.59.2" 2665 | source = "registry+https://github.com/rust-lang/crates.io-index" 2666 | checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5" 2667 | dependencies = [ 2668 | "proc-macro2", 2669 | "quote", 2670 | "syn", 2671 | ] 2672 | 2673 | [[package]] 2674 | name = "windows-link" 2675 | version = "0.2.0" 2676 | source = "registry+https://github.com/rust-lang/crates.io-index" 2677 | checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" 2678 | 2679 | [[package]] 2680 | name = "windows-result" 2681 | version = "0.4.0" 2682 | source = "registry+https://github.com/rust-lang/crates.io-index" 2683 | checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" 2684 | dependencies = [ 2685 | "windows-link", 2686 | ] 2687 | 2688 | [[package]] 2689 | name = "windows-strings" 2690 | version = "0.5.0" 2691 | source = "registry+https://github.com/rust-lang/crates.io-index" 2692 | checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" 2693 | dependencies = [ 2694 | "windows-link", 2695 | ] 2696 | 2697 | [[package]] 2698 | name = "windows-sys" 2699 | version = "0.45.0" 2700 | source = "registry+https://github.com/rust-lang/crates.io-index" 2701 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 2702 | dependencies = [ 2703 | "windows-targets 0.42.2", 2704 | ] 2705 | 2706 | [[package]] 2707 | name = "windows-sys" 2708 | version = "0.52.0" 2709 | source = "registry+https://github.com/rust-lang/crates.io-index" 2710 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2711 | dependencies = [ 2712 | "windows-targets 0.52.6", 2713 | ] 2714 | 2715 | [[package]] 2716 | name = "windows-sys" 2717 | version = "0.59.0" 2718 | source = "registry+https://github.com/rust-lang/crates.io-index" 2719 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 2720 | dependencies = [ 2721 | "windows-targets 0.52.6", 2722 | ] 2723 | 2724 | [[package]] 2725 | name = "windows-sys" 2726 | version = "0.60.2" 2727 | source = "registry+https://github.com/rust-lang/crates.io-index" 2728 | checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 2729 | dependencies = [ 2730 | "windows-targets 0.53.4", 2731 | ] 2732 | 2733 | [[package]] 2734 | name = "windows-targets" 2735 | version = "0.42.2" 2736 | source = "registry+https://github.com/rust-lang/crates.io-index" 2737 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 2738 | dependencies = [ 2739 | "windows_aarch64_gnullvm 0.42.2", 2740 | "windows_aarch64_msvc 0.42.2", 2741 | "windows_i686_gnu 0.42.2", 2742 | "windows_i686_msvc 0.42.2", 2743 | "windows_x86_64_gnu 0.42.2", 2744 | "windows_x86_64_gnullvm 0.42.2", 2745 | "windows_x86_64_msvc 0.42.2", 2746 | ] 2747 | 2748 | [[package]] 2749 | name = "windows-targets" 2750 | version = "0.52.6" 2751 | source = "registry+https://github.com/rust-lang/crates.io-index" 2752 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2753 | dependencies = [ 2754 | "windows_aarch64_gnullvm 0.52.6", 2755 | "windows_aarch64_msvc 0.52.6", 2756 | "windows_i686_gnu 0.52.6", 2757 | "windows_i686_gnullvm 0.52.6", 2758 | "windows_i686_msvc 0.52.6", 2759 | "windows_x86_64_gnu 0.52.6", 2760 | "windows_x86_64_gnullvm 0.52.6", 2761 | "windows_x86_64_msvc 0.52.6", 2762 | ] 2763 | 2764 | [[package]] 2765 | name = "windows-targets" 2766 | version = "0.53.4" 2767 | source = "registry+https://github.com/rust-lang/crates.io-index" 2768 | checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" 2769 | dependencies = [ 2770 | "windows-link", 2771 | "windows_aarch64_gnullvm 0.53.0", 2772 | "windows_aarch64_msvc 0.53.0", 2773 | "windows_i686_gnu 0.53.0", 2774 | "windows_i686_gnullvm 0.53.0", 2775 | "windows_i686_msvc 0.53.0", 2776 | "windows_x86_64_gnu 0.53.0", 2777 | "windows_x86_64_gnullvm 0.53.0", 2778 | "windows_x86_64_msvc 0.53.0", 2779 | ] 2780 | 2781 | [[package]] 2782 | name = "windows_aarch64_gnullvm" 2783 | version = "0.42.2" 2784 | source = "registry+https://github.com/rust-lang/crates.io-index" 2785 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 2786 | 2787 | [[package]] 2788 | name = "windows_aarch64_gnullvm" 2789 | version = "0.52.6" 2790 | source = "registry+https://github.com/rust-lang/crates.io-index" 2791 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2792 | 2793 | [[package]] 2794 | name = "windows_aarch64_gnullvm" 2795 | version = "0.53.0" 2796 | source = "registry+https://github.com/rust-lang/crates.io-index" 2797 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 2798 | 2799 | [[package]] 2800 | name = "windows_aarch64_msvc" 2801 | version = "0.42.2" 2802 | source = "registry+https://github.com/rust-lang/crates.io-index" 2803 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 2804 | 2805 | [[package]] 2806 | name = "windows_aarch64_msvc" 2807 | version = "0.52.6" 2808 | source = "registry+https://github.com/rust-lang/crates.io-index" 2809 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2810 | 2811 | [[package]] 2812 | name = "windows_aarch64_msvc" 2813 | version = "0.53.0" 2814 | source = "registry+https://github.com/rust-lang/crates.io-index" 2815 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 2816 | 2817 | [[package]] 2818 | name = "windows_i686_gnu" 2819 | version = "0.42.2" 2820 | source = "registry+https://github.com/rust-lang/crates.io-index" 2821 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 2822 | 2823 | [[package]] 2824 | name = "windows_i686_gnu" 2825 | version = "0.52.6" 2826 | source = "registry+https://github.com/rust-lang/crates.io-index" 2827 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2828 | 2829 | [[package]] 2830 | name = "windows_i686_gnu" 2831 | version = "0.53.0" 2832 | source = "registry+https://github.com/rust-lang/crates.io-index" 2833 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 2834 | 2835 | [[package]] 2836 | name = "windows_i686_gnullvm" 2837 | version = "0.52.6" 2838 | source = "registry+https://github.com/rust-lang/crates.io-index" 2839 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2840 | 2841 | [[package]] 2842 | name = "windows_i686_gnullvm" 2843 | version = "0.53.0" 2844 | source = "registry+https://github.com/rust-lang/crates.io-index" 2845 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 2846 | 2847 | [[package]] 2848 | name = "windows_i686_msvc" 2849 | version = "0.42.2" 2850 | source = "registry+https://github.com/rust-lang/crates.io-index" 2851 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 2852 | 2853 | [[package]] 2854 | name = "windows_i686_msvc" 2855 | version = "0.52.6" 2856 | source = "registry+https://github.com/rust-lang/crates.io-index" 2857 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2858 | 2859 | [[package]] 2860 | name = "windows_i686_msvc" 2861 | version = "0.53.0" 2862 | source = "registry+https://github.com/rust-lang/crates.io-index" 2863 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 2864 | 2865 | [[package]] 2866 | name = "windows_x86_64_gnu" 2867 | version = "0.42.2" 2868 | source = "registry+https://github.com/rust-lang/crates.io-index" 2869 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 2870 | 2871 | [[package]] 2872 | name = "windows_x86_64_gnu" 2873 | version = "0.52.6" 2874 | source = "registry+https://github.com/rust-lang/crates.io-index" 2875 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2876 | 2877 | [[package]] 2878 | name = "windows_x86_64_gnu" 2879 | version = "0.53.0" 2880 | source = "registry+https://github.com/rust-lang/crates.io-index" 2881 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 2882 | 2883 | [[package]] 2884 | name = "windows_x86_64_gnullvm" 2885 | version = "0.42.2" 2886 | source = "registry+https://github.com/rust-lang/crates.io-index" 2887 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 2888 | 2889 | [[package]] 2890 | name = "windows_x86_64_gnullvm" 2891 | version = "0.52.6" 2892 | source = "registry+https://github.com/rust-lang/crates.io-index" 2893 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2894 | 2895 | [[package]] 2896 | name = "windows_x86_64_gnullvm" 2897 | version = "0.53.0" 2898 | source = "registry+https://github.com/rust-lang/crates.io-index" 2899 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 2900 | 2901 | [[package]] 2902 | name = "windows_x86_64_msvc" 2903 | version = "0.42.2" 2904 | source = "registry+https://github.com/rust-lang/crates.io-index" 2905 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 2906 | 2907 | [[package]] 2908 | name = "windows_x86_64_msvc" 2909 | version = "0.52.6" 2910 | source = "registry+https://github.com/rust-lang/crates.io-index" 2911 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2912 | 2913 | [[package]] 2914 | name = "windows_x86_64_msvc" 2915 | version = "0.53.0" 2916 | source = "registry+https://github.com/rust-lang/crates.io-index" 2917 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 2918 | 2919 | [[package]] 2920 | name = "winnow" 2921 | version = "0.7.13" 2922 | source = "registry+https://github.com/rust-lang/crates.io-index" 2923 | checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" 2924 | dependencies = [ 2925 | "memchr", 2926 | ] 2927 | 2928 | [[package]] 2929 | name = "wit-bindgen" 2930 | version = "0.46.0" 2931 | source = "registry+https://github.com/rust-lang/crates.io-index" 2932 | checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" 2933 | 2934 | [[package]] 2935 | name = "writeable" 2936 | version = "0.6.1" 2937 | source = "registry+https://github.com/rust-lang/crates.io-index" 2938 | checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" 2939 | 2940 | [[package]] 2941 | name = "xts-mode" 2942 | version = "0.5.1" 2943 | source = "registry+https://github.com/rust-lang/crates.io-index" 2944 | checksum = "09cbddb7545ca0b9ffa7bdc653e8743303e1712687a6918ced25f2cdbed42520" 2945 | dependencies = [ 2946 | "byteorder", 2947 | "cipher", 2948 | ] 2949 | 2950 | [[package]] 2951 | name = "yoke" 2952 | version = "0.8.0" 2953 | source = "registry+https://github.com/rust-lang/crates.io-index" 2954 | checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" 2955 | dependencies = [ 2956 | "serde", 2957 | "stable_deref_trait", 2958 | "yoke-derive", 2959 | "zerofrom", 2960 | ] 2961 | 2962 | [[package]] 2963 | name = "yoke-derive" 2964 | version = "0.8.0" 2965 | source = "registry+https://github.com/rust-lang/crates.io-index" 2966 | checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" 2967 | dependencies = [ 2968 | "proc-macro2", 2969 | "quote", 2970 | "syn", 2971 | "synstructure", 2972 | ] 2973 | 2974 | [[package]] 2975 | name = "zerocopy" 2976 | version = "0.7.35" 2977 | source = "registry+https://github.com/rust-lang/crates.io-index" 2978 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 2979 | dependencies = [ 2980 | "byteorder", 2981 | "zerocopy-derive 0.7.35", 2982 | ] 2983 | 2984 | [[package]] 2985 | name = "zerocopy" 2986 | version = "0.8.27" 2987 | source = "registry+https://github.com/rust-lang/crates.io-index" 2988 | checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" 2989 | dependencies = [ 2990 | "zerocopy-derive 0.8.27", 2991 | ] 2992 | 2993 | [[package]] 2994 | name = "zerocopy-derive" 2995 | version = "0.7.35" 2996 | source = "registry+https://github.com/rust-lang/crates.io-index" 2997 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 2998 | dependencies = [ 2999 | "proc-macro2", 3000 | "quote", 3001 | "syn", 3002 | ] 3003 | 3004 | [[package]] 3005 | name = "zerocopy-derive" 3006 | version = "0.8.27" 3007 | source = "registry+https://github.com/rust-lang/crates.io-index" 3008 | checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" 3009 | dependencies = [ 3010 | "proc-macro2", 3011 | "quote", 3012 | "syn", 3013 | ] 3014 | 3015 | [[package]] 3016 | name = "zerofrom" 3017 | version = "0.1.6" 3018 | source = "registry+https://github.com/rust-lang/crates.io-index" 3019 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 3020 | dependencies = [ 3021 | "zerofrom-derive", 3022 | ] 3023 | 3024 | [[package]] 3025 | name = "zerofrom-derive" 3026 | version = "0.1.6" 3027 | source = "registry+https://github.com/rust-lang/crates.io-index" 3028 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 3029 | dependencies = [ 3030 | "proc-macro2", 3031 | "quote", 3032 | "syn", 3033 | "synstructure", 3034 | ] 3035 | 3036 | [[package]] 3037 | name = "zeroize" 3038 | version = "1.8.1" 3039 | source = "registry+https://github.com/rust-lang/crates.io-index" 3040 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 3041 | dependencies = [ 3042 | "zeroize_derive", 3043 | ] 3044 | 3045 | [[package]] 3046 | name = "zeroize_derive" 3047 | version = "1.4.2" 3048 | source = "registry+https://github.com/rust-lang/crates.io-index" 3049 | checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" 3050 | dependencies = [ 3051 | "proc-macro2", 3052 | "quote", 3053 | "syn", 3054 | ] 3055 | 3056 | [[package]] 3057 | name = "zerotrie" 3058 | version = "0.2.2" 3059 | source = "registry+https://github.com/rust-lang/crates.io-index" 3060 | checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" 3061 | dependencies = [ 3062 | "displaydoc", 3063 | "yoke", 3064 | "zerofrom", 3065 | ] 3066 | 3067 | [[package]] 3068 | name = "zerovec" 3069 | version = "0.11.4" 3070 | source = "registry+https://github.com/rust-lang/crates.io-index" 3071 | checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" 3072 | dependencies = [ 3073 | "yoke", 3074 | "zerofrom", 3075 | "zerovec-derive", 3076 | ] 3077 | 3078 | [[package]] 3079 | name = "zerovec-derive" 3080 | version = "0.11.1" 3081 | source = "registry+https://github.com/rust-lang/crates.io-index" 3082 | checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" 3083 | dependencies = [ 3084 | "proc-macro2", 3085 | "quote", 3086 | "syn", 3087 | ] 3088 | --------------------------------------------------------------------------------