pub fn remove_link(
        &self,
        parent: u64,
        name: &str,
        // If provided, will preform "sticky bit" checks for the inode.
        link_inode_and_uid: Option<(u64, u32)>,
        context: UserContext,
    ) -> Result<(Inode, bool), ErrorCode> {
        let mut directories = self.directories.lock().map_err(|_| ErrorCode::Corrupted)?;
        let mut metadata = self.metadata.lock().map_err(|_| ErrorCode::Corrupted)?;
        let parent_directory = directories
            .get_mut(&parent)
            .ok_or(ErrorCode::InodeDoesNotExist)?;
        let (inode, _) = parent_directory.get(name).ok_or(ErrorCode::DoesNotExist)?;

        if let Some((retrieved_inode, _)) = link_inode_and_uid {
            if retrieved_inode != *inode {
                // The inode that the client looked up is out of date (i.e. this link has been
                // deleted and recreated since then). Tell the client to look it up again.
                return Ok((*inode, false));
            }
        }

        let parent_attrs = metadata.get(&parent).ok_or(ErrorCode::InodeDoesNotExist)?;
        if !check_access(
            parent_attrs.uid,
            parent_attrs.gid,
            parent_attrs.mode,
            context.uid(),
            context.gid(),
            libc::W_OK,
        ) {
            return Err(ErrorCode::AccessDenied);
        }

        let uid = context.uid();
        // "Sticky bit" handling
        if parent_attrs.mode & libc::S_ISVTX as u16 != 0 && uid != parent_attrs.uid && uid != 0 {
            if let Some((_, inode_uid)) = link_inode_and_uid {
                if uid != inode_uid {
                    return Err(ErrorCode::AccessDenied);
                }
            } else {
                // Sticky bit is on, and we need to check the inode's uid. Tell the client to lock
                // it and look up the uid.
                return Ok((*inode, false));
            }
        }

        let parent_attrs = metadata
            .get_mut(&parent)
            .ok_or(ErrorCode::InodeDoesNotExist)?;
        parent_attrs.last_metadata_changed = now();
        parent_attrs.last_modified = now();
        let (inode, _) = parent_directory
            .remove(name)
            .ok_or(ErrorCode::DoesNotExist)?;

        Ok((inode, true))
    }
// Remove a directory entry.
// Returns the link inode, and a boolean indicating if processing is complete. If it is false
// then it could not be determined if the link can be removed due to "stick bit".
// In this case the inode's uid should be retrieved and this method retried, passing the
// link_inode_and_uid argument.
Remove a directory entry.
Returns the link inode, and a boolean indicating if processing is complete. If it is false
then it could not be determined if the link can be removed due to "stick bit".
In this case the inode's uid should be retrieved and this method retried, passing the
link_inode_and_uid argument.
Remove a directory entry . Returns the link inode and a boolean indicating if processing is complete . If it is false then it could not be determined if the link can be removed due to " stick bit " . In this case the inode ' s uid should be retrieved and this method retried passing the link_inode_and_uid argument .
pub fn remove_link(
        &self,
        parent: u64,
        name: &str,
        // If provided, will preform "sticky bit" checks for the inode.
        link_inode_and_uid: Option<(u64, u32)>,
        context: UserContext,
    ) -> Result<(Inode, bool), ErrorCode> {
        let mut directories = self.directories.lock().map_err(|_| ErrorCode::Corrupted)?;
        let mut metadata = self.metadata.lock().map_err(|_| ErrorCode::Corrupted)?;
        let parent_directory = directories
            .get_mut(&parent)
            .ok_or(ErrorCode::InodeDoesNotExist)?;
        let (inode, _) = parent_directory.get(name).ok_or(ErrorCode::DoesNotExist)?;
        if let Some((retrieved_inode, _)) = link_inode_and_uid {
            if retrieved_inode != *inode {
                // The inode that the client looked up is out of date (i.e. this link has been
                // deleted and recreated since then). Tell the client to look it up again.
                return Ok((*inode, false));
            }
        }
        let parent_attrs = metadata.get(&parent).ok_or(ErrorCode::InodeDoesNotExist)?;
        if !check_access(
            parent_attrs.uid,
            parent_attrs.gid,
            parent_attrs.mode,
            context.uid(),
            context.gid(),
            libc::W_OK,
        ) {
            return Err(ErrorCode::AccessDenied);
        }
        let uid = context.uid();
        // "Sticky bit" handling
        if parent_attrs.mode & libc::S_ISVTX as u16 != 0 && uid != parent_attrs.uid && uid != 0 {
            if let Some((_, inode_uid)) = link_inode_and_uid {
                if uid != inode_uid {
                    return Err(ErrorCode::AccessDenied);
                }
            } else {
                // Sticky bit is on, and we need to check the inode's uid. Tell the client to lock
                // it and look up the uid.
                return Ok((*inode, false));
            }
        }
        let parent_attrs = metadata
            .get_mut(&parent)
            .ok_or(ErrorCode::InodeDoesNotExist)?;
        parent_attrs.last_metadata_changed = now();
        parent_attrs.last_modified = now();
        let (inode, _) = parent_directory
            .remove(name)
            .ok_or(ErrorCode::DoesNotExist)?;
        Ok((inode, true))
    }
pub fn remove_link ( & self , parent : u64 , name : & str , // If provided, will preform "sticky bit" checks for the inode. link_inode_and_uid : Option < ( u64 , u32 ) > , context : UserContext , ) -> Result < ( Inode , bool ) , ErrorCode > { let mut directories = self . directories . lock ( ) . map_err ( | _ | ErrorCode :: Corrupted ) ? ; let mut metadata = self . metadata . lock ( ) . map_err ( | _ | ErrorCode :: Corrupted ) ? ; let parent_directory = directories . get_mut ( & parent ) . ok_or ( ErrorCode :: InodeDoesNotExist ) ? ; let ( inode , _ ) = parent_directory . get ( name ) . ok_or ( ErrorCode :: DoesNotExist ) ? ; if let Some ( ( retrieved_inode , _ ) ) = link_inode_and_uid { if retrieved_inode != * inode { // The inode that the client looked up is out of date (i.e. this link has been // deleted and recreated since then). Tell the client to look it up again. return Ok ( ( * inode , false ) ) ; } } let parent_attrs = metadata . get ( & parent ) . ok_or ( ErrorCode :: InodeDoesNotExist ) ? ; if ! check_access ( parent_attrs . uid , parent_attrs . gid , parent_attrs . mode , context . uid ( ) , context . gid ( ) , libc :: W_OK , ) { return Err ( ErrorCode :: AccessDenied ) ; } let uid = context . uid ( ) ; // "Sticky bit" handling if parent_attrs . mode & libc :: S_ISVTX as u16 != 0 && uid != parent_attrs . uid && uid != 0 { if let Some ( ( _ , inode_uid ) ) = link_inode_and_uid { if uid != inode_uid { return Err ( ErrorCode :: AccessDenied ) ; } } else { // Sticky bit is on, and we need to check the inode's uid. Tell the client to lock // it and look up the uid. return Ok ( ( * inode , false ) ) ; } } let parent_attrs = metadata . get_mut ( & parent ) . ok_or ( ErrorCode :: InodeDoesNotExist ) ? ; parent_attrs . last_metadata_changed = now ( ) ; parent_attrs . last_modified = now ( ) ; let ( inode , _ ) = parent_directory . remove ( name ) . ok_or ( ErrorCode :: DoesNotExist ) ? ; Ok ( ( inode , true ) ) }
Remove a directory entry.
Remove a directory entry .
&self
parent
u64
name
&str
link_inode_and_uid
Option<(u64, u32)>
context
UserContext
&self
parent
u64
name
&str
link_inode_and_uid
Option<(u64, u32)>
context
UserContext