fn lookup_follow(&self, path: &str, max_follow_times: usize) -> Result<Arc<dyn INode>> {
        if self.metadata()?.type_ != FileType::Dir {
            return Err(FsError::NotDir);
        }
        if path.len() > PATH_MAX {
            return Err(FsError::NameTooLong);
        }

        let mut follow_times = 0;
        let mut result = self.find(".")?;
        let mut rest_path = String::from(path);
        while rest_path != "" {
            if result.metadata()?.type_ != FileType::Dir {
                return Err(FsError::NotDir);
            }
            // handle absolute path
            if let Some('/') = rest_path.chars().next() {
                result = self.fs().root_inode();
                rest_path = String::from(rest_path[1..].trim_start_matches('/'));
                continue;
            }
            let name;
            match rest_path.find('/') {
                None => {
                    name = rest_path;
                    rest_path = String::new();
                }
                Some(pos) => {
                    name = String::from(&rest_path[0..pos]);
                    rest_path = String::from(rest_path[pos + 1..].trim_start_matches('/'));
                }
            };
            if name == "" {
                continue;
            }
            let inode = result.find(&name)?;
            // Handle symlink
            if inode.metadata()?.type_ == FileType::SymLink && max_follow_times > 0 {
                if follow_times >= max_follow_times {
                    return Err(FsError::SymLoop);
                }
                let mut content = [0u8; PATH_MAX];
                let len = inode.read_at(0, &mut content)?;
                let path = str::from_utf8(&content[..len]).map_err(|_| FsError::NotDir)?;
                // result remains unchanged
                rest_path = {
                    let mut new_path = String::from(path);
                    if let Some('/') = new_path.chars().last() {
                        new_path += &rest_path;
                    } else {
                        new_path += "/";
                        new_path += &rest_path;
                    }
                    new_path
                };
                follow_times += 1;
            } else {
                result = inode
            }
        }
        Ok(result)
    }
/// Lookup path from current INode, and follow symlinks at most `max_follow_times` times
Lookup path from current INode, and follow symlinks at most `max_follow_times` times
Lookup path from current INode and follow symlinks at most ` max_follow_times ` times
fn lookup_follow(&self, path: &str, max_follow_times: usize) -> Result<Arc<dyn INode>> {
        if self.metadata()?.type_ != FileType::Dir {
            return Err(FsError::NotDir);
        }
        if path.len() > PATH_MAX {
            return Err(FsError::NameTooLong);
        }
        let mut follow_times = 0;
        let mut result = self.find(".")?;
        let mut rest_path = String::from(path);
        while rest_path != "" {
            if result.metadata()?.type_ != FileType::Dir {
                return Err(FsError::NotDir);
            }
            // handle absolute path
            if let Some('/') = rest_path.chars().next() {
                result = self.fs().root_inode();
                rest_path = String::from(rest_path[1..].trim_start_matches('/'));
                continue;
            }
            let name;
            match rest_path.find('/') {
                None => {
                    name = rest_path;
                    rest_path = String::new();
                }
                Some(pos) => {
                    name = String::from(&rest_path[0..pos]);
                    rest_path = String::from(rest_path[pos + 1..].trim_start_matches('/'));
                }
            };
            if name == "" {
                continue;
            }
            let inode = result.find(&name)?;
            // Handle symlink
            if inode.metadata()?.type_ == FileType::SymLink && max_follow_times > 0 {
                if follow_times >= max_follow_times {
                    return Err(FsError::SymLoop);
                }
                let mut content = [0u8; PATH_MAX];
                let len = inode.read_at(0, &mut content)?;
                let path = str::from_utf8(&content[..len]).map_err(|_| FsError::NotDir)?;
                // result remains unchanged
                rest_path = {
                    let mut new_path = String::from(path);
                    if let Some('/') = new_path.chars().last() {
                        new_path += &rest_path;
                    } else {
                        new_path += "/";
                        new_path += &rest_path;
                    }
                    new_path
                };
                follow_times += 1;
            } else {
                result = inode
            }
        }
        Ok(result)
    }
fn lookup_follow ( & self , path : & str , max_follow_times : usize ) -> Result < Arc < dyn INode > > { if self . metadata ( ) ? . type_ != FileType :: Dir { return Err ( FsError :: NotDir ) ; } if path . len ( ) > PATH_MAX { return Err ( FsError :: NameTooLong ) ; } let mut follow_times = 0 ; let mut result = self . find ( " " ) ? ; let mut rest_path = String :: from ( path ) ; while rest_path != " " { if result . metadata ( ) ? . type_ != FileType :: Dir { return Err ( FsError :: NotDir ) ; } // handle absolute path if let Some ( '/' ) = rest_path . chars ( ) . next ( ) { result = self . fs ( ) . root_inode ( ) ; rest_path = String :: from ( rest_path [ 1 .. ] . trim_start_matches ( '/' ) ) ; continue ; } let name ; match rest_path . find ( '/' ) { None => { name = rest_path ; rest_path = String :: new ( ) ; } Some ( pos ) => { name = String :: from ( & rest_path [ 0 .. pos ] ) ; rest_path = String :: from ( rest_path [ pos + 1 .. ] . trim_start_matches ( '/' ) ) ; } } ; if name == " " { continue ; } let inode = result . find ( & name ) ? ; // Handle symlink if inode . metadata ( ) ? . type_ == FileType :: SymLink && max_follow_times > 0 { if follow_times >= max_follow_times { return Err ( FsError :: SymLoop ) ; } let mut content = [ 0u8 ; PATH_MAX ] ; let len = inode . read_at ( 0 , & mut content ) ? ; let path = str :: from_utf8 ( & content [ .. len ] ) . map_err ( | _ | FsError :: NotDir ) ? ; // result remains unchanged rest_path = { let mut new_path = String :: from ( path ) ; if let Some ( '/' ) = new_path . chars ( ) . last ( ) { new_path += & rest_path ; } else { new_path += " " ; new_path += & rest_path ; } new_path } ; follow_times += 1 ; } else { result = inode } } Ok ( result ) }
Lookup path from current INode, and follow symlinks at most `max_follow_times` times
Lookup path from current INode and follow symlinks at most ` max_follow_times ` times
&self
path
&str
max_follow_times
usize
&self
path
&str
max_follow_times
usize