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_STAT_FAILED = 1,
|
||||||
FIO_RUST_OPEN_SRC_NON_REGULAR = 2,
|
FIO_RUST_OPEN_SRC_NON_REGULAR = 2,
|
||||||
FIO_RUST_OPEN_SRC_FOPEN_FAILED = 3,
|
FIO_RUST_OPEN_SRC_FOPEN_FAILED = 3,
|
||||||
|
FIO_RUST_OPEN_SRC_STDIN = 4,
|
||||||
};
|
};
|
||||||
int FIO_rust_openSrcFile(int allowBlockDevices,
|
int FIO_rust_openSrcFile(int allowBlockDevices,
|
||||||
const char* srcFileName,
|
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;
|
int allowBlockDevices = prefs != NULL ? prefs->allowBlockDevices : 0;
|
||||||
assert(srcFileName != NULL);
|
assert(srcFileName != NULL);
|
||||||
assert(statbuf != NULL);
|
assert(statbuf != NULL);
|
||||||
if (!strcmp (srcFileName, stdinmark)) {
|
|
||||||
DISPLAYLEVEL(4,"Using stdin for input \n");
|
|
||||||
SET_BINARY_MODE(stdin);
|
|
||||||
return stdin;
|
|
||||||
}
|
|
||||||
|
|
||||||
{ FILE* f = NULL;
|
{ FILE* f = NULL;
|
||||||
int const status = FIO_rust_openSrcFile(allowBlockDevices,
|
int const status = FIO_rust_openSrcFile(allowBlockDevices,
|
||||||
srcFileName,
|
srcFileName,
|
||||||
statbuf,
|
statbuf,
|
||||||
&f);
|
&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) {
|
if (status == FIO_RUST_OPEN_SRC_STAT_FAILED) {
|
||||||
DISPLAYLEVEL(1, "zstd: can't stat %s : %s -- ignored \n",
|
DISPLAYLEVEL(1, "zstd: can't stat %s : %s -- ignored \n",
|
||||||
srcFileName, strerror(errno));
|
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_STAT_FAILED: c_int = 1;
|
||||||
const FIO_OPEN_SRC_NON_REGULAR: c_int = 2;
|
const FIO_OPEN_SRC_NON_REGULAR: c_int = 2;
|
||||||
const FIO_OPEN_SRC_FOPEN_FAILED: c_int = 3;
|
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_SUCCESS: c_int = 0;
|
||||||
const FIO_OPEN_DST_SETBUF_FAILED: c_int = 1;
|
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;
|
const FIO_OPEN_DST_ACTION_INVALID: c_int = 12;
|
||||||
|
|
||||||
static STDOUT_MARK: &[u8] = b"/*stdout*\\\0";
|
static STDOUT_MARK: &[u8] = b"/*stdout*\\\0";
|
||||||
|
static STDIN_MARK: &[u8] = b"/*stdin*\\\0";
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
enum DestinationDecision {
|
enum DestinationDecision {
|
||||||
@@ -475,7 +477,8 @@ pub unsafe extern "C" fn FIO_rust_getDictFileStat(
|
|||||||
FIO_DICT_STAT_SUCCESS
|
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
|
/// `stat_buf` and `out_file` deliberately cross this boundary as opaque
|
||||||
/// pointers. The existing utility ABI owns the target-specific `stat_t` layout
|
/// 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,
|
stat_buf: *mut c_void,
|
||||||
out_file: *mut *mut c_void,
|
out_file: *mut *mut c_void,
|
||||||
) -> c_int {
|
) -> 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;
|
return FIO_OPEN_SRC_STAT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1698,6 +1711,19 @@ mod tests {
|
|||||||
assert!(file.is_null());
|
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]
|
#[test]
|
||||||
fn rejects_directory_source_path() {
|
fn rejects_directory_source_path() {
|
||||||
let path = temp_path("open-directory");
|
let path = temp_path("open-directory");
|
||||||
|
|||||||
Reference in New Issue
Block a user