fix(vfs): V-01 — copy dispatches to CarrierFs in carrier mode

This commit is contained in:
2026-09-19 00:16:04 +02:00
parent 533764487a
commit 151fdba09d
3 changed files with 335 additions and 0 deletions
+128
View File
@@ -747,6 +747,134 @@ impl DavFileSystem for CarrierFs {
Ok(())
})
}
fn copy<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> FsFuture<'a, ()> {
Box::pin(async move {
self.touch();
let from_str = Self::path_to_str(from);
let to_str = Self::path_to_str(to);
if from_str == to_str {
return Ok(());
}
let mut inner = self.inner.lock().unwrap();
let node = inner.resolve_path(&from_str).ok_or(FsError::NotFound)?;
if node.is_dir {
return Err(FsError::NotImplemented);
}
let (to_parent_path, to_name) = inner.split_parent_and_name(&to_str);
if inner.anti_leak && is_leak_file(to_name) {
return Err(FsError::Forbidden);
}
let to_parent = inner
.resolve_path(to_parent_path)
.ok_or(FsError::NotFound)?;
if !to_parent.is_dir {
return Err(FsError::Forbidden);
}
// Falls Zieldatei existiert und ein Verzeichnis ist: Fehler
if let Some(dest) = inner.resolve_path(&to_str) {
if dest.is_dir {
return Err(FsError::Forbidden);
}
for b in dest.blocks {
let _ = shred_carrier_block(
&inner.db,
inner.carrier_node_id,
b,
&inner.dek_outer,
inner.format_version,
);
inner.manifest.free_blocks.push(b);
}
inner.manifest.inodes.remove(&dest.id);
}
if inner.manifest.free_blocks.len() < node.blocks.len() {
return Err(FsError::InsufficientStorage);
}
let mut dest_blocks = Vec::with_capacity(node.blocks.len());
for &src_block_idx in &node.blocks {
let dest_block_idx = match inner.allocate_block() {
Ok(b) => b,
Err(e) => {
for b in dest_blocks {
let _ = inner.free_block(b);
}
return Err(e);
}
};
let data = match read_carrier_block(
&inner.db,
inner.carrier_node_id,
src_block_idx,
&inner.dek_outer,
&inner.dek_inner,
inner.format_version,
) {
Ok(d) => d,
Err(e) => {
error!("Fehler beim Lesen des Quell-Blocks während copy: {e}");
let _ = inner.free_block(dest_block_idx);
for b in dest_blocks {
let _ = inner.free_block(b);
}
return Err(FsError::GeneralFailure);
}
};
if let Err(e) = write_carrier_block(
&inner.db,
inner.carrier_node_id,
dest_block_idx,
&inner.dek_outer,
&inner.dek_inner,
&data,
inner.format_version,
) {
error!("Fehler beim Schreiben des Ziel-Blocks während copy: {e}");
let _ = inner.free_block(dest_block_idx);
for b in dest_blocks {
let _ = inner.free_block(b);
}
return Err(FsError::GeneralFailure);
}
dest_blocks.push(dest_block_idx);
}
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
let new_id = inner.manifest.next_inode_id;
inner.manifest.next_inode_id += 1;
let new_inode = CarrierInode {
id: new_id,
parent_id: Some(to_parent.id),
name: to_name.to_string(),
is_dir: false,
size: node.size,
created_at: now,
modified_at: now,
blocks: dest_blocks,
};
inner.manifest.inodes.insert(new_id, new_inode);
inner.save_manifest().map_err(|_| FsError::GeneralFailure)?;
Ok(())
})
}
}
/// Datei-Handle für Dateien innerhalb des Carrier-Dateisystems mit Streaming und Chunk-Pufferung.
+8
View File
@@ -952,11 +952,19 @@ impl DavFileSystem for SanctumFs {
}
fn copy<'a>(&'a self, from: &'a DavPath, to: &'a DavPath) -> FsFuture<'a, ()> {
if let Some(ref cfs) = self.carrier_fs {
return cfs.copy(from, to);
}
Box::pin(async move {
self.touch();
let from_str = Self::path_to_str(from);
let to_str = Self::path_to_str(to);
if from_str == to_str {
return Ok(());
}
let node = self.resolve_path(&from_str)?.ok_or(FsError::NotFound)?;
if node.is_dir {