Files
stfs/examples/fs/main.go
2022-01-05 03:50:37 +01:00

290 lines
5.6 KiB
Go

package main
import (
"archive/tar"
"context"
"encoding/json"
"flag"
"log"
"os"
"path/filepath"
"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"
)
type logger struct {
verbose bool
}
func (l logger) log(level, event string, keyvals ...interface{}) {
k, _ := json.Marshal(keyvals)
log.Println(level, event, string(k))
}
func (l logger) Trace(event string, keyvals ...interface{}) {
if l.verbose {
l.log("TRACE", event, keyvals)
}
}
func (l logger) Debug(event string, keyvals ...interface{}) {
if l.verbose {
l.log("DEBUG", event, keyvals)
}
}
func (l logger) Info(event string, keyvals ...interface{}) {
l.log("INFO", event, keyvals)
}
func (l logger) Warn(event string, keyvals ...interface{}) {
l.log("WARN", event, keyvals)
}
func (l logger) Error(event string, keyvals ...interface{}) {
l.log("ERROR", event, keyvals)
}
func (l logger) With(keyvals ...interface{}) golog.Logger {
return l
}
func main() {
driveFlag := flag.String("drive", "/dev/nst0", "Tape or tar file to use")
recordSizeFlag := flag.Int("recordSize", 20, "Amount of 512-bit blocks per record")
metadataFlag := flag.String("metadata", filepath.Join(os.TempDir(), "metadata.sqlite"), "Metadata database to use")
writeCacheFlag := flag.String("writeCache", filepath.Join(os.TempDir(), "stfs-write-cache"), "Directory to use for write cache")
verboseFlag := flag.Bool("verbose", false, "Enable verbose logging")
flag.Parse()
tm := tape.NewTapeManager(
*driveFlag,
*recordSizeFlag,
false,
)
metadataPersister := persisters.NewMetadataPersister(*metadataFlag)
if err := metadataPersister.Open(); err != nil {
panic(err)
}
l := &logger{
verbose: *verboseFlag,
}
metadataConfig := config.MetadataConfig{
Metadata: metadataPersister,
}
pipeConfig := config.PipeConfig{
Compression: config.NoneKey,
Encryption: config.NoneKey,
Signature: config.NoneKey,
RecordSize: *recordSizeFlag,
}
backendConfig := config.BackendConfig{
GetWriter: tm.GetWriter,
CloseWriter: tm.Close,
GetReader: tm.GetReader,
CloseReader: tm.Close,
GetDrive: tm.GetDrive,
CloseDrive: tm.Close,
}
readCryptoConfig := config.CryptoConfig{}
readOps := operations.NewOperations(
backendConfig,
metadataConfig,
pipeConfig,
readCryptoConfig,
func(event *config.HeaderEvent) {
l.Debug("Header read", event)
},
)
writeOps := operations.NewOperations(
backendConfig,
metadataConfig,
pipeConfig,
config.CryptoConfig{},
func(event *config.HeaderEvent) {
l.Debug("Header write", event)
},
)
stfs := sfs.NewSTFS(
readOps,
writeOps,
config.MetadataConfig{
Metadata: metadataPersister,
},
config.CompressionLevelFastest,
func() (cache.WriteCache, func() error, error) {
return cache.NewCacheWrite(
*writeCacheFlag,
config.WriteCacheTypeFile,
)
},
false,
false,
func(hdr *config.Header) {
l.Trace("Header transform", hdr)
},
l,
)
root, err := metadataPersister.GetRootPath(context.Background())
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)
}
}
fs, err := cache.NewCacheFilesystem(
stfs,
root,
config.NoneKey,
0,
"",
)
if err != nil {
panic(err)
}
log.Println("stat /")
stat, err := fs.Stat("/")
if err != nil {
panic(err)
}
log.Println("Result of stat /:", stat)
log.Println("open /")
dir, err := fs.Open("/")
if err != nil {
panic(err)
}
log.Println("Result of open /:", dir)
log.Println("readdir /")
children, err := dir.Readdir(-1)
if err != nil {
panic(err)
}
log.Println("Result of readdir /:", children)
log.Println("create /test.txt")
file, err := fs.Create("/test.txt")
if err != nil {
panic(err)
}
log.Println("Result of create /test.txt:", file)
log.Println("writeString /test.txt")
n, err := file.WriteString("Hello, world!")
if err != nil {
panic(err)
}
log.Println("Result of writeString /test.txt:", n)
if err := file.Close(); err != nil {
panic(err)
}
log.Println("readdir /")
children, err = dir.Readdir(-1)
if err != nil {
panic(err)
}
log.Println("Result of readdir /:", children)
if err := dir.Close(); err != nil {
panic(err)
}
}