Files
filestash/server/model/webdav.go
2019-01-28 01:09:45 +11:00

214 lines
4.9 KiB
Go

package model
import (
"os"
"context"
. "github.com/mickael-kerjean/filestash/server/common"
"github.com/mickael-kerjean/net/webdav"
"path/filepath"
"strings"
"io"
)
const DAVCachePath = "data/cache/webdav/"
var cachePath string
func init() {
cachePath = filepath.Join(GetCurrentDir(), DAVCachePath) + "/"
os.RemoveAll(cachePath)
os.MkdirAll(cachePath, os.ModePerm)
}
type WebdavFs struct {
backend IBackend
path string
}
func NewWebdavFs(b IBackend, path string) WebdavFs {
return WebdavFs{
backend: b,
path: path,
}
}
func (fs WebdavFs) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
Log.Info("MKDIR ('%s')", name)
if name = fs.resolve(name); name == "" {
return os.ErrInvalid
}
return fs.backend.Mkdir(name)
}
func (fs WebdavFs) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
Log.Info("OPEN_FILE ('%s')", name)
return NewWebdavNode(name, fs), nil
}
func (fs WebdavFs) RemoveAll(ctx context.Context, name string) error {
Log.Info("RM ('%s')", name)
if name = fs.resolve(name); name == "" {
return os.ErrInvalid
}
return fs.backend.Rm(name)
}
func (fs WebdavFs) Rename(ctx context.Context, oldName, newName string) error {
Log.Info("MV ('%s' => '%s')", oldName, newName)
if oldName = fs.resolve(oldName); oldName == "" {
return os.ErrInvalid
}
if newName = fs.resolve(newName); newName == "" {
return os.ErrInvalid
}
return fs.backend.Mv(oldName, newName)
}
func (fs WebdavFs) Stat(ctx context.Context, name string) (os.FileInfo, error) {
Log.Info("STAT ('%s')", name)
if name = fs.resolve(name); name == "" {
return nil, os.ErrInvalid
}
if obj, ok := fs.backend.(interface{ Stat(path string) (os.FileInfo, error) }); ok {
return obj.Stat(name)
}
return nil, os.ErrInvalid
}
func (fs WebdavFs) resolve(path string) string {
p := filepath.Join(fs.path, path)
if strings.HasSuffix(path, "/") == true && strings.HasSuffix(p, "/") == false {
p += "/"
}
if strings.HasPrefix(p, fs.path) == true {
return p
}
return ""
}
type WebdavNode struct {
fs WebdavFs
path string
fileread *os.File
filewrite *os.File
}
func NewWebdavNode(name string, fs WebdavFs) *WebdavNode {
return &WebdavNode{
fs: fs,
path: name,
}
}
func (w *WebdavNode) Readdir(count int) ([]os.FileInfo, error) {
Log.Info(" => READ_DIR ('%s')", w.path)
var path string
if path = w.fs.resolve(w.path); path == "" {
return nil, os.ErrInvalid
}
return w.fs.backend.Ls(path)
}
func (w *WebdavNode) Stat() (os.FileInfo, error) {
Log.Info(" => STAT ('%s')", w.path)
// if w.filewrite != nil {
// var path stringc
// var err error
// if path = w.fs.resolve(w.path); path == "" {
// return nil, os.ErrInvalid
// }
// name := w.filewrite.Name()
// w.filewrite.Close()
// if w.filewrite, err = os.OpenFile(name, os.O_RDONLY, os.ModePerm); err != nil {
// return nil, os.ErrInvalid
// }
// if err = w.fs.backend.Save(path, w.filewrite); err != nil {
// return nil, err
// }
// }
return w.fs.Stat(context.Background(), w.path)
}
func (w *WebdavNode) Close() error {
Log.Info(" => CLOSE ('%s')", w.path)
if w.fileread != nil {
if err := w.cleanup(w.fileread); err != nil {
return err
}
w.fileread = nil
}
if w.filewrite != nil {
defer w.cleanup(w.filewrite)
name := w.filewrite.Name()
w.filewrite.Close()
reader, err := os.OpenFile(name, os.O_RDONLY, os.ModePerm);
if err != nil {
return os.ErrInvalid
}
path := w.fs.resolve(w.path)
if path == "" {
return os.ErrInvalid
}
if err := w.fs.backend.Save(path, reader); err != nil {
return err
}
reader.Close()
}
return nil
}
func (w *WebdavNode) Read(p []byte) (int, error) {
Log.Info(" => READ ('%s')", w.path)
if w.fileread != nil {
return w.fileread.Read(p)
}
return -1, os.ErrInvalid
}
func (w *WebdavNode) Seek(offset int64, whence int) (int64, error) {
Log.Info(" => SEEK ('%s')", w.path)
var path string
var err error
if path = w.fs.resolve(w.path); path == "" {
return 0, os.ErrInvalid
}
if w.fileread == nil {
var reader io.Reader
if w.fileread, err = os.OpenFile(cachePath + "tmp_" + QuickString(10), os.O_WRONLY|os.O_CREATE|os.O_EXCL, os.ModePerm); err != nil {
return 0, os.ErrInvalid
}
if reader, err = w.fs.backend.Cat(path); err != nil {
return 0, os.ErrInvalid
}
io.Copy(w.fileread, reader)
name := w.fileread.Name()
w.fileread.Close()
w.fileread, err = os.OpenFile(name, os.O_RDONLY, os.ModePerm)
}
return w.fileread.Seek(offset, whence)
}
func (w *WebdavNode) Write(p []byte) (int, error) {
Log.Info(" => WRITE ('%s')", w.path)
var err error
if w.filewrite == nil {
if w.filewrite, err = os.OpenFile(cachePath + "tmp_" + QuickString(10), os.O_WRONLY|os.O_CREATE|os.O_EXCL, os.ModePerm); err != nil {
return 0, os.ErrInvalid
}
}
return w.filewrite.Write(p)
}
func (w *WebdavNode) cleanup(file *os.File) error {
name := file.Name()
file.Close();
os.Remove(name);
return nil
}