// Copyright (C) 2019 Marius Schellenberger package authdav import ( "context" "errors" "golang.org/x/net/webdav" "os" ) // ErrWonly indicates forbidden operation var ErrWonly = errors.New("authdav: only file write once operations permitted") const writeFlag = os.O_RDWR | os.O_CREATE | os.O_TRUNC // WriteOnlyOnceFileSystem is a file write only wrapper for a webdav.FileSystem type WriteOnlyOnceFileSystem struct { fs webdav.FileSystem } // NewWriteOnlyOnceFileSystem returns a new WriteOnlyOnceFileSystem wrapping a webdav.FileSystem func NewWriteOnlyOnceFileSystem(fs webdav.FileSystem) *WriteOnlyOnceFileSystem { return &WriteOnlyOnceFileSystem{fs} } // Mkdir is not permitted func (fs *WriteOnlyOnceFileSystem) Mkdir(ctx context.Context, name string, perm os.FileMode) error { return ErrWonly } // OpenFile allows write only once operations func (fs *WriteOnlyOnceFileSystem) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) { fi, err := fs.Stat(ctx, name) if err == nil && fi.Mode().IsRegular() { f, ok := fi.(*FileInfo) if ok && flag == writeFlag && f.RealSize() > 0 { return nil, ErrWonly } } f, err := fs.fs.OpenFile(ctx, name, flag, perm) if err != nil { return nil, err } return &File{f}, nil } // RemoveAll is not permitted func (fs *WriteOnlyOnceFileSystem) RemoveAll(ctx context.Context, name string) error { return ErrWonly } // Rename is not permitted func (fs *WriteOnlyOnceFileSystem) Rename(ctx context.Context, oldName, newName string) error { return ErrWonly } // Stat returns os.FileInfo wrapped in FileInfo func (fs *WriteOnlyOnceFileSystem) Stat(ctx context.Context, name string) (os.FileInfo, error) { fi, err := fs.fs.Stat(ctx, name) if err != nil { return nil, err } return &FileInfo{fi}, nil }