diff --git a/drivers/driver.go b/drivers/driver.go index 9edb279c..348435cd 100644 --- a/drivers/driver.go +++ b/drivers/driver.go @@ -4,7 +4,6 @@ import ( "github.com/Xhofe/alist/model" "github.com/gin-gonic/gin" "github.com/go-resty/resty/v2" - log "github.com/sirupsen/logrus" "net/http" ) @@ -49,7 +48,7 @@ type TokenResp struct { var driversMap = map[string]Driver{} func RegisterDriver(driver Driver) { - log.Infof("register driver: [%s]", driver.Config().Name) + //log.Infof("register driver: [%s]", driver.Config().Name) driversMap[driver.Config().Name] = driver } diff --git a/drivers/native.go b/drivers/native.go index f338f207..aee2ed3d 100644 --- a/drivers/native.go +++ b/drivers/native.go @@ -1,5 +1,73 @@ package drivers +import ( + "fmt" + "io" + "io/ioutil" + "os" + "path" +) + +// File copies a single file from src to dst +func (driver *Native) CopyFile(src, dst string) error { + var err error + var srcfd *os.File + var dstfd *os.File + var srcinfo os.FileInfo + + if srcfd, err = os.Open(src); err != nil { + return err + } + defer srcfd.Close() + + if dstfd, err = os.Create(dst); err != nil { + return err + } + defer dstfd.Close() + + if _, err = io.Copy(dstfd, srcfd); err != nil { + return err + } + if srcinfo, err = os.Stat(src); err != nil { + return err + } + return os.Chmod(dst, srcinfo.Mode()) +} + +// Dir copies a whole directory recursively +func (driver *Native) CopyDir(src string, dst string) error { + var err error + var fds []os.FileInfo + var srcinfo os.FileInfo + + if srcinfo, err = os.Stat(src); err != nil { + return err + } + + if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil { + return err + } + + if fds, err = ioutil.ReadDir(src); err != nil { + return err + } + for _, fd := range fds { + srcfp := path.Join(src, fd.Name()) + dstfp := path.Join(dst, fd.Name()) + + if fd.IsDir() { + if err = driver.CopyDir(srcfp, dstfp); err != nil { + fmt.Println(err) + } + } else { + if err = driver.CopyFile(srcfp, dstfp); err != nil { + fmt.Println(err) + } + } + } + return nil +} + func init() { RegisterDriver(&Native{}) } diff --git a/drivers/native_driver.go b/drivers/native_driver.go index 80dc2a76..eedfcb83 100644 --- a/drivers/native_driver.go +++ b/drivers/native_driver.go @@ -7,6 +7,7 @@ import ( "github.com/Xhofe/alist/utils" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" + "io" "io/ioutil" "os" "path/filepath" @@ -15,10 +16,9 @@ import ( type Native struct{} - func (driver Native) Config() DriverConfig { return DriverConfig{ - Name: "Native", + Name: "Native", OnlyProxy: true, } } @@ -160,22 +160,70 @@ func (driver Native) Preview(path string, account *model.Account) (interface{}, } func (driver Native) MakeDir(path string, account *model.Account) error { - return ErrNotImplement + fullPath := filepath.Join(account.RootFolder, path) + err := os.MkdirAll(fullPath, 0700) + return err } func (driver Native) Move(src string, dst string, account *model.Account) error { - return ErrNotImplement + fullSrc := filepath.Join(account.RootFolder, src) + fullDst := filepath.Join(account.RootFolder, dst) + return os.Rename(fullSrc, fullDst) } func (driver Native) Copy(src string, dst string, account *model.Account) error { - return ErrNotImplement + fullSrc := filepath.Join(account.RootFolder, src) + fullDst := filepath.Join(account.RootFolder, dst) + srcFile, err := driver.File(src, account) + if err != nil { + return err + } + dstFile, err := driver.File(dst, account) + if err == nil { + if !dstFile.IsDir() { + return ErrNotSupport + } + } + if srcFile.IsDir() { + return driver.CopyDir(fullSrc, fullDst) + } + return driver.CopyFile(fullSrc, fullDst) } func (driver Native) Delete(path string, account *model.Account) error { - return ErrNotImplement + fullPath := filepath.Join(account.RootFolder, path) + file, err := driver.File(path, account) + if err != nil { + return err + } + if file.IsDir() { + return os.RemoveAll(fullPath) + } + return os.Remove(fullPath) } func (driver Native) Upload(file *model.FileStream, account *model.Account) error { - return ErrNotImplement + fullPath := filepath.Join(account.RootFolder, file.Path, file.Name) + _, err := driver.File(filepath.Join(file.Path,file.Name), account) + if err == nil { + // TODO overwrite? + } + basePath := filepath.Dir(fullPath) + if !utils.Exists(basePath) { + err := os.MkdirAll(basePath, 0744) + if err != nil { + return err + } + } + out, err := os.Create(fullPath) + if err != nil { + return err + } + defer func() { + _ = out.Close() + }() + _, err = io.Copy(out, file) + return err } + var _ Driver = (*Native)(nil) diff --git a/server/webdav/file.go b/server/webdav/file.go index fe4dd374..c834600d 100644 --- a/server/webdav/file.go +++ b/server/webdav/file.go @@ -130,8 +130,19 @@ func (fs *FileSystem) Link(r *http.Request, rawPath string) (string, error) { return link, err } -func (fs *FileSystem) CreateDirectory(ctx context.Context, reqPath string) (interface{}, error) { - return nil, nil +func (fs *FileSystem) CreateDirectory(ctx context.Context, rawPath string) error { + rawPath = utils.ParsePath(rawPath) + if rawPath == "/" { + return ErrNotImplemented + } + if model.AccountsCount() > 1 && len(strings.Split(rawPath, "/")) < 2 { + return ErrNotImplemented + } + account, path_, driver, err := ParsePath(rawPath) + if err != nil { + return err + } + return driver.MakeDir(path_,account) } func (fs *FileSystem) Upload(ctx context.Context, r *http.Request, rawPath string) error { diff --git a/server/webdav/webdav.go b/server/webdav/webdav.go index ed2eb0c8..2823aa7c 100644 --- a/server/webdav/webdav.go +++ b/server/webdav/webdav.go @@ -281,7 +281,8 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request, fs *FileSyst return http.StatusMethodNotAllowed, err } - etag, err := findETag(ctx, fs, h.LockSystem, reqPath, nil) + _, fi := isPathExist(ctx, fs, reqPath) + etag, err := findETag(ctx, fs, h.LockSystem, reqPath, fi) if err != nil { return http.StatusInternalServerError, err } @@ -311,7 +312,7 @@ func (h *Handler) handleMkcol(w http.ResponseWriter, r *http.Request, fs *FileSy // ctx = context.WithValue(ctx, fsctx.IgnoreDirectoryConflictCtx, true) //} } - if _, err := fs.CreateDirectory(ctx, reqPath); err != nil { + if err := fs.CreateDirectory(ctx, reqPath); err != nil { return http.StatusConflict, err } return http.StatusCreated, nil