Skip to content

Commit 34e2b36

Browse files
authored
Implement basic lsns utility (#554)
--------- Signed-off-by: Malhar Vora <mlvora.2010@gmail.com>
1 parent f77b451 commit 34e2b36

10 files changed

Lines changed: 955 additions & 0 deletions

File tree

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ feat_common_core = [
3838
"lsipc",
3939
"lslocks",
4040
"lsmem",
41+
"lsns",
4142
"mcookie",
4243
"mesg",
4344
"mountpoint",
@@ -110,6 +111,7 @@ lscpu = { optional = true, version = "0.0.1", package = "uu_lscpu", path = "src/
110111
lsipc = { optional = true, version = "0.0.1", package = "uu_lsipc", path = "src/uu/lsipc" }
111112
lslocks = { optional = true, version = "0.0.1", package = "uu_lslocks", path = "src/uu/lslocks" }
112113
lsmem = { optional = true, version = "0.0.1", package = "uu_lsmem", path = "src/uu/lsmem" }
114+
lsns = { optional = true, version = "0.0.1", package = "uu_lsns", path = "src/uu/lsns" }
113115
mcookie = { optional = true, version = "0.0.1", package = "uu_mcookie", path = "src/uu/mcookie" }
114116
mesg = { optional = true, version = "0.0.1", package = "uu_mesg", path = "src/uu/mesg" }
115117
mountpoint = { optional = true, version = "0.0.1", package = "uu_mountpoint", path = "src/uu/mountpoint" }

src/uu/lsns/Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "uu_lsns"
3+
version = "0.0.1"
4+
edition = "2024"
5+
6+
[lib]
7+
path = "src/lsns.rs"
8+
9+
[[bin]]
10+
name = "lsns"
11+
path = "src/main.rs"
12+
13+
[dependencies]
14+
uucore = { workspace = true, features = ["entries"] }
15+
clap = { workspace = true }
16+
smartcols-sys = { workspace = true }

src/uu/lsns/lsns.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# lsns
2+
3+
```
4+
lsns [OPTION]...
5+
```
6+
7+
List the namespaces in the system.

src/uu/lsns/src/errors.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// This file is part of the uutils util-linux package.
2+
//
3+
// For the full copyright and license information, please view the LICENSE
4+
// file that was distributed with this source code.
5+
6+
use std::ffi::c_int;
7+
use std::fmt;
8+
9+
use uucore::error::UError;
10+
11+
#[derive(Debug)]
12+
pub enum LsnsError {
13+
/// Generic I/O error with context message
14+
IOError(String, std::io::Error),
15+
/// CString conversion error (null byte in string)
16+
NulError(String, std::ffi::NulError),
17+
/// Invalid namespace type index
18+
InvalidNamespaceType(usize),
19+
/// Unsupported platform
20+
#[cfg(not(target_os = "linux"))]
21+
UnsupportedPlatform,
22+
/// Invalid namespace inode format
23+
InvalidNamespaceInodeFormat(String),
24+
/// Invalid process stat format
25+
InvalidProcessStatFormat(String),
26+
/// Failed to get UID from directory entry
27+
FailedToGetUid(String),
28+
/// Failed to get PID from directory entry
29+
FailedToGetPid(String),
30+
/// Failed to read process information
31+
FailedToReadProcess(String),
32+
}
33+
34+
impl LsnsError {
35+
/// Create an I/O error with a context message
36+
pub(crate) fn io0(message: impl Into<String>, error: impl Into<std::io::Error>) -> Self {
37+
Self::IOError(message.into(), error.into())
38+
}
39+
40+
/// Helper to convert negative errno to Result
41+
pub(crate) fn io_from_neg_errno(
42+
message: impl Into<String>,
43+
result: c_int,
44+
) -> Result<usize, LsnsError> {
45+
if let Ok(result) = usize::try_from(result) {
46+
Ok(result)
47+
} else {
48+
let err = std::io::Error::from_raw_os_error(-result);
49+
Err(Self::IOError(message.into(), err))
50+
}
51+
}
52+
}
53+
54+
impl fmt::Display for LsnsError {
55+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56+
match self {
57+
Self::IOError(message, err) => write!(f, "{message}: {err}"),
58+
Self::NulError(message, err) => write!(f, "{message}: {err}"),
59+
Self::InvalidNamespaceType(idx) => write!(f, "Invalid namespace type index: {}", idx),
60+
#[cfg(not(target_os = "linux"))]
61+
Self::UnsupportedPlatform => write!(f, "lsns is only supported on Linux"),
62+
Self::InvalidNamespaceInodeFormat(s) => {
63+
write!(f, "Invalid namespace inode format: {}", s)
64+
}
65+
Self::InvalidProcessStatFormat(s) => {
66+
write!(f, "Invalid process stat format: {}", s)
67+
}
68+
Self::FailedToGetUid(s) => {
69+
write!(f, "Failed to get UID from directory entry: {}", s)
70+
}
71+
Self::FailedToGetPid(s) => {
72+
write!(f, "Failed to get PID from directory entry: {}", s)
73+
}
74+
Self::FailedToReadProcess(s) => {
75+
write!(f, "Failed to read process information: {}", s)
76+
}
77+
}
78+
}
79+
}
80+
81+
impl UError for LsnsError {
82+
fn code(&self) -> i32 {
83+
1
84+
}
85+
86+
fn usage(&self) -> bool {
87+
false
88+
}
89+
}
90+
91+
impl std::error::Error for LsnsError {}
92+
93+
// Implement From trait for automatic conversion from std::io::Error
94+
impl From<std::io::Error> for LsnsError {
95+
fn from(err: std::io::Error) -> Self {
96+
Self::IOError(String::new(), err)
97+
}
98+
}
99+
100+
// Implement From trait for automatic conversion from std::ffi::NulError
101+
impl From<std::ffi::NulError> for LsnsError {
102+
fn from(err: std::ffi::NulError) -> Self {
103+
Self::NulError(String::new(), err)
104+
}
105+
}

0 commit comments

Comments
 (0)