From f31e4aea9c486a56d3d1c4c225bf1b3c38a34b88 Mon Sep 17 00:00:00 2001 From: Felicitas Pojtinger Date: Fri, 7 Jan 2022 19:57:01 +0100 Subject: [PATCH] refactor: Decompose drive initialization to `fs` package, add getters for operations --- cmd/stfs/cmd/serve_ftp.go | 66 +--------------------------- examples/fs/main.go | 66 +--------------------------- pkg/fs/filesystem.go | 83 ++++++++++++++++++++++++++++-------- pkg/operations/operations.go | 16 +++++++ 4 files changed, 86 insertions(+), 145 deletions(-) diff --git a/cmd/stfs/cmd/serve_ftp.go b/cmd/stfs/cmd/serve_ftp.go index b896f9e..f8f7cfb 100644 --- a/cmd/stfs/cmd/serve_ftp.go +++ b/cmd/stfs/cmd/serve_ftp.go @@ -1,8 +1,6 @@ package cmd import ( - "archive/tar" - "context" "fmt" "os" "path/filepath" @@ -15,13 +13,10 @@ import ( "github.com/pojntfx/stfs/internal/logging" "github.com/pojntfx/stfs/pkg/cache" "github.com/pojntfx/stfs/pkg/config" - "github.com/pojntfx/stfs/pkg/encryption" sfs "github.com/pojntfx/stfs/pkg/fs" "github.com/pojntfx/stfs/pkg/keys" "github.com/pojntfx/stfs/pkg/operations" "github.com/pojntfx/stfs/pkg/persisters" - "github.com/pojntfx/stfs/pkg/recovery" - "github.com/pojntfx/stfs/pkg/signature" "github.com/pojntfx/stfs/pkg/tape" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -206,66 +201,9 @@ var serveFTPCmd = &cobra.Command{ jsonLogger, ) - root, err := metadataPersister.GetRootPath(context.Background()) + root, err := stfs.Initialize("/", os.ModePerm) if err != nil { - if err == config.ErrNoRootDirectory { - root = "/" - - drive, err := tm.GetDrive() - if err == nil { - err = recovery.Index( - config.DriveReaderConfig{ - Drive: drive.Drive, - DriveIsRegular: drive.DriveIsRegular, - }, - config.DriveConfig{ - Drive: drive.Drive, - DriveIsRegular: drive.DriveIsRegular, - }, - metadataConfig, - pipeConfig, - readCryptoConfig, - - viper.GetInt(recordSizeFlag), - 0, - 0, - true, - 0, - - func(hdr *tar.Header, i int) error { - return encryption.DecryptHeader(hdr, viper.GetString(encryptionFlag), encryptionIdentity) - }, - func(hdr *tar.Header, isRegular bool) error { - return signature.VerifyHeader(hdr, isRegular, viper.GetString(signatureFlag), signatureRecipient) - }, - - func(hdr *config.Header) { - jsonLogger.Debug("Header read", hdr) - }, - ) - if err != nil { - if err := tm.Close(); err != nil { - return err - } - - if err := stfs.MkdirRoot(root, os.ModePerm); err != nil { - return err - } - } - } else if os.IsNotExist(err) { - if err := tm.Close(); err != nil { - return err - } - - if err := stfs.MkdirRoot(root, os.ModePerm); err != nil { - return err - } - } else { - return err - } - } else { - return err - } + return err } fs, err := cache.NewCacheFilesystem( diff --git a/examples/fs/main.go b/examples/fs/main.go index aff0c41..2bf5579 100644 --- a/examples/fs/main.go +++ b/examples/fs/main.go @@ -1,8 +1,6 @@ package main import ( - "archive/tar" - "context" "encoding/json" "flag" "log" @@ -11,12 +9,9 @@ import ( "github.com/pojntfx/stfs/pkg/cache" "github.com/pojntfx/stfs/pkg/config" - "github.com/pojntfx/stfs/pkg/encryption" sfs "github.com/pojntfx/stfs/pkg/fs" "github.com/pojntfx/stfs/pkg/operations" "github.com/pojntfx/stfs/pkg/persisters" - "github.com/pojntfx/stfs/pkg/recovery" - "github.com/pojntfx/stfs/pkg/signature" "github.com/pojntfx/stfs/pkg/tape" golog "github.com/fclairamb/go-log" @@ -152,66 +147,9 @@ func main() { l, ) - root, err := metadataPersister.GetRootPath(context.Background()) + root, err := stfs.Initialize("/", os.ModePerm) if err != nil { - if err == config.ErrNoRootDirectory { - root = "/" - - drive, err := tm.GetDrive() - if err == nil { - err = recovery.Index( - config.DriveReaderConfig{ - Drive: drive.Drive, - DriveIsRegular: drive.DriveIsRegular, - }, - config.DriveConfig{ - Drive: drive.Drive, - DriveIsRegular: drive.DriveIsRegular, - }, - metadataConfig, - pipeConfig, - readCryptoConfig, - - *recordSizeFlag, - 0, - 0, - true, - 0, - - func(hdr *tar.Header, i int) error { - return encryption.DecryptHeader(hdr, config.NoneKey, nil) - }, - func(hdr *tar.Header, isRegular bool) error { - return signature.VerifyHeader(hdr, isRegular, config.NoneKey, nil) - }, - - func(hdr *config.Header) { - l.Debug("Header read", hdr) - }, - ) - if err != nil { - if err := tm.Close(); err != nil { - panic(err) - } - - if err := stfs.MkdirRoot(root, os.ModePerm); err != nil { - panic(err) - } - } - } else if os.IsNotExist(err) { - if err := tm.Close(); err != nil { - panic(err) - } - - if err := stfs.MkdirRoot(root, os.ModePerm); err != nil { - panic(err) - } - } else { - panic(err) - } - } else { - panic(err) - } + panic(err) } fs, err := cache.NewCacheFilesystem( diff --git a/pkg/fs/filesystem.go b/pkg/fs/filesystem.go index 9f536a2..408bf10 100644 --- a/pkg/fs/filesystem.go +++ b/pkg/fs/filesystem.go @@ -16,9 +16,12 @@ import ( ifs "github.com/pojntfx/stfs/internal/fs" "github.com/pojntfx/stfs/pkg/cache" "github.com/pojntfx/stfs/pkg/config" + "github.com/pojntfx/stfs/pkg/encryption" "github.com/pojntfx/stfs/pkg/inventory" "github.com/pojntfx/stfs/pkg/logging" "github.com/pojntfx/stfs/pkg/operations" + "github.com/pojntfx/stfs/pkg/recovery" + "github.com/pojntfx/stfs/pkg/signature" "github.com/spf13/afero" ) @@ -30,8 +33,8 @@ type STFS struct { compressionLevel string getFileBuffer func() (cache.WriteCache, func() error, error) - readOnly bool ignoreReadWritePermissions bool + readOnly bool ioLock sync.Mutex @@ -176,29 +179,75 @@ func (f *STFS) mknodeWithoutLocking(dir bool, name string, perm os.FileMode, ove return nil } -func (f *STFS) MkdirRoot(name string, perm os.FileMode) error { - f.log.Debug("FileSystem.MkdirRoot", map[string]interface{}{ - "name": name, - "perm": perm, +func (f *STFS) Initialize(rootProposal string, rootPerm os.FileMode) (root string, err error) { + f.log.Debug("FileSystem.InitializeIfEmpty", map[string]interface{}{ + "rootProposal": rootProposal, + "rootPerm": rootPerm, }) - if f.readOnly { - return os.ErrPermission - } - f.ioLock.Lock() defer f.ioLock.Unlock() - if err := f.mknodeWithoutLocking(true, name, perm, true, ""); err != nil { - return err + existingRoot, err := f.metadata.Metadata.GetRootPath(context.Background()) + if err == config.ErrNoRootDirectory { + drive, err := f.readOps.GetBackend().GetDrive() + + mkdirRoot := func() (string, error) { + if err := f.readOps.GetBackend().CloseDrive(); err != nil { + return "", err + } + + if f.readOnly { + return "", os.ErrPermission + } + + if err := f.mknodeWithoutLocking(true, rootProposal, rootPerm, true, ""); err != nil { + return "", err + } + + // Ensure that the new root path is being used + return f.metadata.Metadata.GetRootPath(context.Background()) + } + + if err != nil { + return mkdirRoot() + } + + if err := recovery.Index( + config.DriveReaderConfig{ + Drive: drive.Drive, + DriveIsRegular: drive.DriveIsRegular, + }, + drive, + f.readOps.GetMetadata(), + f.readOps.GetPipes(), + f.readOps.GetCrypto(), + + f.readOps.GetPipes().RecordSize, + 0, + 0, + true, + 0, + + func(hdr *tar.Header, i int) error { + return encryption.DecryptHeader(hdr, f.readOps.GetPipes().Encryption, f.readOps.GetCrypto().Identity) + }, + func(hdr *tar.Header, isRegular bool) error { + return signature.VerifyHeader(hdr, isRegular, f.readOps.GetPipes().Signature, f.readOps.GetCrypto().Recipient) + }, + + f.onHeader, + ); err != nil { + return mkdirRoot() + } + + // Ensure that the new root path is being used + return f.metadata.Metadata.GetRootPath(context.Background()) + } else if err != nil { + return "", err } - // Ensure that the new root path is being used - if _, err := f.metadata.Metadata.GetRootPath(context.Background()); err != nil { - return err - } - - return nil + return existingRoot, nil } func (f *STFS) Mkdir(name string, perm os.FileMode) error { diff --git a/pkg/operations/operations.go b/pkg/operations/operations.go index 0ad8194..c34b464 100644 --- a/pkg/operations/operations.go +++ b/pkg/operations/operations.go @@ -37,3 +37,19 @@ func NewOperations( onHeader: onHeader, } } + +func (o *Operations) GetBackend() config.BackendConfig { + return o.backend +} + +func (o *Operations) GetMetadata() config.MetadataConfig { + return o.metadata +} + +func (o *Operations) GetPipes() config.PipeConfig { + return o.pipes +} + +func (o *Operations) GetCrypto() config.CryptoConfig { + return o.crypto +}