Skip to content

Commit e46cdbb

Browse files
committed
fix(mktemp): add wasi platform support for temporary directory handling
- Add conditional compilation for WASI target to avoid panics from `std::env::temp_dir()` - Implement fallback logic in `Options` to read TMPDIR environment variable directly on WASI - Update `get_tmpdir_env_or_default()` with WASI-specific handling for temp directory resolution - Add `#[cfg_attr]` annotations to skip host path-dependent tests on WASI sandbox environment - Ignore 14 tests that require host filesystem access when running under wasi_runner - Ignore directory permission test on WASI due to lack of `chmod` support and mode parameter limitations
1 parent 33df181 commit e46cdbb

4 files changed

Lines changed: 56 additions & 6 deletions

File tree

.github/workflows/wasi.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ jobs:
7171
test_base32:: test_base64:: test_basenc:: test_basename:: \
7272
test_comm:: test_cut:: test_dirname:: test_echo:: \
7373
test_expand:: test_factor:: test_false:: test_fold:: \
74-
test_head:: test_link:: test_ln:: test_nl:: test_numfmt:: \
74+
test_head:: test_link:: test_ln:: test_mktemp:: test_nl:: test_numfmt:: \
7575
test_od:: test_paste:: test_printf:: test_shuf:: test_sum:: \
7676
test_tee:: test_tr:: test_true:: test_truncate:: \
7777
test_unexpand:: test_unlink:: test_wc:: test_yes::

src/uu/mktemp/src/mktemp.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,13 @@ impl Options {
143143
} else if matches.get_flag(OPT_T) || matches.contains_id(OPT_TMPDIR) {
144144
// If --tmpdir is given without an argument, or -t is given
145145
// export in TMPDIR
146-
Some(env::temp_dir())
146+
#[cfg(target_os = "wasi")]
147+
// WASI's `std::env::temp_dir()` unconditionally panics
148+
let default_tmp_dir = env::var_os(TMPDIR_ENV_VAR)
149+
.map_or_else(|| PathBuf::from(FALLBACK_TMPDIR), PathBuf::from);
150+
#[cfg(not(target_os = "wasi"))]
151+
let default_tmp_dir = env::temp_dir();
152+
Some(default_tmp_dir)
147153
} else {
148154
None
149155
};
@@ -629,6 +635,13 @@ fn exec(dir: &Path, prefix: &str, rand: usize, suffix: &str, make_dir: bool) ->
629635
fn get_tmpdir_env_or_default() -> PathBuf {
630636
match env::var_os(TMPDIR_ENV_VAR) {
631637
Some(val) if val.is_empty() => PathBuf::from(FALLBACK_TMPDIR),
638+
// WASI's `std::env::temp_dir()` unconditionally panics,
639+
// so read `TMPDIR` directly.
640+
#[cfg(target_os = "wasi")]
641+
Some(val) => PathBuf::from(val),
642+
#[cfg(target_os = "wasi")]
643+
None => PathBuf::from(FALLBACK_TMPDIR),
644+
#[cfg(not(target_os = "wasi"))]
632645
_ => env::temp_dir(),
633646
}
634647
}

tests/by-util/test_install.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,15 @@ fn test_install_and_strip() {
789789
let scene = TestScenario::new(util_name!());
790790
let at = &scene.fixtures;
791791

792-
at.write("strip", STRIP_PROGRAM);
792+
// Write the strip script and sync to disk to avoid ETXTBSY race on some
793+
// platforms (observed on ARM64 Linux CI runners).
794+
let strip_path = at.plus("strip");
795+
{
796+
use std::io::Write;
797+
let mut f = fs::File::create(&strip_path).unwrap();
798+
f.write_all(STRIP_PROGRAM.as_bytes()).unwrap();
799+
f.sync_all().unwrap();
800+
}
793801
at.set_mode("strip", 0o755);
794802
at.write("source", "file contents");
795803
let path = format!(
@@ -830,7 +838,15 @@ fn test_install_and_strip_with_program() {
830838
let scene = TestScenario::new(util_name!());
831839
let at = &scene.fixtures;
832840

833-
at.write("strip-program", STRIP_PROGRAM);
841+
// Write the strip script and sync to disk to avoid ETXTBSY race on some
842+
// platforms (observed on ARM64 Linux CI runners).
843+
let strip_path = at.plus("strip-program");
844+
{
845+
use std::io::Write;
846+
let mut f = fs::File::create(&strip_path).unwrap();
847+
f.write_all(STRIP_PROGRAM.as_bytes()).unwrap();
848+
f.sync_all().unwrap();
849+
}
834850
at.set_mode("strip-program", 0o755);
835851
at.write("source", "file contents");
836852

tests/by-util/test_mktemp.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ fn test_mktemp_mktemp() {
118118
}
119119

120120
#[test]
121+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
121122
fn test_mktemp_mktemp_t() {
122123
let scene = TestScenario::new(util_name!());
123124

@@ -399,6 +400,7 @@ fn test_mktemp_suffix() {
399400
}
400401

401402
#[test]
403+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
402404
fn test_mktemp_tmpdir() {
403405
let scene = TestScenario::new(util_name!());
404406
let dir = tempdir().unwrap();
@@ -462,6 +464,7 @@ fn test_mktemp_tmpdir() {
462464
}
463465

464466
#[test]
467+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
465468
fn test_mktemp_empty_tmpdir() {
466469
let scene = TestScenario::new(util_name!());
467470
let pathname = scene.fixtures.as_string();
@@ -482,6 +485,7 @@ fn test_mktemp_empty_tmpdir() {
482485
}
483486

484487
#[test]
488+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
485489
fn test_mktemp_tmpdir_one_arg() {
486490
let scene = TestScenario::new(util_name!());
487491

@@ -495,6 +499,7 @@ fn test_mktemp_tmpdir_one_arg() {
495499
}
496500

497501
#[test]
502+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
498503
fn test_mktemp_directory_tmpdir() {
499504
let scene = TestScenario::new(util_name!());
500505

@@ -599,6 +604,11 @@ fn test_respect_template_directory() {
599604

600605
#[cfg(unix)]
601606
#[test]
607+
#[cfg_attr(
608+
wasi_runner,
609+
ignore = "WASI: path_create_directory has no mode parameter and chmod returns ENOSYS, \
610+
so directories can't be created with restricted permissions"
611+
)]
602612
fn test_directory_permissions() {
603613
let (at, mut ucmd) = at_and_ucmd!();
604614
let result = ucmd.args(&["-d", "XXX"]).succeeds();
@@ -869,6 +879,7 @@ fn test_nonexistent_tmpdir_env_var() {
869879
}
870880

871881
#[test]
882+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
872883
fn test_empty_tmpdir_env_var() {
873884
#[cfg(not(any(windows, target_os = "android")))]
874885
{
@@ -967,11 +978,13 @@ fn test_nonexistent_dir_prefix() {
967978
}
968979

969980
#[test]
981+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
970982
fn test_default_missing_value() {
971983
new_ucmd!().arg("-d").arg("--tmpdir").succeeds();
972984
}
973985

974986
#[test]
987+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
975988
fn test_default_issue_4821_t_tmpdir() {
976989
let scene = TestScenario::new(util_name!());
977990
let pathname = scene.fixtures.as_string();
@@ -987,6 +1000,7 @@ fn test_default_issue_4821_t_tmpdir() {
9871000
}
9881001

9891002
#[test]
1003+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
9901004
fn test_default_issue_4821_t_tmpdir_p() {
9911005
let scene = TestScenario::new(util_name!());
9921006
let pathname = scene.fixtures.as_string();
@@ -1003,6 +1017,7 @@ fn test_default_issue_4821_t_tmpdir_p() {
10031017
}
10041018

10051019
#[test]
1020+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
10061021
fn test_t_ensure_tmpdir_has_higher_priority_than_p() {
10071022
let scene = TestScenario::new(util_name!());
10081023
let pathname = scene.fixtures.as_string();
@@ -1099,7 +1114,8 @@ fn test_missing_short_tmpdir_flag() {
10991114
}
11001115

11011116
#[test]
1102-
#[cfg(target_os = "linux")]
1117+
#[cfg(unix)]
1118+
#[cfg_attr(wasi_runner, ignore = "WASI: wasmtime rejects non-UTF-8 arguments")]
11031119
fn test_non_utf8_template() {
11041120
use std::ffi::OsStr;
11051121
use std::os::unix::ffi::OsStrExt;
@@ -1114,6 +1130,7 @@ fn test_non_utf8_template() {
11141130

11151131
#[test]
11161132
#[cfg(target_os = "linux")]
1133+
#[cfg_attr(wasi_runner, ignore = "WASI: wasmtime rejects non-UTF-8 arguments")]
11171134
fn test_non_utf8_tmpdir_path() {
11181135
use std::os::unix::ffi::OsStrExt;
11191136
let (at, mut ucmd) = at_and_ucmd!();
@@ -1128,6 +1145,7 @@ fn test_non_utf8_tmpdir_path() {
11281145

11291146
#[test]
11301147
#[cfg(target_os = "linux")]
1148+
#[cfg_attr(wasi_runner, ignore = "WASI: wasmtime rejects non-UTF-8 arguments")]
11311149
fn test_non_utf8_tmpdir_long_option() {
11321150
use std::os::unix::ffi::OsStrExt;
11331151
let (at, mut ucmd) = at_and_ucmd!();
@@ -1146,7 +1164,8 @@ fn test_non_utf8_tmpdir_long_option() {
11461164
}
11471165

11481166
#[test]
1149-
#[cfg(target_os = "linux")]
1167+
#[cfg(unix)]
1168+
#[cfg_attr(wasi_runner, ignore = "WASI: wasmtime rejects non-UTF-8 arguments")]
11501169
fn test_invalid_utf8_suffix() {
11511170
use std::os::unix::ffi::OsStrExt;
11521171
let (at, mut ucmd) = at_and_ucmd!();
@@ -1167,6 +1186,7 @@ fn test_invalid_utf8_suffix() {
11671186

11681187
#[test]
11691188
#[cfg(target_os = "linux")]
1189+
#[cfg_attr(wasi_runner, ignore = "WASI: wasmtime rejects non-UTF-8 arguments")]
11701190
fn test_non_utf8_tmpdir_directory_creation() {
11711191
use std::os::unix::ffi::OsStrExt;
11721192
let (at, mut ucmd) = at_and_ucmd!();
@@ -1183,6 +1203,7 @@ fn test_non_utf8_tmpdir_directory_creation() {
11831203

11841204
#[test]
11851205
#[cfg(unix)]
1206+
#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")]
11861207
fn test_mktemp_hidden_file_single_dot() {
11871208
let scene = TestScenario::new(util_name!());
11881209
let dir = tempdir().unwrap();

0 commit comments

Comments
 (0)