/// The primary entry point for opening files relative to a task.
///
/// Absolute paths are resolve relative to the root of the FsContext for
/// this task. Relative paths are resolve relative to dir_fd. To resolve
/// relative to the current working directory, pass FdNumber::AT_FDCWD for
/// dir_fd.
///
/// Returns a FileHandle but does not install the FileHandle in the FdTable
/// for this task.
The primary entry point for opening files relative to a task.
Absolute paths are resolve relative to the root of the FsContext for
this task. Relative paths are resolve relative to dir_fd. To resolve
relative to the current working directory, pass FdNumber::AT_FDCWD for
dir_fd.

Returns a FileHandle but does not install the FileHandle in the FdTable
for this task.
The primary entry point for opening files relative to a task . Absolute paths are resolve relative to the root of the FsContext for this task . Relative paths are resolve relative to dir_fd . To resolve relative to the current working directory pass FdNumber :: AT_FDCWD for dir_fd . Returns a FileHandle but does not install the FileHandle in the FdTable for this task .
pub fn open_file_at(
        &self,
        dir_fd: FdNumber,
        path: &FsStr,
        flags: OpenFlags,
        mode: FileMode,
    ) -> Result<FileHandle, Errno> {
        let mut flags = flags;
        if flags.contains(OpenFlags::PATH) {
            // When O_PATH is specified in flags, flag bits other than O_CLOEXEC,
            // O_DIRECTORY, and O_NOFOLLOW are ignored.
            const ALLOWED_FLAGS: OpenFlags = OpenFlags::from_bits_truncate(
                OpenFlags::PATH.bits()
                    | OpenFlags::CLOEXEC.bits()
                    | OpenFlags::DIRECTORY.bits()
                    | OpenFlags::NOFOLLOW.bits(),
            );
            flags = flags & ALLOWED_FLAGS;
        }
        let nofollow = flags.contains(OpenFlags::NOFOLLOW);
        let must_create = flags.contains(OpenFlags::CREAT) && flags.contains(OpenFlags::EXCL);
        let symlink_mode =
            if nofollow || must_create { SymlinkMode::NoFollow } else { SymlinkMode::Follow };
        if path.is_empty() {
            return error!(ENOENT);
        }
        let (dir, path) = self.resolve_dir_fd(dir_fd, path)?;
        let mut context = LookupContext::new(symlink_mode);
        context.must_be_directory = flags.contains(OpenFlags::DIRECTORY);
        let name = self.resolve_open_path(&mut context, dir, path, mode, flags)?;
        // Be sure not to reference the mode argument after this point.
        // Below, we shadow the mode argument with the mode of the file we are
        // opening. This line of code will hopefully catch future bugs if we
        // refactor this function.
        std::mem::drop(mode);
        let mode = name.entry.node.info().mode;
        if nofollow && mode.is_lnk() {
            return error!(ELOOP);
        }
        if mode.is_dir() {
            if flags.can_write()
                || flags.contains(OpenFlags::CREAT)
                || flags.contains(OpenFlags::TRUNC)
            {
                return error!(EISDIR);
            }
        } else if context.must_be_directory {
            return error!(ENOTDIR);
        }
        if flags.contains(OpenFlags::TRUNC) && mode.is_reg() {
            // You might think we should check file.can_write() at this
            // point, which is what the docs suggest, but apparently we
            // are supposed to truncate the file if this task can write
            // to the underlying node, even if we are opening the file
            // as read-only. See OpenTest.CanTruncateReadOnly.
            // TODO(security): We should really do an access check for whether
            // this task can write to this file.
            if mode.contains(FileMode::IWUSR) {
                name.entry.node.truncate(0)?;
            }
        }
        name.open(&*self.kernel(), flags)
    }
pub fn open_file_at ( & self , dir_fd : FdNumber , path : & FsStr , flags : OpenFlags , mode : FileMode , ) -> Result < FileHandle , Errno > { let mut flags = flags ; if flags . contains ( OpenFlags :: PATH ) { // When O_PATH is specified in flags, flag bits other than O_CLOEXEC, // O_DIRECTORY, and O_NOFOLLOW are ignored. const ALLOWED_FLAGS : OpenFlags = OpenFlags :: from_bits_truncate ( OpenFlags :: PATH . bits ( ) | OpenFlags :: CLOEXEC . bits ( ) | OpenFlags :: DIRECTORY . bits ( ) | OpenFlags :: NOFOLLOW . bits ( ) , ) ; flags = flags & ALLOWED_FLAGS ; } let nofollow = flags . contains ( OpenFlags :: NOFOLLOW ) ; let must_create = flags . contains ( OpenFlags :: CREAT ) && flags . contains ( OpenFlags :: EXCL ) ; let symlink_mode = if nofollow || must_create { SymlinkMode :: NoFollow } else { SymlinkMode :: Follow } ; if path . is_empty ( ) { return error ! ( ENOENT ) ; } let ( dir , path ) = self . resolve_dir_fd ( dir_fd , path ) ? ; let mut context = LookupContext :: new ( symlink_mode ) ; context . must_be_directory = flags . contains ( OpenFlags :: DIRECTORY ) ; let name = self . resolve_open_path ( & mut context , dir , path , mode , flags ) ? ; // Be sure not to reference the mode argument after this point. // Below, we shadow the mode argument with the mode of the file we are // opening. This line of code will hopefully catch future bugs if we // refactor this function. std :: mem :: drop ( mode ) ; let mode = name . entry . node . info ( ) . mode ; if nofollow && mode . is_lnk ( ) { return error ! ( ELOOP ) ; } if mode . is_dir ( ) { if flags . can_write ( ) || flags . contains ( OpenFlags :: CREAT ) || flags . contains ( OpenFlags :: TRUNC ) { return error ! ( EISDIR ) ; } } else if context . must_be_directory { return error ! ( ENOTDIR ) ; } if flags . contains ( OpenFlags :: TRUNC ) && mode . is_reg ( ) { // You might think we should check file.can_write() at this // point, which is what the docs suggest, but apparently we // are supposed to truncate the file if this task can write // to the underlying node, even if we are opening the file // as read-only. See OpenTest.CanTruncateReadOnly. // TODO(security): We should really do an access check for whether // this task can write to this file. if mode . contains ( FileMode :: IWUSR ) { name . entry . node . truncate ( 0 ) ? ; } } name . open ( & * self . kernel ( ) , flags ) }
The primary entry point for opening files relative to a task.
The primary entry point for opening files relative to a task .
&self
dir_fd
FdNumber
path
&FsStr
flags
OpenFlags
mode
FileMode