feat: udpates
This commit is contained in:
@@ -37,6 +37,7 @@ File ext `*.__encfile`:
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
"name": "<file name>",
|
||||||
"iv": "<16 bytes IV in base64>"
|
"iv": "<16 bytes IV in base64>"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
109
encfs/file.go
109
encfs/file.go
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
encfs/fs.go
22
encfs/fs.go
@@ -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
10
main.go
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user