refactor(cli): move source-open policy to Rust
Move stdin-sentinel classification and source stat/open result policy into the Rust fileio backend while keeping C responsible for diagnostics, binary-mode setup, and FILE ownership. The bridge leaves stat layout and native file utilities behind the existing C ABI and adds a focused no-stat stdin test. Test Plan: git diff --cached --check; focused Rust test added but full capped verification will run after the remaining workers are integrated.
This commit is contained in:
+7
-6
@@ -351,6 +351,7 @@ enum {
|
||||
FIO_RUST_OPEN_SRC_STAT_FAILED = 1,
|
||||
FIO_RUST_OPEN_SRC_NON_REGULAR = 2,
|
||||
FIO_RUST_OPEN_SRC_FOPEN_FAILED = 3,
|
||||
FIO_RUST_OPEN_SRC_STDIN = 4,
|
||||
};
|
||||
int FIO_rust_openSrcFile(int allowBlockDevices,
|
||||
const char* srcFileName,
|
||||
@@ -671,17 +672,17 @@ static FILE* FIO_openSrcFile(const FIO_prefs_t* const prefs, const char* srcFile
|
||||
int allowBlockDevices = prefs != NULL ? prefs->allowBlockDevices : 0;
|
||||
assert(srcFileName != NULL);
|
||||
assert(statbuf != NULL);
|
||||
if (!strcmp (srcFileName, stdinmark)) {
|
||||
DISPLAYLEVEL(4,"Using stdin for input \n");
|
||||
SET_BINARY_MODE(stdin);
|
||||
return stdin;
|
||||
}
|
||||
|
||||
{ FILE* f = NULL;
|
||||
int const status = FIO_rust_openSrcFile(allowBlockDevices,
|
||||
srcFileName,
|
||||
statbuf,
|
||||
&f);
|
||||
if (status == FIO_RUST_OPEN_SRC_STDIN) {
|
||||
DISPLAYLEVEL(4,"Using stdin for input \n");
|
||||
SET_BINARY_MODE(stdin);
|
||||
return stdin;
|
||||
}
|
||||
|
||||
if (status == FIO_RUST_OPEN_SRC_STAT_FAILED) {
|
||||
DISPLAYLEVEL(1, "zstd: can't stat %s : %s -- ignored \n",
|
||||
srcFileName, strerror(errno));
|
||||
|
||||
@@ -55,6 +55,7 @@ const FIO_OPEN_SRC_SUCCESS: c_int = 0;
|
||||
const FIO_OPEN_SRC_STAT_FAILED: c_int = 1;
|
||||
const FIO_OPEN_SRC_NON_REGULAR: c_int = 2;
|
||||
const FIO_OPEN_SRC_FOPEN_FAILED: c_int = 3;
|
||||
const FIO_OPEN_SRC_STDIN: c_int = 4;
|
||||
|
||||
const FIO_OPEN_DST_SUCCESS: c_int = 0;
|
||||
const FIO_OPEN_DST_SETBUF_FAILED: c_int = 1;
|
||||
@@ -84,6 +85,7 @@ const FIO_OPEN_DST_ACTION_SUCCESS: c_int = 11;
|
||||
const FIO_OPEN_DST_ACTION_INVALID: c_int = 12;
|
||||
|
||||
static STDOUT_MARK: &[u8] = b"/*stdout*\\\0";
|
||||
static STDIN_MARK: &[u8] = b"/*stdin*\\\0";
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum DestinationDecision {
|
||||
@@ -475,7 +477,8 @@ pub unsafe extern "C" fn FIO_rust_getDictFileStat(
|
||||
FIO_DICT_STAT_SUCCESS
|
||||
}
|
||||
|
||||
/// Opens a non-stdin source path and returns a status for the C policy adapter.
|
||||
/// Classifies stdin before opening or statting, then opens a non-stdin source
|
||||
/// path and returns a status for the C policy adapter.
|
||||
///
|
||||
/// `stat_buf` and `out_file` deliberately cross this boundary as opaque
|
||||
/// pointers. The existing utility ABI owns the target-specific `stat_t` layout
|
||||
@@ -488,7 +491,17 @@ pub unsafe extern "C" fn FIO_rust_openSrcFile(
|
||||
stat_buf: *mut c_void,
|
||||
out_file: *mut *mut c_void,
|
||||
) -> c_int {
|
||||
if file_name.is_null() || stat_buf.is_null() || out_file.is_null() {
|
||||
if file_name.is_null() || out_file.is_null() {
|
||||
return FIO_OPEN_SRC_STAT_FAILED;
|
||||
}
|
||||
|
||||
// The stdin sentinel is a dispatch decision, not a filesystem path. It
|
||||
// must be recognized before the stat buffer is touched; C retains the
|
||||
// stream selection, binary-mode setup, and exact diagnostic.
|
||||
if c_string_equals(file_name, STDIN_MARK) {
|
||||
return FIO_OPEN_SRC_STDIN;
|
||||
}
|
||||
if stat_buf.is_null() {
|
||||
return FIO_OPEN_SRC_STAT_FAILED;
|
||||
}
|
||||
|
||||
@@ -1698,6 +1711,19 @@ mod tests {
|
||||
assert!(file.is_null());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn classifies_stdin_before_stat_and_leaves_output_untouched() {
|
||||
let stdin = CString::new("/*stdin*\\").expect("stdin sentinel contains no NUL");
|
||||
let sentinel = ptr::dangling_mut::<c_void>();
|
||||
let mut out_file = sentinel;
|
||||
|
||||
let status = unsafe {
|
||||
FIO_rust_openSrcFile(0, stdin.as_ptr(), ptr::null_mut(), &mut out_file)
|
||||
};
|
||||
assert_eq!(status, FIO_OPEN_SRC_STDIN);
|
||||
assert_eq!(out_file, sentinel);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_directory_source_path() {
|
||||
let path = temp_path("open-directory");
|
||||
|
||||
Reference in New Issue
Block a user