diff --git a/pkg/storage/utils/decomposedfs/decomposedfs.go b/pkg/storage/utils/decomposedfs/decomposedfs.go index 873f136942..ebbb7f9a30 100644 --- a/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -163,7 +163,7 @@ func (fs *Decomposedfs) GetQuota(ctx context.Context, ref *provider.Reference) ( quotaStr = string(ri.Opaque.Map["quota"].Value) } - avail, err := fs.getAvailableSize(n.InternalPath()) + avail, err := node.GetAvailableSize(n.InternalPath()) if err != nil { return 0, 0, err } diff --git a/pkg/storage/utils/decomposedfs/node/node.go b/pkg/storage/utils/decomposedfs/node/node.go index 9871548576..696177f4a5 100644 --- a/pkg/storage/utils/decomposedfs/node/node.go +++ b/pkg/storage/utils/decomposedfs/node/node.go @@ -938,3 +938,31 @@ func parseMTime(v string) (t time.Time, err error) { } return time.Unix(sec, nsec), err } + +// CheckQuota checks if both disk space and available quota are sufficient +var CheckQuota = func(spaceRoot *Node, fileSize uint64) (quotaSufficient bool, err error) { + used, _ := spaceRoot.GetTreeSize() + if !enoughDiskSpace(spaceRoot.InternalPath(), fileSize) { + return false, errtypes.InsufficientStorage("disk full") + } + quotaByte, _ := xattr.Get(spaceRoot.InternalPath(), xattrs.QuotaAttr) + var total uint64 + if quotaByte == nil { + // if quota is not set, it means unlimited + return true, nil + } + total, _ = strconv.ParseUint(string(quotaByte), 10, 64) + // if total is smaller that used, total-used could overflow and be bigger than fileSize + if fileSize > total-used || total < used { + return false, errtypes.InsufficientStorage("quota exceeded") + } + return true, nil +} + +func enoughDiskSpace(path string, fileSize uint64) bool { + avalB, err := GetAvailableSize(path) + if err != nil { + return false + } + return avalB > fileSize +} diff --git a/pkg/storage/utils/decomposedfs/decomposedfs_unix.go b/pkg/storage/utils/decomposedfs/node/node_unix.go similarity index 87% rename from pkg/storage/utils/decomposedfs/decomposedfs_unix.go rename to pkg/storage/utils/decomposedfs/node/node_unix.go index d5b7507002..05edf02158 100644 --- a/pkg/storage/utils/decomposedfs/decomposedfs_unix.go +++ b/pkg/storage/utils/decomposedfs/node/node_unix.go @@ -19,11 +19,12 @@ //go:build !windows // +build !windows -package decomposedfs +package node import "syscall" -func (fs *Decomposedfs) getAvailableSize(path string) (uint64, error) { +// GetAvailableSize stats the filesystem and return the available bytes +func GetAvailableSize(path string) (uint64, error) { stat := syscall.Statfs_t{} err := syscall.Statfs(path, &stat) if err != nil { diff --git a/pkg/storage/utils/decomposedfs/decomposedfs_windows.go b/pkg/storage/utils/decomposedfs/node/node_windows.go similarity index 88% rename from pkg/storage/utils/decomposedfs/decomposedfs_windows.go rename to pkg/storage/utils/decomposedfs/node/node_windows.go index e4a6c18236..55febbbd88 100644 --- a/pkg/storage/utils/decomposedfs/decomposedfs_windows.go +++ b/pkg/storage/utils/decomposedfs/node/node_windows.go @@ -19,11 +19,12 @@ //go:build windows // +build windows -package decomposedfs +package node import "golang.org/x/sys/windows" -func (fs *Decomposedfs) getAvailableSize(path string) (uint64, error) { +// GetAvailableSize stats the filesystem and return the available bytes +func GetAvailableSize(path string) (uint64, error) { var free, total, avail uint64 pathPtr, err := windows.UTF16PtrFromString(path) if err != nil { diff --git a/pkg/storage/utils/decomposedfs/upload.go b/pkg/storage/utils/decomposedfs/upload.go index 1c63cb794b..cde8729dac 100644 --- a/pkg/storage/utils/decomposedfs/upload.go +++ b/pkg/storage/utils/decomposedfs/upload.go @@ -31,7 +31,6 @@ import ( "io/ioutil" "os" "path/filepath" - "strconv" "strings" "time" @@ -43,11 +42,9 @@ import ( "github.com/cs3org/reva/pkg/logger" "github.com/cs3org/reva/pkg/storage/utils/chunking" "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/node" - "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/xattrs" "github.com/cs3org/reva/pkg/utils" "github.com/google/uuid" "github.com/pkg/errors" - "github.com/pkg/xattr" "github.com/rs/zerolog" tusd "github.com/tus/tusd/pkg/handler" ) @@ -110,35 +107,6 @@ func (fs *Decomposedfs) Upload(ctx context.Context, ref *provider.Reference, r i return uploadInfo.FinishUpload(ctx) } -// CheckQuota checks if both disk space and available quota are sufficient -var CheckQuota = func(ctx context.Context, fs *Decomposedfs, spaceRoot *node.Node, fileSize uint64) (quotaSufficient bool, err error) { - used, _ := spaceRoot.GetTreeSize() - if !enoughDiskSpace(fs, spaceRoot.InternalPath(), fileSize) { - return false, errtypes.InsufficientStorage("disk full") - } - quotaByte, _ := xattr.Get(spaceRoot.InternalPath(), xattrs.QuotaAttr) - var total uint64 - if quotaByte == nil { - // if quota is not set, it means unlimited - return true, nil - } - total, _ = strconv.ParseUint(string(quotaByte), 10, 64) - // if total is smaller that used, total-used could overflow and be bigger than fileSize - if fileSize > total-used || total < used { - return false, errtypes.InsufficientStorage("quota exceeded") - } - return true, nil -} - -func enoughDiskSpace(fs *Decomposedfs, path string, fileSize uint64) bool { - avalB, err := fs.getAvailableSize(path) - if err != nil { - return false - } - - return avalB > fileSize -} - // InitiateUpload returns upload ids corresponding to different protocols it supports // TODO read optional content for small files in this request // TODO InitiateUpload (and Upload) needs a way to receive the expected checksum. Maybe in metadata as 'checksum' => 'sha1 aeosvp45w5xaeoe' = lowercase, space separated? @@ -192,7 +160,7 @@ func (fs *Decomposedfs) InitiateUpload(ctx context.Context, ref *provider.Refere log.Debug().Interface("info", info).Interface("node", n).Interface("metadata", metadata).Msg("Decomposedfs: resolved filename") - _, err = CheckQuota(ctx, fs, n.SpaceRoot, uint64(info.Size)) + _, err = node.CheckQuota(n.SpaceRoot, uint64(info.Size)) if err != nil { return nil, err } @@ -515,7 +483,7 @@ func (upload *fileUpload) FinishUpload(ctx context.Context) (err error) { ) n.SpaceRoot = node.New(upload.info.Storage["SpaceRoot"], "", "", 0, "", nil, upload.fs.lu) - _, err = CheckQuota(upload.ctx, upload.fs, n.SpaceRoot, uint64(fi.Size())) + _, err = node.CheckQuota(n.SpaceRoot, uint64(fi.Size())) if err != nil { return err } diff --git a/pkg/storage/utils/decomposedfs/upload_test.go b/pkg/storage/utils/decomposedfs/upload_test.go index 6dea19be9e..26d492d9a7 100644 --- a/pkg/storage/utils/decomposedfs/upload_test.go +++ b/pkg/storage/utils/decomposedfs/upload_test.go @@ -101,13 +101,13 @@ var _ = Describe("File uploads", func() { Context("quota exceeded", func() { Describe("InitiateUpload", func() { It("fails", func() { - var originalFunc = decomposedfs.CheckQuota - decomposedfs.CheckQuota = func(ctx context.Context, fs *decomposedfs.Decomposedfs, spaceRoot *node.Node, fileSize uint64) (quotaSufficient bool, err error) { + var originalFunc = node.CheckQuota + node.CheckQuota = func(spaceRoot *node.Node, fileSize uint64) (quotaSufficient bool, err error) { return false, errtypes.InsufficientStorage("quota exceeded") } _, err := fs.InitiateUpload(ctx, ref, 10, map[string]string{}) Expect(err).To(MatchError(errtypes.InsufficientStorage("quota exceeded"))) - decomposedfs.CheckQuota = originalFunc + node.CheckQuota = originalFunc }) }) })