Implement uuidgen
Implement uuidgen as a wrapper over the `uuid` crate.
This commit is contained in:
128
Cargo.lock
generated
128
Cargo.lock
generated
@@ -76,6 +76,15 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@@ -123,6 +132,12 @@ version = "3.17.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.19"
|
version = "1.2.19"
|
||||||
@@ -391,7 +406,7 @@ dependencies = [
|
|||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-core 0.57.0",
|
"windows-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -505,6 +520,15 @@ version = "2.7.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -521,6 +545,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"libc",
|
"libc",
|
||||||
|
"memoffset",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -934,6 +959,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1_smol"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@@ -1166,7 +1197,9 @@ dependencies = [
|
|||||||
"uu_renice",
|
"uu_renice",
|
||||||
"uu_rev",
|
"uu_rev",
|
||||||
"uu_setsid",
|
"uu_setsid",
|
||||||
|
"uu_uuidgen",
|
||||||
"uucore",
|
"uucore",
|
||||||
|
"uuid",
|
||||||
"xattr",
|
"xattr",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1331,6 +1364,19 @@ dependencies = [
|
|||||||
"uucore",
|
"uucore",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uu_uuidgen"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"nix",
|
||||||
|
"rand 0.9.1",
|
||||||
|
"thiserror",
|
||||||
|
"uucore",
|
||||||
|
"uuid",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uucore"
|
name = "uucore"
|
||||||
version = "0.0.30"
|
version = "0.0.30"
|
||||||
@@ -1369,6 +1415,29 @@ version = "0.0.30"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bb6d972f580f8223cb7052d8580aea2b7061e368cf476de32ea9457b19459ed"
|
checksum = "0bb6d972f580f8223cb7052d8580aea2b7061e368cf476de32ea9457b19459ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
|
||||||
|
dependencies = [
|
||||||
|
"atomic",
|
||||||
|
"getrandom",
|
||||||
|
"md-5",
|
||||||
|
"rand 0.9.1",
|
||||||
|
"sha1_smol",
|
||||||
|
"uuid-rng-internal",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid-rng-internal"
|
||||||
|
version = "1.16.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9376f53b15ed85851c10175b5e45f0af556b4853ff3fe335080b337e3828981e"
|
||||||
|
dependencies = [
|
||||||
|
"rand 0.9.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
@@ -1499,7 +1568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
|
checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-collections",
|
"windows-collections",
|
||||||
"windows-core 0.61.0",
|
"windows-core",
|
||||||
"windows-future",
|
"windows-future",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
"windows-numerics",
|
"windows-numerics",
|
||||||
@@ -1511,19 +1580,7 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
|
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-core 0.61.0",
|
"windows-core",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-core"
|
|
||||||
version = "0.57.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
|
|
||||||
dependencies = [
|
|
||||||
"windows-implement 0.57.0",
|
|
||||||
"windows-interface 0.57.0",
|
|
||||||
"windows-result 0.1.2",
|
|
||||||
"windows-targets 0.52.6",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1532,10 +1589,10 @@ version = "0.61.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-implement 0.60.0",
|
"windows-implement",
|
||||||
"windows-interface 0.59.1",
|
"windows-interface",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
"windows-result 0.3.2",
|
"windows-result",
|
||||||
"windows-strings",
|
"windows-strings",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1545,21 +1602,10 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
|
checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-core 0.61.0",
|
"windows-core",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-implement"
|
|
||||||
version = "0.57.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-implement"
|
name = "windows-implement"
|
||||||
version = "0.60.0"
|
version = "0.60.0"
|
||||||
@@ -1571,17 +1617,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-interface"
|
|
||||||
version = "0.57.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-interface"
|
name = "windows-interface"
|
||||||
version = "0.59.1"
|
version = "0.59.1"
|
||||||
@@ -1605,19 +1640,10 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-core 0.61.0",
|
"windows-core",
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-result"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets 0.52.6",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-result"
|
name = "windows-result"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ feat_common_core = [
|
|||||||
"renice",
|
"renice",
|
||||||
"rev",
|
"rev",
|
||||||
"setsid",
|
"setsid",
|
||||||
|
"uuidgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
@@ -69,6 +70,8 @@ tempfile = "3.9.0"
|
|||||||
textwrap = { version = "0.16.0", features = ["terminal_size"] }
|
textwrap = { version = "0.16.0", features = ["terminal_size"] }
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
uucore = "0.0.30"
|
uucore = "0.0.30"
|
||||||
|
uuid = { version = "1.16.0", features = ["rng-rand"] }
|
||||||
|
windows = { version = "0.61.1" }
|
||||||
xattr = "1.3.1"
|
xattr = "1.3.1"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@@ -99,6 +102,7 @@ mountpoint = { optional = true, version = "0.0.1", package = "uu_mountpoint", pa
|
|||||||
renice = { optional = true, version = "0.0.1", package = "uu_renice", path = "src/uu/renice" }
|
renice = { optional = true, version = "0.0.1", package = "uu_renice", path = "src/uu/renice" }
|
||||||
rev = { optional = true, version = "0.0.1", package = "uu_rev", path = "src/uu/rev" }
|
rev = { optional = true, version = "0.0.1", package = "uu_rev", path = "src/uu/rev" }
|
||||||
setsid = { optional = true, version = "0.0.1", package = "uu_setsid", path ="src/uu/setsid" }
|
setsid = { optional = true, version = "0.0.1", package = "uu_setsid", path ="src/uu/setsid" }
|
||||||
|
uuidgen = { optional = true, version = "0.0.1", package = "uu_uuidgen", path ="src/uu/uuidgen" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
# dmesg test require fixed-boot-time feature turned on.
|
# dmesg test require fixed-boot-time feature turned on.
|
||||||
@@ -109,6 +113,7 @@ rand = { workspace = true }
|
|||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
uucore = { workspace = true, features = ["entries", "process", "signals"] }
|
uucore = { workspace = true, features = ["entries", "process", "signals"] }
|
||||||
|
uuid = { workspace = true }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dev-dependencies]
|
[target.'cfg(unix)'.dev-dependencies]
|
||||||
nix = { workspace = true, features = ["term"] }
|
nix = { workspace = true, features = ["term"] }
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ First, reimplement the most important tools from util-linux:
|
|||||||
- `ldattach`: Attaches line discipline to a serial line.
|
- `ldattach`: Attaches line discipline to a serial line.
|
||||||
- `readprofile`: Reads kernel profiling info.
|
- `readprofile`: Reads kernel profiling info.
|
||||||
- `i386, linux32, linux64, x86_64`: Set personality flags for execution environment.
|
- `i386, linux32, linux64, x86_64`: Set personality flags for execution environment.
|
||||||
|
- `uuidgen`: Generate different types of UUID.
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
* /bin/more is already implemented in https://github.com/uutils/coreutils
|
* /bin/more is already implemented in https://github.com/uutils/coreutils
|
||||||
|
|||||||
24
src/uu/uuidgen/Cargo.toml
Normal file
24
src/uu/uuidgen/Cargo.toml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
[package]
|
||||||
|
name = "uu_uuidgen"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "src/uuidgen.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "uuidgen"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { workspace = true }
|
||||||
|
rand = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
|
uucore = { workspace = true }
|
||||||
|
uuid = { workspace = true, features = ["v1", "v3", "v4", "v5"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
windows = { workspace = true, features = ["Win32_NetworkManagement_IpHelper", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock"] }
|
||||||
|
|
||||||
|
[target.'cfg(all(target_family = "unix", not(target_os = "redox")))'.dependencies]
|
||||||
|
nix = { workspace = true, features = ["net"] }
|
||||||
1
src/uu/uuidgen/src/main.rs
Normal file
1
src/uu/uuidgen/src/main.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uucore::bin!(uu_uuidgen);
|
||||||
209
src/uu/uuidgen/src/uuidgen.rs
Normal file
209
src/uu/uuidgen/src/uuidgen.rs
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
// This file is part of the uutils util-linux package.
|
||||||
|
//
|
||||||
|
// For the full copyright and license information, please view the LICENSE
|
||||||
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use windows::Win32::{
|
||||||
|
Foundation::{ERROR_BUFFER_OVERFLOW, ERROR_SUCCESS},
|
||||||
|
NetworkManagement::IpHelper::{
|
||||||
|
GetAdaptersAddresses, GAA_FLAG_SKIP_ANYCAST, GAA_FLAG_SKIP_DNS_SERVER,
|
||||||
|
GAA_FLAG_SKIP_FRIENDLY_NAME, GAA_FLAG_SKIP_MULTICAST, GAA_FLAG_SKIP_UNICAST,
|
||||||
|
IP_ADAPTER_ADDRESSES_LH,
|
||||||
|
},
|
||||||
|
Networking::WinSock::AF_UNSPEC,
|
||||||
|
};
|
||||||
|
|
||||||
|
use clap::{crate_version, Arg, ArgAction, ArgGroup, Command};
|
||||||
|
|
||||||
|
#[cfg(all(target_family = "unix", not(target_os = "redox")))]
|
||||||
|
use nix::ifaddrs::getifaddrs;
|
||||||
|
use uucore::{
|
||||||
|
error::{UResult, USimpleError},
|
||||||
|
format_usage, help_about, help_usage,
|
||||||
|
};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
const ABOUT: &str = help_about!("uuidgen.md");
|
||||||
|
const USAGE: &str = help_usage!("uuidgen.md");
|
||||||
|
|
||||||
|
#[uucore::main]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
let args = uu_app().try_get_matches_from_mut(args)?;
|
||||||
|
|
||||||
|
let md5 = args.get_flag(options::MD5);
|
||||||
|
let sha1 = args.get_flag(options::SHA1);
|
||||||
|
|
||||||
|
let namespace = args.get_one(options::NAMESPACE);
|
||||||
|
let name: Option<&String> = args.get_one(options::NAME);
|
||||||
|
|
||||||
|
// https://github.com/clap-rs/clap/issues/1537
|
||||||
|
if !(md5 || sha1) && (namespace.is_some() || name.is_some()) {
|
||||||
|
return Err(USimpleError::new(
|
||||||
|
1,
|
||||||
|
"--namespace and --name arguments require either --md5 or --sha1",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.get_flag(options::TIME) {
|
||||||
|
let node_id = get_node_id().unwrap_or_else(|| {
|
||||||
|
let mut default: [u8; 6] = rand::random();
|
||||||
|
default[0] |= 0x01;
|
||||||
|
default
|
||||||
|
});
|
||||||
|
println!("{:?}", Uuid::now_v1(&node_id));
|
||||||
|
} else if md5 || sha1 {
|
||||||
|
let f = if md5 { Uuid::new_v3 } else { Uuid::new_v5 };
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"{:?}",
|
||||||
|
f(
|
||||||
|
namespace.expect("namespace arg to be set"),
|
||||||
|
name.expect("name to be set").as_bytes()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Random is the default
|
||||||
|
println!("{}", Uuid::new_v4());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uu_app() -> Command {
|
||||||
|
let all_uuid_types = [options::RANDOM, options::TIME, options::MD5, options::SHA1];
|
||||||
|
|
||||||
|
Command::new(uucore::util_name())
|
||||||
|
.version(crate_version!())
|
||||||
|
.about(ABOUT)
|
||||||
|
.override_usage(format_usage(USAGE))
|
||||||
|
.infer_long_args(true)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::RANDOM)
|
||||||
|
.short('r')
|
||||||
|
.long(options::RANDOM)
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("generate random UUID (v4)"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::TIME)
|
||||||
|
.short('t')
|
||||||
|
.long(options::TIME)
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("generate time UUID (v1)"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::NAMESPACE)
|
||||||
|
.short('n')
|
||||||
|
.long(options::NAMESPACE)
|
||||||
|
.action(ArgAction::Set)
|
||||||
|
.value_parser(namespace_from_str)
|
||||||
|
.help("namespace for md5/sha1 - one of: @dns @url @oid @x500"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::NAME)
|
||||||
|
.short('N')
|
||||||
|
.long(options::NAME)
|
||||||
|
.action(ArgAction::Set)
|
||||||
|
.help("name for md5/sha1"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::MD5)
|
||||||
|
.short('m')
|
||||||
|
.long(options::MD5)
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.requires_all([options::NAMESPACE, options::NAME])
|
||||||
|
.help("generate md5 UUID (v3)"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::SHA1)
|
||||||
|
.short('s')
|
||||||
|
.long(options::SHA1)
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.requires_all([options::NAMESPACE, options::NAME])
|
||||||
|
.help("generate sha1 UUID (v5)"),
|
||||||
|
)
|
||||||
|
.group(ArgGroup::new("mode").args(all_uuid_types).multiple(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn namespace_from_str(s: &str) -> Result<Uuid, USimpleError> {
|
||||||
|
match s {
|
||||||
|
"@dns" => Ok(Uuid::NAMESPACE_DNS),
|
||||||
|
"@url" => Ok(Uuid::NAMESPACE_URL),
|
||||||
|
"@oid" => Ok(Uuid::NAMESPACE_OID),
|
||||||
|
"@x500" => Ok(Uuid::NAMESPACE_X500),
|
||||||
|
_ => Err(USimpleError {
|
||||||
|
code: 1,
|
||||||
|
message: format!("Invalid namespace {}.", s),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod options {
|
||||||
|
pub const RANDOM: &str = "random";
|
||||||
|
pub const TIME: &str = "time";
|
||||||
|
pub const MD5: &str = "md5";
|
||||||
|
pub const SHA1: &str = "sha1";
|
||||||
|
pub const NAMESPACE: &str = "namespace";
|
||||||
|
pub const NAME: &str = "name";
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn get_node_id() -> Option<[u8; 6]> {
|
||||||
|
unsafe {
|
||||||
|
// Skip everything we can - we are only interested in PhysicalAddress
|
||||||
|
let flags = GAA_FLAG_SKIP_UNICAST
|
||||||
|
| GAA_FLAG_SKIP_ANYCAST
|
||||||
|
| GAA_FLAG_SKIP_MULTICAST
|
||||||
|
| GAA_FLAG_SKIP_DNS_SERVER
|
||||||
|
| GAA_FLAG_SKIP_FRIENDLY_NAME;
|
||||||
|
|
||||||
|
let mut size = 0;
|
||||||
|
let ret = GetAdaptersAddresses(AF_UNSPEC.0 as u32, flags, None, None, &mut size);
|
||||||
|
if ret != ERROR_BUFFER_OVERFLOW.0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = vec![0u8; size as usize];
|
||||||
|
let ret = GetAdaptersAddresses(
|
||||||
|
AF_UNSPEC.0 as u32,
|
||||||
|
flags,
|
||||||
|
None,
|
||||||
|
Some(buf.as_mut_ptr() as *mut IP_ADAPTER_ADDRESSES_LH),
|
||||||
|
&mut size,
|
||||||
|
);
|
||||||
|
if ret != ERROR_SUCCESS.0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: GetAdaptersAddresses returns ERROR_NO_DATA error if it's zero len
|
||||||
|
let mut adapter_ptr = buf.as_ptr() as *const IP_ADAPTER_ADDRESSES_LH;
|
||||||
|
while !adapter_ptr.is_null() {
|
||||||
|
let adapter = adapter_ptr.read();
|
||||||
|
|
||||||
|
if adapter.PhysicalAddressLength == 6 {
|
||||||
|
return Some(adapter.PhysicalAddress[0..6].try_into().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter_ptr = adapter.Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(target_family = "unix", not(target_os = "redox")))]
|
||||||
|
fn get_node_id() -> Option<[u8; 6]> {
|
||||||
|
getifaddrs().ok().and_then(|iflist| {
|
||||||
|
iflist
|
||||||
|
.filter_map(|intf| intf.address?.as_link_addr()?.addr())
|
||||||
|
.find(|mac| mac.iter().any(|x| *x != 0))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(
|
||||||
|
target_os = "windows",
|
||||||
|
all(target_family = "unix", not(target_os = "redox"))
|
||||||
|
)))]
|
||||||
|
fn get_node_id() -> Option<[u8; 6]> {
|
||||||
|
None
|
||||||
|
}
|
||||||
11
src/uu/uuidgen/uuidgen.md
Normal file
11
src/uu/uuidgen/uuidgen.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# uuidgen
|
||||||
|
```
|
||||||
|
uuidgen [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Create UUIDs:
|
||||||
|
- v1: time + MAC address (-t/--time)
|
||||||
|
- v3: namespace + name, MD5 based (-m/--md5)
|
||||||
|
- v4: random (-r/--random)
|
||||||
|
- v5: namespace + name, SHA1 based (-s/--sha1)
|
||||||
98
tests/by-util/test_uuidgen.rs
Normal file
98
tests/by-util/test_uuidgen.rs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// This file is part of the uutils util-linux package.
|
||||||
|
//
|
||||||
|
// For the full copyright and license information, please view the LICENSE
|
||||||
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::common::util::{TestScenario, UCommand};
|
||||||
|
|
||||||
|
fn assert_ver_eq(cmd: &mut UCommand, ver: uuid::Version) {
|
||||||
|
let uuid = Uuid::parse_str(
|
||||||
|
cmd.succeeds()
|
||||||
|
.stdout_str()
|
||||||
|
.strip_suffix('\n')
|
||||||
|
.expect("newline"),
|
||||||
|
)
|
||||||
|
.expect("valid UUID");
|
||||||
|
assert_eq!(uuid.get_variant(), uuid::Variant::RFC4122);
|
||||||
|
assert_eq!(uuid.get_version(), Some(ver));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_random() {
|
||||||
|
assert_ver_eq(&mut new_ucmd!(), uuid::Version::Random);
|
||||||
|
assert_ver_eq(new_ucmd!().arg("-r"), uuid::Version::Random);
|
||||||
|
assert_ver_eq(new_ucmd!().arg("--random"), uuid::Version::Random);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_time() {
|
||||||
|
assert_ver_eq(new_ucmd!().arg("-t"), uuid::Version::Mac);
|
||||||
|
assert_ver_eq(new_ucmd!().arg("--time"), uuid::Version::Mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_arg_conflict() {
|
||||||
|
new_ucmd!().args(&["-r", "-t"]).fails().code_is(1);
|
||||||
|
new_ucmd!().args(&["--time", "--random"]).fails().code_is(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_md5_sha1() {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--namespace", "@dns", "--name", "example.com", "-m"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only("9073926b-929f-31c2-abc9-fad77ae3e8eb\n");
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-s", "--namespace", "@dns", "--name", "foobar"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only("a050b517-6677-5119-9a77-2d26bbf30507\n");
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["-s", "--namespace", "@url", "--name", "foobar"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only("8304efdd-bd6e-5b7c-a27f-83f3f05c64e0\n");
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--sha1", "--namespace", "@oid", "--name", "foobar"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only("364c03e1-bcdc-58bb-94ed-43e9a92f5f08\n");
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--sha1", "--namespace", "@x500", "--name", "foobar"])
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only("34da942e-f4a3-5169-9c65-267d2b22cf11\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_arg() {
|
||||||
|
new_ucmd!().arg("-Z").fails().code_is(1);
|
||||||
|
new_ucmd!().args(&["-r", "-Z"]).fails().code_is(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_name_namespace_on_non_hash() {
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--namespace", "@dns", "-r"])
|
||||||
|
.fails()
|
||||||
|
.code_is(1);
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--name", "example.com", "-r"])
|
||||||
|
.fails()
|
||||||
|
.code_is(1);
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--namespace", "@dns", "--name", "example.com", "-r"])
|
||||||
|
.fails()
|
||||||
|
.code_is(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_missing_name_namespace() {
|
||||||
|
new_ucmd!().arg("--sha1").fails().code_is(1);
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--sha1", "--namespace", "@dns"])
|
||||||
|
.fails()
|
||||||
|
.code_is(1);
|
||||||
|
new_ucmd!()
|
||||||
|
.args(&["--sha1", "--name", "example.com"])
|
||||||
|
.fails()
|
||||||
|
.code_is(1);
|
||||||
|
}
|
||||||
@@ -60,3 +60,7 @@ mod test_fsfreeze;
|
|||||||
#[cfg(feature = "mcookie")]
|
#[cfg(feature = "mcookie")]
|
||||||
#[path = "by-util/test_mcookie.rs"]
|
#[path = "by-util/test_mcookie.rs"]
|
||||||
mod test_mcookie;
|
mod test_mcookie;
|
||||||
|
|
||||||
|
#[cfg(feature = "uuidgen")]
|
||||||
|
#[path = "by-util/test_uuidgen.rs"]
|
||||||
|
mod test_uuidgen;
|
||||||
|
|||||||
Reference in New Issue
Block a user