fix(openapi): harden story 2.1 production lifecycle
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user