feat: Start implementation of Afero FileSystem, File and FileInfo
This commit is contained in:
@@ -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),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
103
internal/fs/file.go
Normal 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
69
internal/fs/fileinfo.go
Normal 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
165
internal/fs/fs.go
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user