From 0010f0ee1023cc429bae2b514296ecdcac33cdc4 Mon Sep 17 00:00:00 2001 From: Krishna Srinivas Date: Thu, 29 Oct 2015 15:09:29 -0700 Subject: [PATCH] Remove empty directories while removing an oobject --- pkg/fs/fs-object.go | 46 ++++++++++++++++++++++++++++++++++++--------- pkg/fs/fs-utils.go | 20 ++++++++++++++++++++ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/pkg/fs/fs-object.go b/pkg/fs/fs-object.go index 9747db3c2..98b04797a 100644 --- a/pkg/fs/fs-object.go +++ b/pkg/fs/fs-object.go @@ -268,6 +268,37 @@ func (fs Filesystem) CreateObject(bucket, object, expectedMD5Sum string, size in return newObject, nil } +func deleteObjectPath(basePath, deletePath, bucket, object string) *probe.Error { + if basePath == deletePath { + return nil + } + + fi, err := os.Stat(deletePath) + if err != nil { + if os.IsNotExist(err) { + return probe.NewError(ObjectNotFound{Bucket: bucket, Object: object}) + } + return probe.NewError(err) + } + if fi.IsDir() { + empty, err := isDirEmpty(deletePath) + if err != nil { + return err.Trace() + } + if !empty { + return nil + } + } + + if err := os.Remove(deletePath); err != nil { + return probe.NewError(err) + } + if err := deleteObjectPath(basePath, filepath.Dir(deletePath), bucket, object); err != nil { + return err.Trace() + } + return nil +} + // DeleteObject - delete and object func (fs Filesystem) DeleteObject(bucket, object string) *probe.Error { fs.lock.Lock() @@ -278,6 +309,7 @@ func (fs Filesystem) DeleteObject(bucket, object string) *probe.Error { return probe.NewError(BucketNameInvalid{Bucket: bucket}) } + bucketPath := filepath.Join(fs.path, bucket) // check bucket exists if _, err := os.Stat(filepath.Join(fs.path, bucket)); os.IsNotExist(err) { return probe.NewError(BucketNotFound{Bucket: bucket}) @@ -296,16 +328,12 @@ func (fs Filesystem) DeleteObject(bucket, object string) *probe.Error { } else { objectPath = fs.path + string(os.PathSeparator) + bucket + string(os.PathSeparator) + object } - - _, err := os.Stat(objectPath) - if err != nil { - if os.IsNotExist(err) { - return probe.NewError(ObjectNotFound{Bucket: bucket, Object: object}) - } - return probe.NewError(err) + err := deleteObjectPath(bucketPath, objectPath, bucket, object) + if os.IsNotExist(err.ToGoError()) { + return probe.NewError(ObjectNotFound{Bucket: bucket, Object: object}) } - if err := os.Remove(objectPath); err != nil { - return probe.NewError(err) + if err != nil { + return err.Trace() } return nil } diff --git a/pkg/fs/fs-utils.go b/pkg/fs/fs-utils.go index 0d0c188fe..244854ef8 100644 --- a/pkg/fs/fs-utils.go +++ b/pkg/fs/fs-utils.go @@ -18,11 +18,31 @@ package fs import ( "errors" + "io" "os" "path/filepath" "sort" + + "github.com/minio/minio-xl/pkg/probe" ) +// Check if a directory is empty +func isDirEmpty(dirname string) (bool, *probe.Error) { + f, err := os.Open(dirname) + defer f.Close() + if err != nil { + return false, probe.NewError(err) + } + names, err := f.Readdirnames(1) + if err != nil && err != io.EOF { + return false, probe.NewError(err) + } + if len(names) > 0 { + return false, nil + } + return true, nil +} + // RemoveAllDirs - removes only itself and all subdirectories func RemoveAllDirs(path string) error { allFiles := func(fp string, fl os.FileInfo, err error) error {