feat: udpates

This commit is contained in:
2024-09-01 15:13:18 +08:00
parent 1971f37a9d
commit 84c0e2e872
4 changed files with 130 additions and 12 deletions

View File

@@ -37,6 +37,7 @@ File ext `*.__encfile`:
```json ```json
{ {
"name": "<file name>",
"iv": "<16 bytes IV in base64>" "iv": "<16 bytes IV in base64>"
} }
``` ```

View File

@@ -1,28 +1,121 @@
package encfs package encfs
import ( import (
"crypto/rand"
"encoding/json"
"errors"
"io"
"os" "os"
"syscall" "syscall"
"github.com/spf13/afero" "github.com/spf13/afero"
) )
type EncFile struct { const EncFileExt = ".__encfile"
isDir bool
closed bool var (
file *os.File ErrFileForbiddenFileExt = errors.New("File ext is forbidden")
)
type EncFileMeta struct {
Name string `json:"name"`
Iv []byte `json:"iv"`
} }
func NewEncFile(file *os.File) (*EncFile, error) { func newEncFileMeta(name string) (*EncFileMeta, error) {
iv := make([]byte, 16)
_, err := rand.Read(iv)
if err != nil {
return nil, err
}
encFileMeta := &EncFileMeta{
Name: name,
Iv: iv,
}
encFileMetaName := name + EncFileExt
encFileMetaFile, err := os.Create(encFileMetaName)
if err != nil {
return nil, err
}
defer func() {
_ = encFileMetaFile.Close()
}()
encFileMetaBytes, err := marshalEncFileMeta(encFileMeta)
if err != nil {
return nil, err
}
_, err = encFileMetaFile.Write(encFileMetaBytes)
if err != nil {
return nil, err
}
return encFileMeta, nil
}
func openEncFileMeta(name string) (*EncFileMeta, error) {
encFileMetaName := name + "." + EncFileExt
encFileMetaFile, err := os.Open(encFileMetaName)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
defer func() {
_ = encFileMetaFile.Close()
}()
encFileMetaBytes, err := io.ReadAll(encFileMetaFile)
if err != nil {
return nil, err
}
encFileMeta, err := unmarchalEncFileMeta(encFileMetaBytes)
if err != nil {
return nil, err
}
return encFileMeta, nil
}
func marshalEncFileMeta(encFileMeata *EncFileMeta) ([]byte, error) {
return json.Marshal(encFileMeata)
}
func unmarchalEncFileMeta(data []byte) (*EncFileMeta, error) {
var encFileMeta EncFileMeta
err := json.Unmarshal(data, &encFileMeta)
if err != nil {
return nil, err
}
return &encFileMeta, nil
}
type EncFile struct {
isDir bool
closed bool
encFileMeta *EncFileMeta
file *os.File
}
func NewEncFile(name string, file *os.File, isCreate bool) (*EncFile, error) {
fileInfo, err := file.Stat() fileInfo, err := file.Stat()
if err != nil { if err != nil {
return nil, err return nil, err
} }
isDir := fileInfo.IsDir() isDir := fileInfo.IsDir()
var encFileMeta *EncFileMeta = nil
if !isDir {
if isCreate {
encFileMeta, err = newEncFileMeta(name)
} else {
encFileMeta, err = openEncFileMeta(name)
}
if err != nil {
return nil, err
}
}
return &EncFile{ return &EncFile{
isDir: isDir, isDir: isDir,
closed: false, closed: false,
file: file, encFileMeta: encFileMeta,
file: file,
}, nil }, nil
} }

View File

@@ -2,6 +2,7 @@ package encfs
import ( import (
"os" "os"
"strings"
"time" "time"
"github.com/spf13/afero" "github.com/spf13/afero"
@@ -18,13 +19,16 @@ func NewEncFs() afero.Fs {
func (EncFs) Name() string { return "EncFs" } func (EncFs) Name() string { return "EncFs" }
func (EncFs) Create(name string) (afero.File, error) { func (EncFs) Create(name string) (afero.File, error) {
if err := checkFileExt(name); err != nil {
return nil, err
}
f, e := os.Create(name) f, e := os.Create(name)
if f == nil { if f == nil {
// while this looks strange, we need to return a bare nil (of type nil) not // while this looks strange, we need to return a bare nil (of type nil) not
// a nil value of type *os.File or nil won't be nil // a nil value of type *os.File or nil won't be nil
return nil, e return nil, e
} }
return convertOsFileToEncFile(f, e) return convertOsFileToEncFile(name, f, e, true)
} }
func (EncFs) Mkdir(name string, perm os.FileMode) error { func (EncFs) Mkdir(name string, perm os.FileMode) error {
@@ -36,13 +40,16 @@ func (EncFs) MkdirAll(path string, perm os.FileMode) error {
} }
func (EncFs) Open(name string) (afero.File, error) { func (EncFs) Open(name string) (afero.File, error) {
if err := checkFileExt(name); err != nil {
return nil, err
}
f, e := os.Open(name) f, e := os.Open(name)
if f == nil { if f == nil {
// while this looks strange, we need to return a bare nil (of type nil) not // while this looks strange, we need to return a bare nil (of type nil) not
// a nil value of type *os.File or nil won't be nil // a nil value of type *os.File or nil won't be nil
return nil, e return nil, e
} }
return convertOsFileToEncFile(f, e) return convertOsFileToEncFile(name, f, e, false)
} }
func (EncFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) { func (EncFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
@@ -99,12 +106,19 @@ func (EncFs) ReadlinkIfPossible(name string) (string, error) {
return os.Readlink(name) return os.Readlink(name)
} }
func convertOsFileToEncFile(file *os.File, e error) (afero.File, error) { func checkFileExt(name string) error {
if strings.HasSuffix(name, EncFileExt) {
return ErrFileForbiddenFileExt
}
return nil
}
func convertOsFileToEncFile(name string, file *os.File, e error, isCreate bool) (afero.File, error) {
if e != nil { if e != nil {
return nil, e return nil, e
} }
// TODO add password, and IV etc ... // TODO add password, and IV etc ...
encFile, err := NewEncFile(file) encFile, err := NewEncFile(name, file, isCreate)
if err != nil { if err != nil {
return nil, err return nil, err
} }

10
main.go
View File

@@ -6,6 +6,7 @@ import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"math" "math"
"os"
"git.hatter.ink/hatter/go-afero-encfs/encfs" "git.hatter.ink/hatter/go-afero-encfs/encfs"
"github.com/spf13/afero" "github.com/spf13/afero"
@@ -94,6 +95,15 @@ func main() {
return return
} }
fmt.Println("write len: ", len) fmt.Println("write len: ", len)
f, err := os.Open("test2")
fmt.Println(f, "-", err, ", ", os.IsNotExist(err))
a, err := encFs.Open(".")
fs, err := a.Readdir(1000)
for _, ff := range fs {
fmt.Println(ff.Name())
}
} }
func generateCtrEncryptBytes(key, iv []byte, offset, len int64) ([]byte, error) { func generateCtrEncryptBytes(key, iv []byte, offset, len int64) ([]byte, error) {