fix(vfs): V-01 — copy dispatches to CarrierFs in carrier mode
This commit is contained in:
+128
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user