// Preconditions: The caller must hold no locks (since opening pipes may block
// indefinitely).
The caller must hold no locks (since opening pipes may block
indefinitely).
// Preconditions : The caller must hold no locks ( since opening pipes may block // indefinitely ) .
func (d *dentry) open(ctx context.Context, rp *vfs.ResolvingPath, opts *vfs.OpenOptions, afterCreate bool) (*vfs.FileDescription, error) {
	ats := vfs.AccessTypesForOpenFlags(opts)
	if !afterCreate {
		if err := d.inode.checkPermissions(rp.Credentials(), ats); err != nil {
			return nil, err
		}
	}
	switch impl := d.inode.impl.(type) {
	case *regularFile:
		var fd regularFileFD
		fd.LockFD.Init(&d.inode.locks)
		if err := fd.vfsfd.Init(&fd, opts.Flags, rp.Mount(), &d.vfsd, &vfs.FileDescriptionOptions{AllowDirectIO: true}); err != nil {
			return nil, err
		}
		if !afterCreate && opts.Flags&linux.O_TRUNC != 0 {
			if _, err := impl.truncate(0); err != nil {
				return nil, err
			}
		}
		if fd.vfsfd.IsWritable() {
			fsmetric.TmpfsOpensW.Increment()
		} else if fd.vfsfd.IsReadable() {
			fsmetric.TmpfsOpensRO.Increment()
		}
		return &fd.vfsfd, nil
	case *directory:
		if ats&vfs.MayWrite != 0 {
			return nil, syserror.EISDIR
		}
		var fd directoryFD
		fd.LockFD.Init(&d.inode.locks)
		if err := fd.vfsfd.Init(&fd, opts.Flags, rp.Mount(), &d.vfsd, &vfs.FileDescriptionOptions{AllowDirectIO: true}); err != nil {
			return nil, err
		}
		return &fd.vfsfd, nil
	case *symlink:
		return nil, syserror.ELOOP
	case *namedPipe:
		return impl.pipe.Open(ctx, rp.Mount(), &d.vfsd, opts.Flags, &d.inode.locks)
	case *deviceFile:
		return rp.VirtualFilesystem().OpenDeviceSpecialFile(ctx, rp.Mount(), &d.vfsd, impl.kind, impl.major, impl.minor, opts)
	case *socketFile:
		return nil, syserror.ENXIO
	default:
		panic(fmt.Sprintf("unknown inode type: %T", d.inode.impl))
	}
}
func ( d * dentry ) open ( ctx context . Context , rp * vfs . ResolvingPath , opts * vfs . OpenOptions , afterCreate bool ) ( * vfs . FileDescription , error ) { ats := vfs . AccessTypesForOpenFlags ( opts ) if ! afterCreate { if err := d . inode . checkPermissions ( rp . Credentials ( ) , ats ) ; err != nil { return nil , err } } switch impl := d . inode . impl . ( type ) { case * regularFile : var fd regularFileFD fd . LockFD . Init ( & d . inode . locks ) if err := fd . vfsfd . Init ( & fd , opts . Flags , rp . Mount ( ) , & d . vfsd , & vfs . FileDescriptionOptions { AllowDirectIO : true } ) ; err != nil { return nil , err } if ! afterCreate && opts . Flags & linux . O_TRUNC != 0 { if _ , err := impl . truncate ( 0 ) ; err != nil { return nil , err } } if fd . vfsfd . IsWritable ( ) { fsmetric . TmpfsOpensW . Increment ( ) } else if fd . vfsfd . IsReadable ( ) { fsmetric . TmpfsOpensRO . Increment ( ) } return & fd . vfsfd , nil case * directory : if ats & vfs . MayWrite != 0 { return nil , syserror . EISDIR } var fd directoryFD fd . LockFD . Init ( & d . inode . locks ) if err := fd . vfsfd . Init ( & fd , opts . Flags , rp . Mount ( ) , & d . vfsd , & vfs . FileDescriptionOptions { AllowDirectIO : true } ) ; err != nil { return nil , err } return & fd . vfsfd , nil case * symlink : return nil , syserror . ELOOP case * namedPipe : return impl . pipe . Open ( ctx , rp . Mount ( ) , & d . vfsd , opts . Flags , & d . inode . locks ) case * deviceFile : return rp . VirtualFilesystem ( ) . OpenDeviceSpecialFile ( ctx , rp . Mount ( ) , & d . vfsd , impl . kind , impl . major , impl . minor , opts ) case * socketFile : return nil , syserror . ENXIO default : panic ( fmt . Sprintf ( " " , d . inode . impl ) ) } }
The caller must hold no locks (since opening pipes may block
indefinitely).
The caller must hold no locks ( since opening pipes may block indefinitely ) .
// Can't open directories writably. // Can't open symlinks without O_PATH, which is handled at the VFS layer.