feat: init commit
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
main
|
||||
# ---> Go
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
# go-afero-encfs
|
||||
|
||||
`go-afero-encfs` is a afero encrypted fs implementation
|
||||
|
||||
In stage 1 we only encrypt file content, the file name is not encrypted.
|
||||
|
||||
In the future we are going to encrypt the file name also.
|
||||
|
||||
128
encfs/file.go
Normal file
128
encfs/file.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package encfs
|
||||
|
||||
type EncFile struct {}
|
||||
|
||||
func (f *File) Close() error {
|
||||
if f.closed {
|
||||
return afero.ErrFileClosed
|
||||
}
|
||||
|
||||
f.closed = true
|
||||
f.h = nil
|
||||
f.data = nil
|
||||
f.fs = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *File) Read(p []byte) (n int, err error) {
|
||||
if f.closed {
|
||||
return 0, afero.ErrFileClosed
|
||||
}
|
||||
|
||||
if f.h.Typeflag == tar.TypeDir {
|
||||
return 0, syscall.EISDIR
|
||||
}
|
||||
|
||||
return f.data.Read(p)
|
||||
}
|
||||
|
||||
func (f *File) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
if f.closed {
|
||||
return 0, afero.ErrFileClosed
|
||||
}
|
||||
|
||||
if f.h.Typeflag == tar.TypeDir {
|
||||
return 0, syscall.EISDIR
|
||||
}
|
||||
|
||||
return f.data.ReadAt(p, off)
|
||||
}
|
||||
|
||||
func (f *File) Seek(offset int64, whence int) (int64, error) {
|
||||
if f.closed {
|
||||
return 0, afero.ErrFileClosed
|
||||
}
|
||||
|
||||
if f.h.Typeflag == tar.TypeDir {
|
||||
return 0, syscall.EISDIR
|
||||
}
|
||||
|
||||
return f.data.Seek(offset, whence)
|
||||
}
|
||||
|
||||
func (f *File) Write(p []byte) (n int, err error) { return 0, syscall.EROFS }
|
||||
|
||||
func (f *File) WriteAt(p []byte, off int64) (n int, err error) { return 0, syscall.EROFS }
|
||||
|
||||
func (f *File) Name() string {
|
||||
return filepath.Join(splitpath(f.h.Name))
|
||||
}
|
||||
|
||||
func (f *File) getDirectoryNames() ([]string, error) {
|
||||
d, ok := f.fs.files[f.Name()]
|
||||
if !ok {
|
||||
return nil, &os.PathError{Op: "readdir", Path: f.Name(), Err: syscall.ENOENT}
|
||||
}
|
||||
|
||||
var names []string
|
||||
for n := range d {
|
||||
names = append(names, n)
|
||||
}
|
||||
sort.Strings(names)
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
|
||||
if f.closed {
|
||||
return nil, afero.ErrFileClosed
|
||||
}
|
||||
|
||||
if !f.h.FileInfo().IsDir() {
|
||||
return nil, syscall.ENOTDIR
|
||||
}
|
||||
|
||||
names, err := f.getDirectoryNames()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := f.fs.files[f.Name()]
|
||||
var fi []os.FileInfo
|
||||
for _, n := range names {
|
||||
if n == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
f := d[n]
|
||||
fi = append(fi, f.h.FileInfo())
|
||||
if count > 0 && len(fi) >= count {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return fi, nil
|
||||
}
|
||||
|
||||
func (f *File) Readdirnames(n int) ([]string, error) {
|
||||
fi, err := f.Readdir(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var names []string
|
||||
for _, f := range fi {
|
||||
names = append(names, f.Name())
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func (f *File) Stat() (os.FileInfo, error) { return f.h.FileInfo(), nil }
|
||||
|
||||
func (f *File) Sync() error { return nil }
|
||||
|
||||
func (f *File) Truncate(size int64) error { return syscall.EROFS }
|
||||
|
||||
func (f *File) WriteString(s string) (ret int, err error) { return 0, syscall.EROFS }
|
||||
95
encfs/fs.go
Normal file
95
encfs/fs.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package encfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// copied from afero/os.go
|
||||
|
||||
type EncFs struct{}
|
||||
|
||||
func NewEncFs() Fs {
|
||||
return &EncFs{}
|
||||
}
|
||||
|
||||
func (EncFs) Name() string { return "EncFs" }
|
||||
|
||||
func (EncFs) Create(name string) (File, error) {
|
||||
f, e := os.Create(name)
|
||||
if f == nil {
|
||||
// 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
|
||||
return nil, e
|
||||
}
|
||||
return f, e
|
||||
}
|
||||
|
||||
func (EncFs) Mkdir(name string, perm os.FileMode) error {
|
||||
return os.Mkdir(name, perm)
|
||||
}
|
||||
|
||||
func (EncFs) MkdirAll(path string, perm os.FileMode) error {
|
||||
return os.MkdirAll(path, perm)
|
||||
}
|
||||
|
||||
func (EncFs) Open(name string) (File, error) {
|
||||
f, e := os.Open(name)
|
||||
if f == nil {
|
||||
// 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
|
||||
return nil, e
|
||||
}
|
||||
return f, e
|
||||
}
|
||||
|
||||
func (EncFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
|
||||
f, e := os.OpenFile(name, flag, perm)
|
||||
if f == nil {
|
||||
// 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
|
||||
return nil, e
|
||||
}
|
||||
return f, e
|
||||
}
|
||||
|
||||
func (EncFs) Remove(name string) error {
|
||||
return os.Remove(name)
|
||||
}
|
||||
|
||||
func (EncFs) RemoveAll(path string) error {
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
func (EncFs) Rename(oldname, newname string) error {
|
||||
return os.Rename(oldname, newname)
|
||||
}
|
||||
|
||||
func (EncFs) Stat(name string) (os.FileInfo, error) {
|
||||
return os.Stat(name)
|
||||
}
|
||||
|
||||
func (EncFs) Chmod(name string, mode os.FileMode) error {
|
||||
return os.Chmod(name, mode)
|
||||
}
|
||||
|
||||
func (EncFs) Chown(name string, uid, gid int) error {
|
||||
return os.Chown(name, uid, gid)
|
||||
}
|
||||
|
||||
func (EncFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||
return os.Chtimes(name, atime, mtime)
|
||||
}
|
||||
|
||||
func (EncFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
|
||||
fi, err := os.Lstat(name)
|
||||
return fi, true, err
|
||||
}
|
||||
|
||||
func (EncFs) SymlinkIfPossible(oldname, newname string) error {
|
||||
return os.Symlink(oldname, newname)
|
||||
}
|
||||
|
||||
func (EncFs) ReadlinkIfPossible(name string) (string, error) {
|
||||
return os.Readlink(name)
|
||||
}
|
||||
8
go.mod
Normal file
8
go.mod
Normal file
@@ -0,0 +1,8 @@
|
||||
module git.hatter.ink/hatter/go-afero-encfs
|
||||
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
)
|
||||
4
go.sum
Normal file
4
go.sum
Normal file
@@ -0,0 +1,4 @@
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
35
main.go
Normal file
35
main.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/hex"
|
||||
"crypto/aes"
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("Hello Go.")
|
||||
osFs := afero.NewOsFs()
|
||||
fmt.Println(osFs)
|
||||
|
||||
key := []byte {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
cipher, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
dest := []byte {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
src := []byte {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
}
|
||||
cipher.Encrypt(dest, src)
|
||||
|
||||
fmt.Println(hex.EncodeToString(key))
|
||||
fmt.Println(hex.EncodeToString(src))
|
||||
fmt.Println(hex.EncodeToString(dest))
|
||||
}
|
||||
Reference in New Issue
Block a user