feat: Start implementation of Afero FileSystem, File and FileInfo

This commit is contained in:
Felicitas Pojtinger
2021-12-17 18:11:21 +01:00
parent 4d29621a6a
commit 97a61beaa7
5 changed files with 416 additions and 126 deletions

View File

@@ -4,21 +4,98 @@ import (
"flag"
"log"
"net/http"
"os"
"path/filepath"
"github.com/pojntfx/stfs/internal/fs"
"github.com/pojntfx/stfs/internal/handlers"
"github.com/pojntfx/stfs/internal/logging"
"github.com/pojntfx/stfs/internal/persisters"
"github.com/pojntfx/stfs/pkg/config"
"github.com/pojntfx/stfs/pkg/operations"
"github.com/pojntfx/stfs/pkg/tape"
"github.com/spf13/afero"
)
func main() {
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
laddr := flag.String("laddr", "localhost:1337", "Listen address")
dir := flag.String("dir", "/", "Directory to use as the root directory")
drive := flag.String("drive", "/dev/nst0", "Tape or tar file to use")
metadata := flag.String("metadata", filepath.Join(home, ".local", "share", "stbak", "var", "lib", "stbak", "metadata.sqlite"), "Metadata database to use")
recordSize := flag.Int("recordSize", 20, "Amount of 512-bit blocks per record")
flag.Parse()
stfs := afero.NewHttpFs(fs.NewSTFS())
tm := tape.NewTapeManager(
*drive,
*recordSize,
false,
)
metadataPersister := persisters.NewMetadataPersister(*metadata)
if err := metadataPersister.Open(); err != nil {
panic(err)
}
logger := logging.NewLogger()
ops := operations.NewOperations(
config.BackendConfig{
GetWriter: tm.GetWriter,
CloseWriter: tm.Close,
GetReader: tm.GetReader,
CloseReader: tm.Close,
GetDrive: tm.GetDrive,
CloseDrive: tm.Close,
},
config.MetadataConfig{
Metadata: metadataPersister,
},
config.PipeConfig{
Compression: config.NoneKey,
Encryption: config.NoneKey,
Signature: config.NoneKey,
RecordSize: *recordSize,
},
config.CryptoConfig{
Recipient: []byte{},
Identity: []byte{},
Password: "",
},
logger.PrintHeaderEvent,
)
stfs := afero.NewHttpFs(
fs.NewFileSystem(
ops,
config.MetadataConfig{
Metadata: metadataPersister,
},
logger.PrintHeader,
),
)
log.Println("Listening on", *laddr)
log.Fatal(http.ListenAndServe(*laddr, handlers.PanicHandler(http.FileServer(stfs.Dir(*dir)))))
panic(
http.ListenAndServe(
*laddr,
handlers.PanicHandler(
http.FileServer(
stfs.Dir(*dir),
),
),
),
)
}

View File

@@ -1,124 +0,0 @@
package fs
import (
"errors"
"os"
"time"
"github.com/spf13/afero"
)
var (
ErrNotImplemented = errors.New("not implemented")
)
type STFS struct{}
func NewSTFS() afero.Fs {
return &STFS{}
}
func (STFS) Name() string { return "STFS" }
func (STFS) Create(name string) (afero.File, error) {
panic(ErrNotImplemented)
// f, e := os.Create(name)
// if f == nil {
// return nil, e
// }
// return f, e
}
func (STFS) Mkdir(name string, perm os.FileMode) error {
panic(ErrNotImplemented)
// return os.Mkdir(name, perm)
}
func (STFS) MkdirAll(path string, perm os.FileMode) error {
panic(ErrNotImplemented)
// return os.MkdirAll(path, perm)
}
func (STFS) Open(name string) (afero.File, error) {
panic(ErrNotImplemented)
// f, e := os.Open(name)
// if f == nil {
// return nil, e
// }
// return f, e
}
func (STFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
panic(ErrNotImplemented)
// f, e := os.OpenFile(name, flag, perm)
// if f == nil {
// return nil, e
// }
// return f, e
}
func (STFS) Remove(name string) error {
panic(ErrNotImplemented)
// return os.Remove(name)
}
func (STFS) RemoveAll(path string) error {
panic(ErrNotImplemented)
// return os.RemoveAll(path)
}
func (STFS) Rename(oldname, newname string) error {
panic(ErrNotImplemented)
// return os.Rename(oldname, newname)
}
func (STFS) Stat(name string) (os.FileInfo, error) {
panic(ErrNotImplemented)
// return os.Stat(name)
}
func (STFS) Chmod(name string, mode os.FileMode) error {
panic(ErrNotImplemented)
// return os.Chmod(name, mode)
}
func (STFS) Chown(name string, uid, gid int) error {
panic(ErrNotImplemented)
// return os.Chown(name, uid, gid)
}
func (STFS) Chtimes(name string, atime time.Time, mtime time.Time) error {
panic(ErrNotImplemented)
// return os.Chtimes(name, atime, mtime)
}
func (STFS) LstatIfPossible(name string) (os.FileInfo, bool, error) {
panic(ErrNotImplemented)
// fi, err := os.Lstat(name)
// return fi, true, err
}
func (STFS) SymlinkIfPossible(oldname, newname string) error {
panic(ErrNotImplemented)
// return os.Symlink(oldname, newname)
}
func (STFS) ReadlinkIfPossible(name string) (string, error) {
panic(ErrNotImplemented)
// return os.Readlink(name)
}

103
internal/fs/file.go Normal file
View File

@@ -0,0 +1,103 @@
package fs
import (
"log"
"os"
"github.com/spf13/afero"
)
type File struct {
afero.File
name string
info os.FileInfo
}
func NewFile(
name string,
stat os.FileInfo,
) *File {
return &File{
name: name,
info: stat,
}
}
func (f File) Name() string {
log.Println("File.Name", f.name)
return f.name
}
func (f File) Stat() (os.FileInfo, error) {
log.Println("File.Stat", f.name)
return f.info, nil
}
func (f File) Readdir(count int) ([]os.FileInfo, error) {
log.Println("File.Readdir", f.name, count)
return nil, ErrNotImplemented
}
func (f File) Readdirnames(n int) ([]string, error) {
log.Println("File.Readdirnames", f.name, n)
return nil, ErrNotImplemented
}
func (f File) Sync() error {
log.Println("File.Sync", f.name)
return ErrNotImplemented
}
func (f File) Truncate(size int64) error {
log.Println("File.Truncate", f.name, size)
return ErrNotImplemented
}
func (f File) WriteString(s string) (ret int, err error) {
log.Println("File.WriteString", f.name, s)
return -1, ErrNotImplemented
}
func (f File) Close() error {
log.Println("File.Close", f.name)
return ErrNotImplemented
}
func (f File) Read(p []byte) (n int, err error) {
log.Println("File.Read", f.name, p)
return -1, ErrNotImplemented
}
func (f File) ReadAt(p []byte, off int64) (n int, err error) {
log.Println("File.ReadAt", f.name, p, off)
return -1, ErrNotImplemented
}
func (f File) Seek(offset int64, whence int) (int64, error) {
log.Println("File.Seek", f.name, offset, whence)
return -1, ErrNotImplemented
}
func (f File) Write(p []byte) (n int, err error) {
log.Println("File.Write", f.name, p)
return -1, ErrNotImplemented
}
func (f File) WriteAt(p []byte, off int64) (n int, err error) {
log.Println("File.WriteAt", f.name, p, off)
return -1, ErrNotImplemented
}

69
internal/fs/fileinfo.go Normal file
View File

@@ -0,0 +1,69 @@
package fs
import (
"log"
"os"
"time"
)
type FileInfo struct {
os.FileInfo
name string
size int64
mode int64
modTime time.Time
isDir bool
}
func NewFileInfo(
name string,
size int64,
mode int64,
modTime time.Time,
isDir bool,
) *FileInfo {
return &FileInfo{
name: name,
size: size,
mode: mode,
modTime: modTime,
isDir: isDir,
}
}
func (f FileInfo) Name() string {
log.Println("FileInfo.Name", f.name)
return f.name
}
func (f FileInfo) Size() int64 {
log.Println("FileInfo.Size", f.name)
return f.size
}
func (f FileInfo) Mode() os.FileMode {
log.Println("FileInfo.Mode", f.name)
return os.FileMode(f.mode)
}
func (f FileInfo) ModTime() time.Time {
log.Println("FileInfo.ModTime", f.name)
return f.modTime
}
func (f FileInfo) IsDir() bool {
log.Println("FileInfo.IsDir", f.name)
return f.isDir
}
func (f FileInfo) Sys() interface{} {
log.Println("FileInfo.Sys", f.name)
return nil
}

165
internal/fs/fs.go Normal file
View File

@@ -0,0 +1,165 @@
package fs
import (
"archive/tar"
"database/sql"
"errors"
"log"
"os"
"path/filepath"
"time"
models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata"
"github.com/pojntfx/stfs/pkg/config"
"github.com/pojntfx/stfs/pkg/inventory"
"github.com/pojntfx/stfs/pkg/operations"
"github.com/spf13/afero"
)
var (
ErrNotImplemented = errors.New("not implemented")
)
type FileSystem struct {
ops *operations.Operations
metadata config.MetadataConfig
onHeader func(hdr *models.Header)
}
func NewFileSystem(
ops *operations.Operations,
metadata config.MetadataConfig,
onHeader func(hdr *models.Header),
) afero.Fs {
return &FileSystem{
ops: ops,
metadata: metadata,
onHeader: onHeader,
}
}
func (S *FileSystem) Name() string {
log.Println("FileSystem.Name")
return "STFS"
}
func (S *FileSystem) Create(name string) (afero.File, error) {
log.Println("FileSystem.Name", name)
panic(ErrNotImplemented)
}
func (S *FileSystem) Mkdir(name string, perm os.FileMode) error {
log.Println("FileSystem.Mkdir", name, perm)
panic(ErrNotImplemented)
}
func (S *FileSystem) MkdirAll(path string, perm os.FileMode) error {
log.Println("FileSystem.MkdirAll", path, perm)
panic(ErrNotImplemented)
}
func (s *FileSystem) Open(name string) (afero.File, error) {
log.Println("FileSystem.Open", name)
hdr, err := inventory.Stat(
s.metadata,
name,
s.onHeader,
)
if err != nil {
if err == sql.ErrNoRows {
return nil, os.ErrNotExist
}
return nil, err
}
return NewFile(
filepath.Base(name),
NewFileInfo(
filepath.Base(name),
hdr.Size,
hdr.Mode,
hdr.ModTime,
hdr.Typeflag == tar.TypeDir,
),
), nil
}
func (S *FileSystem) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
log.Println("FileSystem.OpenFile", name, flag, perm)
panic(ErrNotImplemented)
}
func (S *FileSystem) Remove(name string) error {
log.Println("FileSystem.Remove", name)
panic(ErrNotImplemented)
}
func (S *FileSystem) RemoveAll(path string) error {
log.Println("FileSystem.RemoveAll", path)
panic(ErrNotImplemented)
}
func (S *FileSystem) Rename(oldname, newname string) error {
log.Println("FileSystem.Rename", oldname, newname)
panic(ErrNotImplemented)
}
func (S *FileSystem) Stat(name string) (os.FileInfo, error) {
log.Println("FileSystem.Stat", name)
panic(ErrNotImplemented)
}
func (S *FileSystem) Chmod(name string, mode os.FileMode) error {
log.Println("FileSystem.Chmod", name, mode)
panic(ErrNotImplemented)
}
func (S *FileSystem) Chown(name string, uid, gid int) error {
log.Println("FileSystem.Chown", name, uid, gid)
panic(ErrNotImplemented)
}
func (S *FileSystem) Chtimes(name string, atime time.Time, mtime time.Time) error {
log.Println("FileSystem.Chtimes", name, atime, mtime)
panic(ErrNotImplemented)
}
func (S *FileSystem) LstatIfPossible(name string) (os.FileInfo, bool, error) {
log.Println("FileSystem.LstatIfPossible", name)
panic(ErrNotImplemented)
}
func (S *FileSystem) SymlinkIfPossible(oldname, newname string) error {
log.Println("FileSystem.SymlinkIfPossible", oldname, newname)
panic(ErrNotImplemented)
}
func (S *FileSystem) ReadlinkIfPossible(name string) (string, error) {
log.Println("FileSystem.ReadlinkIfPossible", name)
panic(ErrNotImplemented)
}