2019-04-29 21:25:05 +00:00
|
|
|
// Copyright 2018 The gVisor Authors.
|
2018-04-27 17:37:02 +00:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package fsutil
|
|
|
|
|
|
|
|
import (
|
2019-01-15 04:33:29 +00:00
|
|
|
"sync"
|
|
|
|
|
2019-06-13 23:49:09 +00:00
|
|
|
"gvisor.dev/gvisor/pkg/sentry/context"
|
|
|
|
"gvisor.dev/gvisor/pkg/sentry/fs"
|
|
|
|
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
|
|
|
|
"gvisor.dev/gvisor/pkg/sentry/memmap"
|
|
|
|
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
|
|
|
|
"gvisor.dev/gvisor/pkg/syserror"
|
|
|
|
"gvisor.dev/gvisor/pkg/waiter"
|
2018-04-27 17:37:02 +00:00
|
|
|
)
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// SimpleFileInode is a simple implementation of InodeOperations.
|
|
|
|
//
|
|
|
|
// +stateify savable
|
|
|
|
type SimpleFileInode struct {
|
|
|
|
InodeGenericChecker `state:"nosave"`
|
|
|
|
InodeNoExtendedAttributes `state:"nosave"`
|
|
|
|
InodeNoopRelease `state:"nosave"`
|
|
|
|
InodeNoopWriteOut `state:"nosave"`
|
2019-05-09 22:34:44 +00:00
|
|
|
InodeNotAllocatable `state:"nosave"`
|
2019-01-15 04:33:29 +00:00
|
|
|
InodeNotDirectory `state:"nosave"`
|
|
|
|
InodeNotMappable `state:"nosave"`
|
|
|
|
InodeNotOpenable `state:"nosave"`
|
|
|
|
InodeNotSocket `state:"nosave"`
|
|
|
|
InodeNotSymlink `state:"nosave"`
|
|
|
|
InodeNotTruncatable `state:"nosave"`
|
|
|
|
InodeNotVirtual `state:"nosave"`
|
|
|
|
|
|
|
|
InodeSimpleAttributes
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewSimpleFileInode returns a new SimpleFileInode.
|
|
|
|
func NewSimpleFileInode(ctx context.Context, owner fs.FileOwner, perms fs.FilePermissions, typ uint64) *SimpleFileInode {
|
|
|
|
return &SimpleFileInode{
|
|
|
|
InodeSimpleAttributes: NewInodeSimpleAttributes(ctx, owner, perms, typ),
|
|
|
|
}
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// NoReadWriteFileInode is an implementation of InodeOperations that supports
|
|
|
|
// opening files that are not readable or writeable.
|
2018-08-02 17:41:44 +00:00
|
|
|
//
|
|
|
|
// +stateify savable
|
2019-01-15 04:33:29 +00:00
|
|
|
type NoReadWriteFileInode struct {
|
|
|
|
InodeGenericChecker `state:"nosave"`
|
|
|
|
InodeNoExtendedAttributes `state:"nosave"`
|
|
|
|
InodeNoopRelease `state:"nosave"`
|
|
|
|
InodeNoopWriteOut `state:"nosave"`
|
2019-05-09 22:34:44 +00:00
|
|
|
InodeNotAllocatable `state:"nosave"`
|
2018-04-27 17:37:02 +00:00
|
|
|
InodeNotDirectory `state:"nosave"`
|
2019-01-15 04:33:29 +00:00
|
|
|
InodeNotMappable `state:"nosave"`
|
2018-04-27 17:37:02 +00:00
|
|
|
InodeNotSocket `state:"nosave"`
|
|
|
|
InodeNotSymlink `state:"nosave"`
|
2019-01-15 04:33:29 +00:00
|
|
|
InodeNotTruncatable `state:"nosave"`
|
|
|
|
InodeNotVirtual `state:"nosave"`
|
2018-04-27 17:37:02 +00:00
|
|
|
|
|
|
|
InodeSimpleAttributes
|
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// NewNoReadWriteFileInode returns a new NoReadWriteFileInode.
|
|
|
|
func NewNoReadWriteFileInode(ctx context.Context, owner fs.FileOwner, perms fs.FilePermissions, typ uint64) *NoReadWriteFileInode {
|
|
|
|
return &NoReadWriteFileInode{
|
|
|
|
InodeSimpleAttributes: NewInodeSimpleAttributes(ctx, owner, perms, typ),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetFile implements fs.InodeOperations.GetFile.
|
|
|
|
func (*NoReadWriteFileInode) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
|
|
|
return fs.NewFile(ctx, dirent, flags, &NoReadWriteFile{}), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeSimpleAttributes implements methods for updating in-memory unstable
|
|
|
|
// attributes.
|
2018-08-02 17:41:44 +00:00
|
|
|
//
|
|
|
|
// +stateify savable
|
2018-04-27 17:37:02 +00:00
|
|
|
type InodeSimpleAttributes struct {
|
2019-01-28 21:25:27 +00:00
|
|
|
// fsType is the immutable filesystem type that will be returned by
|
2019-01-15 04:33:29 +00:00
|
|
|
// StatFS.
|
2019-01-28 21:25:27 +00:00
|
|
|
fsType uint64
|
2018-04-27 17:37:02 +00:00
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// mu protects unstable.
|
|
|
|
mu sync.RWMutex `state:"nosave"`
|
2019-01-28 21:25:27 +00:00
|
|
|
unstable fs.UnstableAttr
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-28 21:25:27 +00:00
|
|
|
// NewInodeSimpleAttributes returns a new InodeSimpleAttributes with the given
|
|
|
|
// owner and permissions, and all timestamps set to the current time.
|
2019-01-15 04:33:29 +00:00
|
|
|
func NewInodeSimpleAttributes(ctx context.Context, owner fs.FileOwner, perms fs.FilePermissions, typ uint64) InodeSimpleAttributes {
|
2019-01-28 21:25:27 +00:00
|
|
|
return NewInodeSimpleAttributesWithUnstable(fs.WithCurrentTime(ctx, fs.UnstableAttr{
|
|
|
|
Owner: owner,
|
|
|
|
Perms: perms,
|
|
|
|
}), typ)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewInodeSimpleAttributesWithUnstable returns a new InodeSimpleAttributes
|
|
|
|
// with the given unstable attributes.
|
|
|
|
func NewInodeSimpleAttributesWithUnstable(uattr fs.UnstableAttr, typ uint64) InodeSimpleAttributes {
|
2019-01-15 04:33:29 +00:00
|
|
|
return InodeSimpleAttributes{
|
2019-01-28 21:25:27 +00:00
|
|
|
fsType: typ,
|
|
|
|
unstable: uattr,
|
2019-01-15 04:33:29 +00:00
|
|
|
}
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// UnstableAttr implements fs.InodeOperations.UnstableAttr.
|
2019-01-15 04:33:29 +00:00
|
|
|
func (i *InodeSimpleAttributes) UnstableAttr(ctx context.Context, _ *fs.Inode) (fs.UnstableAttr, error) {
|
|
|
|
i.mu.RLock()
|
2019-01-28 21:25:27 +00:00
|
|
|
u := i.unstable
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.RUnlock()
|
|
|
|
return u, nil
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// SetPermissions implements fs.InodeOperations.SetPermissions.
|
|
|
|
func (i *InodeSimpleAttributes) SetPermissions(ctx context.Context, _ *fs.Inode, p fs.FilePermissions) bool {
|
|
|
|
i.mu.Lock()
|
2019-01-28 21:25:27 +00:00
|
|
|
i.unstable.SetPermissions(ctx, p)
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.Unlock()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetOwner implements fs.InodeOperations.SetOwner.
|
|
|
|
func (i *InodeSimpleAttributes) SetOwner(ctx context.Context, _ *fs.Inode, owner fs.FileOwner) error {
|
|
|
|
i.mu.Lock()
|
2019-01-28 21:25:27 +00:00
|
|
|
i.unstable.SetOwner(ctx, owner)
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.Unlock()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetTimestamps implements fs.InodeOperations.SetTimestamps.
|
|
|
|
func (i *InodeSimpleAttributes) SetTimestamps(ctx context.Context, _ *fs.Inode, ts fs.TimeSpec) error {
|
|
|
|
i.mu.Lock()
|
2019-01-28 21:25:27 +00:00
|
|
|
i.unstable.SetTimestamps(ctx, ts)
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.Unlock()
|
|
|
|
return nil
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// AddLink implements fs.InodeOperations.AddLink.
|
2019-01-15 04:33:29 +00:00
|
|
|
func (i *InodeSimpleAttributes) AddLink() {
|
|
|
|
i.mu.Lock()
|
2019-01-28 21:25:27 +00:00
|
|
|
i.unstable.Links++
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.Unlock()
|
|
|
|
}
|
2018-04-27 17:37:02 +00:00
|
|
|
|
|
|
|
// DropLink implements fs.InodeOperations.DropLink.
|
2019-01-15 04:33:29 +00:00
|
|
|
func (i *InodeSimpleAttributes) DropLink() {
|
|
|
|
i.mu.Lock()
|
2019-01-28 21:25:27 +00:00
|
|
|
i.unstable.Links--
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.Unlock()
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// StatFS implements fs.InodeOperations.StatFS.
|
|
|
|
func (i *InodeSimpleAttributes) StatFS(context.Context) (fs.Info, error) {
|
2019-01-28 21:25:27 +00:00
|
|
|
if i.fsType == 0 {
|
2019-01-15 04:33:29 +00:00
|
|
|
return fs.Info{}, syserror.ENOSYS
|
|
|
|
}
|
2019-01-28 21:25:27 +00:00
|
|
|
return fs.Info{Type: i.fsType}, nil
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// NotifyAccess updates the access time.
|
|
|
|
func (i *InodeSimpleAttributes) NotifyAccess(ctx context.Context) {
|
|
|
|
i.mu.Lock()
|
2019-01-28 21:25:27 +00:00
|
|
|
i.unstable.AccessTime = ktime.NowFromContext(ctx)
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.Unlock()
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// NotifyModification updates the modification time.
|
|
|
|
func (i *InodeSimpleAttributes) NotifyModification(ctx context.Context) {
|
|
|
|
i.mu.Lock()
|
2019-01-28 21:25:27 +00:00
|
|
|
i.unstable.ModificationTime = ktime.NowFromContext(ctx)
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.Unlock()
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// NotifyStatusChange updates the status change time.
|
|
|
|
func (i *InodeSimpleAttributes) NotifyStatusChange(ctx context.Context) {
|
|
|
|
i.mu.Lock()
|
2019-01-28 21:25:27 +00:00
|
|
|
i.unstable.StatusChangeTime = ktime.NowFromContext(ctx)
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.Unlock()
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-05-20 20:34:06 +00:00
|
|
|
// NotifyModificationAndStatusChange updates the modification and status change
|
|
|
|
// times.
|
|
|
|
func (i *InodeSimpleAttributes) NotifyModificationAndStatusChange(ctx context.Context) {
|
|
|
|
i.mu.Lock()
|
|
|
|
now := ktime.NowFromContext(ctx)
|
|
|
|
i.unstable.ModificationTime = now
|
|
|
|
i.unstable.StatusChangeTime = now
|
|
|
|
i.mu.Unlock()
|
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// InodeSimpleExtendedAttributes implements
|
|
|
|
// fs.InodeOperations.{Get,Set,List}xattr.
|
2018-08-02 17:41:44 +00:00
|
|
|
//
|
|
|
|
// +stateify savable
|
2019-01-15 04:33:29 +00:00
|
|
|
type InodeSimpleExtendedAttributes struct {
|
|
|
|
// mu protects xattrs.
|
|
|
|
mu sync.RWMutex `state:"nosave"`
|
2019-04-05 22:48:26 +00:00
|
|
|
xattrs map[string]string
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// Getxattr implements fs.InodeOperations.Getxattr.
|
2019-04-05 22:48:26 +00:00
|
|
|
func (i *InodeSimpleExtendedAttributes) Getxattr(_ *fs.Inode, name string) (string, error) {
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.RLock()
|
|
|
|
value, ok := i.xattrs[name]
|
|
|
|
i.mu.RUnlock()
|
|
|
|
if !ok {
|
2019-04-05 22:48:26 +00:00
|
|
|
return "", syserror.ENOATTR
|
2019-01-15 04:33:29 +00:00
|
|
|
}
|
|
|
|
return value, nil
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// Setxattr implements fs.InodeOperations.Setxattr.
|
2019-04-05 22:48:26 +00:00
|
|
|
func (i *InodeSimpleExtendedAttributes) Setxattr(_ *fs.Inode, name, value string) error {
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.Lock()
|
|
|
|
if i.xattrs == nil {
|
2019-04-05 22:48:26 +00:00
|
|
|
i.xattrs = make(map[string]string)
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
2019-01-15 04:33:29 +00:00
|
|
|
i.xattrs[name] = value
|
|
|
|
i.mu.Unlock()
|
2018-04-27 17:37:02 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// Listxattr implements fs.InodeOperations.Listxattr.
|
|
|
|
func (i *InodeSimpleExtendedAttributes) Listxattr(_ *fs.Inode) (map[string]struct{}, error) {
|
|
|
|
i.mu.RLock()
|
|
|
|
names := make(map[string]struct{}, len(i.xattrs))
|
|
|
|
for name := range i.xattrs {
|
|
|
|
names[name] = struct{}{}
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
2019-01-15 04:33:29 +00:00
|
|
|
i.mu.RUnlock()
|
|
|
|
return names, nil
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// staticFile is a file with static contents. It is returned by
|
|
|
|
// InodeStaticFileGetter.GetFile.
|
|
|
|
//
|
|
|
|
// +stateify savable
|
|
|
|
type staticFile struct {
|
2019-04-11 07:41:42 +00:00
|
|
|
FileGenericSeek `state:"nosave"`
|
|
|
|
FileNoIoctl `state:"nosave"`
|
|
|
|
FileNoMMap `state:"nosave"`
|
2019-05-21 22:17:05 +00:00
|
|
|
FileNoSplice `state:"nosave"`
|
2019-04-11 07:41:42 +00:00
|
|
|
FileNoopFsync `state:"nosave"`
|
|
|
|
FileNoopFlush `state:"nosave"`
|
|
|
|
FileNoopRelease `state:"nosave"`
|
|
|
|
FileNoopWrite `state:"nosave"`
|
|
|
|
FileNotDirReaddir `state:"nosave"`
|
|
|
|
FileUseInodeUnstableAttr `state:"nosave"`
|
2019-05-21 22:17:05 +00:00
|
|
|
waiter.AlwaysReady `state:"nosave"`
|
2018-04-27 17:37:02 +00:00
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
FileStaticContentReader
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// InodeNoStatFS implement StatFS by retuning ENOSYS.
|
|
|
|
type InodeNoStatFS struct{}
|
2018-04-27 17:37:02 +00:00
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// StatFS implements fs.InodeOperations.StatFS.
|
|
|
|
func (InodeNoStatFS) StatFS(context.Context) (fs.Info, error) {
|
|
|
|
return fs.Info{}, syserror.ENOSYS
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// InodeStaticFileGetter implements GetFile for a file with static contents.
|
|
|
|
//
|
|
|
|
// +stateify savable
|
|
|
|
type InodeStaticFileGetter struct {
|
|
|
|
Contents []byte
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// GetFile implements fs.InodeOperations.GetFile.
|
|
|
|
func (i *InodeStaticFileGetter) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
|
|
|
return fs.NewFile(ctx, dirent, flags, &staticFile{
|
|
|
|
FileStaticContentReader: NewFileStaticContentReader(i.Contents),
|
|
|
|
}), nil
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// InodeNotMappable returns a nil memmap.Mappable.
|
|
|
|
type InodeNotMappable struct{}
|
2018-04-27 17:37:02 +00:00
|
|
|
|
|
|
|
// Mappable implements fs.InodeOperations.Mappable.
|
2019-01-15 04:33:29 +00:00
|
|
|
func (InodeNotMappable) Mappable(*fs.Inode) memmap.Mappable {
|
2018-04-27 17:37:02 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// InodeNoopWriteOut is a no-op implementation of fs.InodeOperations.WriteOut.
|
|
|
|
type InodeNoopWriteOut struct{}
|
2018-04-27 17:37:02 +00:00
|
|
|
|
|
|
|
// WriteOut is a no-op.
|
2019-01-15 04:33:29 +00:00
|
|
|
func (InodeNoopWriteOut) WriteOut(context.Context, *fs.Inode) error {
|
2018-04-27 17:37:02 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeNotDirectory can be used by Inodes that are not directories.
|
|
|
|
type InodeNotDirectory struct{}
|
|
|
|
|
|
|
|
// Lookup implements fs.InodeOperations.Lookup.
|
|
|
|
func (InodeNotDirectory) Lookup(context.Context, *fs.Inode, string) (*fs.Dirent, error) {
|
|
|
|
return nil, syserror.ENOTDIR
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create implements fs.InodeOperations.Create.
|
|
|
|
func (InodeNotDirectory) Create(context.Context, *fs.Inode, string, fs.FileFlags, fs.FilePermissions) (*fs.File, error) {
|
|
|
|
return nil, syserror.ENOTDIR
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateLink implements fs.InodeOperations.CreateLink.
|
|
|
|
func (InodeNotDirectory) CreateLink(context.Context, *fs.Inode, string, string) error {
|
|
|
|
return syserror.ENOTDIR
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateHardLink implements fs.InodeOperations.CreateHardLink.
|
|
|
|
func (InodeNotDirectory) CreateHardLink(context.Context, *fs.Inode, *fs.Inode, string) error {
|
|
|
|
return syserror.ENOTDIR
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateDirectory implements fs.InodeOperations.CreateDirectory.
|
|
|
|
func (InodeNotDirectory) CreateDirectory(context.Context, *fs.Inode, string, fs.FilePermissions) error {
|
|
|
|
return syserror.ENOTDIR
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bind implements fs.InodeOperations.Bind.
|
2018-10-17 18:36:32 +00:00
|
|
|
func (InodeNotDirectory) Bind(context.Context, *fs.Inode, string, transport.BoundEndpoint, fs.FilePermissions) (*fs.Dirent, error) {
|
2018-08-10 21:31:56 +00:00
|
|
|
return nil, syserror.ENOTDIR
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// CreateFifo implements fs.InodeOperations.CreateFifo.
|
|
|
|
func (InodeNotDirectory) CreateFifo(context.Context, *fs.Inode, string, fs.FilePermissions) error {
|
|
|
|
return syserror.ENOTDIR
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove implements fs.InodeOperations.Remove.
|
|
|
|
func (InodeNotDirectory) Remove(context.Context, *fs.Inode, string) error {
|
|
|
|
return syserror.ENOTDIR
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveDirectory implements fs.InodeOperations.RemoveDirectory.
|
|
|
|
func (InodeNotDirectory) RemoveDirectory(context.Context, *fs.Inode, string) error {
|
|
|
|
return syserror.ENOTDIR
|
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// Rename implements fs.FileOperations.Rename.
|
2019-05-17 20:04:44 +00:00
|
|
|
func (InodeNotDirectory) Rename(context.Context, *fs.Inode, *fs.Inode, string, *fs.Inode, string, bool) error {
|
2019-01-15 04:33:29 +00:00
|
|
|
return syserror.EINVAL
|
|
|
|
}
|
|
|
|
|
2018-04-27 17:37:02 +00:00
|
|
|
// InodeNotSocket can be used by Inodes that are not sockets.
|
|
|
|
type InodeNotSocket struct{}
|
|
|
|
|
|
|
|
// BoundEndpoint implements fs.InodeOperations.BoundEndpoint.
|
2018-10-17 18:36:32 +00:00
|
|
|
func (InodeNotSocket) BoundEndpoint(*fs.Inode, string) transport.BoundEndpoint {
|
2018-04-27 17:37:02 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// InodeNotTruncatable can be used by Inodes that cannot be truncated.
|
|
|
|
type InodeNotTruncatable struct{}
|
|
|
|
|
|
|
|
// Truncate implements fs.InodeOperations.Truncate.
|
|
|
|
func (InodeNotTruncatable) Truncate(context.Context, *fs.Inode, int64) error {
|
|
|
|
return syserror.EINVAL
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeIsDirTruncate implements fs.InodeOperations.Truncate for directories.
|
|
|
|
type InodeIsDirTruncate struct{}
|
|
|
|
|
|
|
|
// Truncate implements fs.InodeOperations.Truncate.
|
|
|
|
func (InodeIsDirTruncate) Truncate(context.Context, *fs.Inode, int64) error {
|
|
|
|
return syserror.EISDIR
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeNoopTruncate implements fs.InodeOperations.Truncate as a noop.
|
|
|
|
type InodeNoopTruncate struct{}
|
|
|
|
|
|
|
|
// Truncate implements fs.InodeOperations.Truncate.
|
|
|
|
func (InodeNoopTruncate) Truncate(context.Context, *fs.Inode, int64) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeNotRenameable can be used by Inodes that cannot be truncated.
|
2018-04-27 17:37:02 +00:00
|
|
|
type InodeNotRenameable struct{}
|
|
|
|
|
|
|
|
// Rename implements fs.InodeOperations.Rename.
|
2019-05-17 20:04:44 +00:00
|
|
|
func (InodeNotRenameable) Rename(context.Context, *fs.Inode, *fs.Inode, string, *fs.Inode, string, bool) error {
|
2018-04-27 17:37:02 +00:00
|
|
|
return syserror.EINVAL
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeNotOpenable can be used by Inodes that cannot be opened.
|
|
|
|
type InodeNotOpenable struct{}
|
|
|
|
|
|
|
|
// GetFile implements fs.InodeOperations.GetFile.
|
|
|
|
func (InodeNotOpenable) GetFile(context.Context, *fs.Dirent, fs.FileFlags) (*fs.File, error) {
|
|
|
|
return nil, syserror.EIO
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeNotVirtual can be used by Inodes that are not virtual.
|
|
|
|
type InodeNotVirtual struct{}
|
|
|
|
|
|
|
|
// IsVirtual implements fs.InodeOperations.IsVirtual.
|
|
|
|
func (InodeNotVirtual) IsVirtual() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// InodeVirtual can be used by Inodes that are virtual.
|
|
|
|
type InodeVirtual struct{}
|
|
|
|
|
|
|
|
// IsVirtual implements fs.InodeOperations.IsVirtual.
|
|
|
|
func (InodeVirtual) IsVirtual() bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-04-27 17:37:02 +00:00
|
|
|
// InodeNotSymlink can be used by Inodes that are not symlinks.
|
|
|
|
type InodeNotSymlink struct{}
|
|
|
|
|
|
|
|
// Readlink implements fs.InodeOperations.Readlink.
|
|
|
|
func (InodeNotSymlink) Readlink(context.Context, *fs.Inode) (string, error) {
|
|
|
|
return "", syserror.ENOLINK
|
|
|
|
}
|
|
|
|
|
|
|
|
// Getlink implements fs.InodeOperations.Getlink.
|
|
|
|
func (InodeNotSymlink) Getlink(context.Context, *fs.Inode) (*fs.Dirent, error) {
|
|
|
|
return nil, syserror.ENOLINK
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeNoExtendedAttributes can be used by Inodes that do not support
|
|
|
|
// extended attributes.
|
|
|
|
type InodeNoExtendedAttributes struct{}
|
|
|
|
|
|
|
|
// Getxattr implements fs.InodeOperations.Getxattr.
|
2019-04-05 22:48:26 +00:00
|
|
|
func (InodeNoExtendedAttributes) Getxattr(*fs.Inode, string) (string, error) {
|
|
|
|
return "", syserror.EOPNOTSUPP
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Setxattr implements fs.InodeOperations.Setxattr.
|
2019-04-05 22:48:26 +00:00
|
|
|
func (InodeNoExtendedAttributes) Setxattr(*fs.Inode, string, string) error {
|
2018-04-27 17:37:02 +00:00
|
|
|
return syserror.EOPNOTSUPP
|
|
|
|
}
|
|
|
|
|
|
|
|
// Listxattr implements fs.InodeOperations.Listxattr.
|
|
|
|
func (InodeNoExtendedAttributes) Listxattr(*fs.Inode) (map[string]struct{}, error) {
|
|
|
|
return nil, syserror.EOPNOTSUPP
|
|
|
|
}
|
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// InodeNoopRelease implements fs.InodeOperations.Release as a noop.
|
|
|
|
type InodeNoopRelease struct{}
|
2018-04-27 17:37:02 +00:00
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// Release implements fs.InodeOperations.Release.
|
|
|
|
func (InodeNoopRelease) Release(context.Context) {}
|
2018-04-27 17:37:02 +00:00
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// InodeGenericChecker implements fs.InodeOperations.Check with a generic
|
|
|
|
// implementation.
|
|
|
|
type InodeGenericChecker struct{}
|
2018-04-27 17:37:02 +00:00
|
|
|
|
2019-01-15 04:33:29 +00:00
|
|
|
// Check implements fs.InodeOperations.Check.
|
|
|
|
func (InodeGenericChecker) Check(ctx context.Context, inode *fs.Inode, p fs.PermMask) bool {
|
|
|
|
return fs.ContextCanAccessFile(ctx, inode, p)
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
2019-04-10 17:48:28 +00:00
|
|
|
|
|
|
|
// InodeDenyWriteChecker implements fs.InodeOperations.Check which denies all
|
|
|
|
// write operations.
|
|
|
|
type InodeDenyWriteChecker struct{}
|
|
|
|
|
|
|
|
// Check implements fs.InodeOperations.Check.
|
|
|
|
func (InodeDenyWriteChecker) Check(ctx context.Context, inode *fs.Inode, p fs.PermMask) bool {
|
|
|
|
if p.Write {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return fs.ContextCanAccessFile(ctx, inode, p)
|
|
|
|
}
|
2019-05-09 22:34:44 +00:00
|
|
|
|
|
|
|
//InodeNotAllocatable can be used by Inodes that do not support Allocate().
|
|
|
|
type InodeNotAllocatable struct{}
|
|
|
|
|
|
|
|
func (InodeNotAllocatable) Allocate(_ context.Context, _ *fs.Inode, _, _ int64) error {
|
|
|
|
return syserror.EOPNOTSUPP
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeNoopAllocate implements fs.InodeOperations.Allocate as a noop.
|
|
|
|
type InodeNoopAllocate struct{}
|
|
|
|
|
|
|
|
// Allocate implements fs.InodeOperations.Allocate.
|
|
|
|
func (InodeNoopAllocate) Allocate(_ context.Context, _ *fs.Inode, _, _ int64) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// InodeIsDirAllocate implements fs.InodeOperations.Allocate for directories.
|
|
|
|
type InodeIsDirAllocate struct{}
|
|
|
|
|
|
|
|
// Allocate implements fs.InodeOperations.Allocate.
|
|
|
|
func (InodeIsDirAllocate) Allocate(_ context.Context, _ *fs.Inode, _, _ int64) error {
|
|
|
|
return syserror.EISDIR
|
|
|
|
}
|