fix(openapi): harden story 2.1 production lifecycle
CI / Rust Checks (push) Failing after 4m6s
CI / UI Checks (push) Has been skipped
CI / Frontend E2E (push) Has been skipped
CI / Community Image Smoke (push) Has been skipped
CI / Deploy (push) Has been skipped

This commit is contained in:
2026-08-29 00:48:22 +03:00
parent 2c94af6791
commit bc03c33387
46 changed files with 2198 additions and 276 deletions
+48 -9
View File
@@ -1,5 +1,19 @@
use crate::{ArtifactError, ArtifactStore, TempScan};
pub(crate) struct NamePage {
pub(crate) names: Vec<NameEntry>,
/// Opaque `telldir` position immediately after the last consumed entry.
/// It is meaningful only for the same opened directory inode.
pub(crate) continuation: Option<i64>,
}
pub(crate) struct NameEntry {
pub(crate) name: String,
/// Directory position immediately before this entry. Resuming here
/// guarantees a candidate omitted by a result limit is reconsidered.
pub(crate) cookie_before: i64,
}
pub(crate) fn valid_temp_name(name: &str) -> bool {
let Some(rest) = name.strip_prefix(ArtifactStore::temp_prefix()) else {
return false;
@@ -20,11 +34,12 @@ pub(crate) fn valid_temp_name(name: &str) -> bool {
&& sequence.bytes().all(|byte| byte.is_ascii_digit())
}
pub(crate) fn list_names(
pub(crate) fn list_names_after(
parent: i32,
remaining: &mut usize,
report: &mut TempScan,
) -> Result<Vec<String>, ArtifactError> {
continuation: Option<i64>,
) -> Result<NamePage, ArtifactError> {
let dot = std::ffi::CString::new(".").map_err(|_| ArtifactError::Storage)?;
let raw = unsafe {
libc::openat(
@@ -44,13 +59,32 @@ pub(crate) fn list_names(
return Err(ArtifactError::Storage);
}
let mut names = Vec::new();
if let Some(cookie) = continuation {
unsafe {
libc::seekdir(directory, cookie as libc::c_long);
}
}
loop {
if *remaining == 0 {
break;
let continuation = unsafe { libc::telldir(directory) };
unsafe {
libc::closedir(directory);
}
return Ok(NamePage {
names,
continuation: (continuation >= 0).then_some(continuation as i64),
});
}
unsafe {
*libc::__errno_location() = 0;
}
let cookie_before = unsafe { libc::telldir(directory) };
if cookie_before < 0 {
unsafe {
libc::closedir(directory);
}
return Err(ArtifactError::Storage);
}
let entry = unsafe { libc::readdir(directory) };
if entry.is_null() {
if unsafe { *libc::__errno_location() } != 0 {
@@ -59,7 +93,13 @@ pub(crate) fn list_names(
}
return Err(ArtifactError::Storage);
}
break;
unsafe {
libc::closedir(directory);
}
return Ok(NamePage {
names,
continuation: None,
});
}
let name = unsafe { std::ffi::CStr::from_ptr((*entry).d_name.as_ptr()) }.to_bytes();
if name == b"." || name == b".." {
@@ -68,11 +108,10 @@ pub(crate) fn list_names(
report.scanned += 1;
*remaining -= 1;
if let Ok(name) = std::str::from_utf8(name) {
names.push(name.to_owned());
names.push(NameEntry {
name: name.to_owned(),
cookie_before: cookie_before as i64,
});
}
}
unsafe {
libc::closedir(directory);
}
Ok(names)
}