1
0
Fork 0
authdav/filesystem.go
2019-09-02 09:42:41 +02:00

79 lines
2.1 KiB
Go

// 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 {
Filters []Filter
fs webdav.FileSystem
}
// NewWriteOnlyOnceFileSystem returns a new WriteOnlyOnceFileSystem wrapping a webdav.FileSystem
func NewWriteOnlyOnceFileSystem(fs webdav.FileSystem) *WriteOnlyOnceFileSystem {
return &WriteOnlyOnceFileSystem{fs: 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
}
}
for _, filter := range fs.Filters {
err = filter.Filter(name)
if err != nil {
return nil, err
}
}
f, err := fs.fs.OpenFile(ctx, name, flag, perm)
if err != nil {
return nil, err
}
return &File{f}, nil
}
// RemoveAll only permits deleting empty files
func (fs *WriteOnlyOnceFileSystem) RemoveAll(ctx context.Context, name string) error {
fi, err := fs.fs.Stat(ctx, name)
if err != nil {
return err
}
if fi.Mode().IsRegular() && fi.Size() == 0 {
return fs.fs.RemoveAll(ctx, name)
}
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
}