Add support for rename
All checks were successful
continuous-integration/drone the build was successful
All checks were successful
continuous-integration/drone the build was successful
This commit is contained in:
parent
926a29fa47
commit
1fb63833c5
@ -390,7 +390,7 @@ impl Filesystem for OliveFilesystem {
|
|||||||
reply.error(ENOENT);
|
reply.error(ENOENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let link = if let Some(link) = link.to_str() {
|
let link = if let Some(link) = link.to_str() {
|
||||||
link
|
link
|
||||||
@ -400,7 +400,7 @@ impl Filesystem for OliveFilesystem {
|
|||||||
reply.error(ENOENT);
|
reply.error(ENOENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let requester = self.requester.clone();
|
let requester = self.requester.clone();
|
||||||
|
|
||||||
@ -419,7 +419,10 @@ impl Filesystem for OliveFilesystem {
|
|||||||
reply.entry(&Duration::from_secs(5), &file_attr, 42);
|
reply.entry(&Duration::from_secs(5), &file_attr, 42);
|
||||||
}
|
}
|
||||||
DataResponse::Error { code, message } => {
|
DataResponse::Error { code, message } => {
|
||||||
warn!("symlink(parent: {:#x?}) failed: {:?}", parent_vnode, message);
|
warn!(
|
||||||
|
"symlink(parent: {:#x?}) failed: {:?}",
|
||||||
|
parent_vnode, message
|
||||||
|
);
|
||||||
reply.error(code as c_int);
|
reply.error(code as c_int);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,12 +444,62 @@ impl Filesystem for OliveFilesystem {
|
|||||||
flags: u32,
|
flags: u32,
|
||||||
reply: ReplyEmpty,
|
reply: ReplyEmpty,
|
||||||
) {
|
) {
|
||||||
debug!(
|
let name = if let Some(name) = name.to_str() {
|
||||||
"[Not Implemented] rename(parent: {:#x?}, name: {:?}, newparent: {:#x?}, \
|
name
|
||||||
newname: {:?}, flags: {})",
|
} else {
|
||||||
parent, name, newparent, newname, flags,
|
// If we can't decode the filename, pretend it doesn't exist.
|
||||||
|
error!("rename: Old Filename not convertible.");
|
||||||
|
reply.error(ENOENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
|
let newname = if let Some(newname) = newname.to_str() {
|
||||||
|
newname
|
||||||
|
} else {
|
||||||
|
// If we can't decode the filename, pretend it doesn't exist.
|
||||||
|
error!("rename: New Filename not convertible.");
|
||||||
|
reply.error(ENOENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
|
let requester = self.requester.clone();
|
||||||
|
|
||||||
|
self.spawn_with_error_handler(
|
||||||
|
async move {
|
||||||
|
let parent_vnode = VnodeId(
|
||||||
|
parent
|
||||||
|
.try_into()
|
||||||
|
.context("Converting u64 inode to u32 VnodeId.")?,
|
||||||
|
);
|
||||||
|
|
||||||
|
let newparent_vnode = VnodeId(
|
||||||
|
newparent
|
||||||
|
.try_into()
|
||||||
|
.context("Converting u64 inode to u32 VnodeId.")?,
|
||||||
|
);
|
||||||
|
|
||||||
|
match requester
|
||||||
|
.rename(parent_vnode, name, newparent_vnode, newname)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
DataResponse::Success(()) => {
|
||||||
|
reply.ok();
|
||||||
|
}
|
||||||
|
DataResponse::Error { code, message } => {
|
||||||
|
warn!(
|
||||||
|
"rename(parent: {:#x?}, newparent: {:#?}) failed: {:?}",
|
||||||
|
parent_vnode, newparent_vnode, message
|
||||||
|
);
|
||||||
|
reply.error(code as c_int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
"rename",
|
||||||
);
|
);
|
||||||
reply.error(ENOSYS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a hard link.
|
/// Create a hard link.
|
||||||
|
@ -226,10 +226,14 @@ impl Requester {
|
|||||||
&self,
|
&self,
|
||||||
dir_vnode: VnodeId,
|
dir_vnode: VnodeId,
|
||||||
name: String,
|
name: String,
|
||||||
link: String
|
link: String,
|
||||||
) -> anyhow::Result<DataResponse<FileMetadata>> {
|
) -> anyhow::Result<DataResponse<FileMetadata>> {
|
||||||
self.internal
|
self.internal
|
||||||
.command(&DataCommand::MakeSymlink { dir_vnode, name, link })
|
.command(&DataCommand::MakeSymlink {
|
||||||
|
dir_vnode,
|
||||||
|
name,
|
||||||
|
link,
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,6 +257,23 @@ impl Requester {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn rename(
|
||||||
|
&self,
|
||||||
|
old_dir_vnode: VnodeId,
|
||||||
|
old_name: String,
|
||||||
|
new_dir_vnode: VnodeId,
|
||||||
|
new_name: String,
|
||||||
|
) -> anyhow::Result<DataResponse<()>> {
|
||||||
|
self.internal
|
||||||
|
.command(&DataCommand::Rename {
|
||||||
|
old_dir_vnode,
|
||||||
|
old_name,
|
||||||
|
new_dir_vnode,
|
||||||
|
new_name,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn open(&self, vnode: VnodeId, mode: OpenMode) -> anyhow::Result<DataResponse<u32>> {
|
pub async fn open(&self, vnode: VnodeId, mode: OpenMode) -> anyhow::Result<DataResponse<u32>> {
|
||||||
self.internal
|
self.internal
|
||||||
.command(&DataCommand::OpenFile { vnode, mode })
|
.command(&DataCommand::OpenFile { vnode, mode })
|
||||||
|
@ -108,6 +108,12 @@ pub enum DataCommand {
|
|||||||
name: String,
|
name: String,
|
||||||
link: String,
|
link: String,
|
||||||
},
|
},
|
||||||
|
Rename {
|
||||||
|
old_dir_vnode: VnodeId,
|
||||||
|
old_name: String,
|
||||||
|
new_dir_vnode: VnodeId,
|
||||||
|
new_name: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
@ -166,7 +166,11 @@ pub async fn handle_command_stream(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
DataCommand::MakeSymlink { dir_vnode, name, link } => {
|
DataCommand::MakeSymlink {
|
||||||
|
dir_vnode,
|
||||||
|
name,
|
||||||
|
link,
|
||||||
|
} => {
|
||||||
send_bare_message(
|
send_bare_message(
|
||||||
&mut tx,
|
&mut tx,
|
||||||
&file_access
|
&file_access
|
||||||
@ -174,7 +178,22 @@ pub async fn handle_command_stream(
|
|||||||
.await
|
.await
|
||||||
.unwrap_or_else(error_to_response),
|
.unwrap_or_else(error_to_response),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
}
|
||||||
|
DataCommand::Rename {
|
||||||
|
old_dir_vnode,
|
||||||
|
old_name,
|
||||||
|
new_dir_vnode,
|
||||||
|
new_name,
|
||||||
|
} => {
|
||||||
|
send_bare_message(
|
||||||
|
&mut tx,
|
||||||
|
&file_access
|
||||||
|
.rename(old_dir_vnode, old_name, new_dir_vnode, new_name)
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(error_to_response),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -815,4 +815,28 @@ impl FileAccess {
|
|||||||
let metadata = self.read_metadata(&target_path, vnode).await?;
|
let metadata = self.read_metadata(&target_path, vnode).await?;
|
||||||
Ok(DataResponse::Success(metadata))
|
Ok(DataResponse::Success(metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Symlink safety:
|
||||||
|
/// Makes an attempt to safely resolve symlinks, but there is a possibility of a TOCTOU race.
|
||||||
|
/// TODO Revisit later for safety.
|
||||||
|
pub async fn rename(
|
||||||
|
&self,
|
||||||
|
old_dir_vnode: VnodeId,
|
||||||
|
old_name: String,
|
||||||
|
new_dir_vnode: VnodeId,
|
||||||
|
new_name: String,
|
||||||
|
) -> anyhow::Result<DataResponse<()>> {
|
||||||
|
let old_parent_dir_resolved = self
|
||||||
|
.resolve_vnode_including_follow_symlinks_safely_best_effort(old_dir_vnode)
|
||||||
|
.await?;
|
||||||
|
let source_path = old_parent_dir_resolved.join(old_name);
|
||||||
|
|
||||||
|
let new_parent_dir_resolved = self
|
||||||
|
.resolve_vnode_including_follow_symlinks_safely_best_effort(new_dir_vnode)
|
||||||
|
.await?;
|
||||||
|
let target_path = new_parent_dir_resolved.join(new_name);
|
||||||
|
|
||||||
|
tokio::fs::rename(source_path, target_path).await?;
|
||||||
|
Ok(DataResponse::Success(()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user