Allow filesize type as a valid limit value (#11349)

# Description
This pr allow us to use `filesize` type as a valid limit value, which is
benefit for some file size based limits.

# User-Facing Changes
```console
/data/source/nushell> ulimit -f                                                                                                   
╭───┬─────────────────────────────────────────────────────┬───────────┬───────────╮
│ # │                     description                     │   soft    │   hard    │
├───┼─────────────────────────────────────────────────────┼───────────┼───────────┤
│ 0 │ Maximum size of files created by the shell (kB, -f) │ unlimited │ unlimited │
╰───┴─────────────────────────────────────────────────────┴───────────┴───────────╯
/data/source/nushell> ulimit -f 10Mib                                                                                           
/data/source/nushell> ulimit -f                                                                                                    
╭───┬─────────────────────────────────────────────────────┬───────┬───────╮
│ # │                     description                     │ soft  │ hard  │
├───┼─────────────────────────────────────────────────────┼───────┼───────┤
│ 0 │ Maximum size of files created by the shell (kB, -f) │ 10240 │ 10240 │
╰───┴─────────────────────────────────────────────────────┴───────┴───────╯
/data/source/nushell> ulimit -n                                                                                                 
╭───┬──────────────────────────────────────────────┬──────┬────────╮
│ # │                 description                  │ soft │  hard  │
├───┼──────────────────────────────────────────────┼──────┼────────┤
│ 0 │ Maximum number of open file descriptors (-n) │ 1024 │ 524288 │
╰───┴──────────────────────────────────────────────┴──────┴────────╯
/data/source/nushell> ulimit -n 10Mib                                                                                            
Error: nu:🐚:type_mismatch

  × Type mismatch.
   ╭─[entry #5:1:1]
 1 │ ulimit -n 10Mib
   ·             ─┬─
   ·              ╰── filesize is not compatible with resource RLIMIT_NOFILE
   ╰────
```

# Tests + Formatting
Make sure you've run and fixed any issues with these commands:

- [x] add `commands::ulimit::limit_set_filesize1`
- [x] add `commands::ulimit::limit_set_filesize2`
- [x] `cargo fmt --all -- --check` to check standard code formatting
(`cargo fmt --all` applies these changes)
- [x] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used`
to check that you're using the standard code style
- [x] `cargo test --workspace` to check that all tests pass (on Windows
make sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- [x] `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library
This commit is contained in:
nibon7 2023-12-16 23:56:03 +08:00 committed by GitHub
parent 020e121391
commit a6da8ce769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 12 deletions

View File

@ -338,14 +338,7 @@ fn set_limits(
call_span: Span, call_span: Span,
) -> Result<(), ShellError> { ) -> Result<(), ShellError> {
let (mut soft_limit, mut hard_limit) = getrlimit(res.resource)?; let (mut soft_limit, mut hard_limit) = getrlimit(res.resource)?;
let new_limit = parse_limit( let new_limit = parse_limit(limit_value, res, soft, soft_limit, hard_limit, call_span)?;
limit_value,
res.multiplier,
soft,
soft_limit,
hard_limit,
call_span,
)?;
if hard { if hard {
hard_limit = new_limit; hard_limit = new_limit;
@ -427,7 +420,7 @@ fn getrlimit(res: Resource) -> Result<(rlim_t, rlim_t), ShellError> {
/// Parse user input /// Parse user input
fn parse_limit( fn parse_limit(
limit_value: &Value, limit_value: &Value,
multiplier: rlim_t, res: &ResourceInfo,
soft: bool, soft: bool,
soft_limit: rlim_t, soft_limit: rlim_t,
hard_limit: rlim_t, hard_limit: rlim_t,
@ -442,13 +435,31 @@ fn parse_limit(
help: Some(e.to_string()), help: Some(e.to_string()),
})?; })?;
let (limit, overflow) = value.overflowing_mul(multiplier); let (limit, overflow) = value.overflowing_mul(res.multiplier);
if overflow { if overflow {
Ok(RLIM_INFINITY) Ok(RLIM_INFINITY)
} else { } else {
Ok(limit) Ok(limit)
} }
} }
Value::Filesize { val, internal_span } => {
if res.multiplier != 1024 {
return Err(ShellError::TypeMismatch {
err_message: format!(
"filesize is not compatible with resource {:?}",
res.resource
),
span: *internal_span,
});
}
rlim_t::try_from(*val).map_err(|e| ShellError::CantConvert {
to_type: "rlim_t".into(),
from_type: "i64".into(),
span: *internal_span,
help: Some(e.to_string()),
})
}
Value::String { val, internal_span } => { Value::String { val, internal_span } => {
if val == "unlimited" { if val == "unlimited" {
Ok(RLIM_INFINITY) Ok(RLIM_INFINITY)
@ -470,7 +481,7 @@ fn parse_limit(
} }
_ => Err(ShellError::TypeMismatch { _ => Err(ShellError::TypeMismatch {
err_message: format!( err_message: format!(
"string or int required, you provide {}", "string, int or filesize required, you provide {}",
limit_value.get_type() limit_value.get_type()
), ),
span: limit_value.span(), span: limit_value.span(),

View File

@ -134,7 +134,7 @@ fn limit_set_invalid4() {
" "
); );
assert!(actual.err.contains("string or int required")); assert!(actual.err.contains("string, int or filesize required"));
}); });
} }
@ -168,3 +168,50 @@ fn limit_set_invalid5() {
assert!(actual.out.eq("unlimited")); assert!(actual.out.eq("unlimited"));
}); });
} }
#[test]
fn limit_set_filesize1() {
Playground::setup("limit_set_filesize1", |dirs, _sandbox| {
let actual = nu!(
cwd: dirs.test(), pipeline(
"
let hard = (ulimit -c | first | get hard);
match $hard {
\"unlimited\" => {
ulimit -c 1Mib;
ulimit -c
| first
| get soft
},
$x if $x >= 1024 * 1024 => {
ulimit -c 1Mib;
ulimit -c
| first
| get soft
}
_ => {
echo \"hard limit too small\"
}
}
"
));
assert!(actual.out.eq("1024") || actual.out.eq("hard limit too small"));
});
}
#[test]
fn limit_set_filesize2() {
Playground::setup("limit_set_filesize2", |dirs, _sandbox| {
let actual = nu!(
cwd: dirs.test(),
"
ulimit -n 10Kib
"
);
assert!(actual
.err
.contains("filesize is not compatible with resource RLIMIT_NOFILE"));
});
}