basic structure of idea
This commit is contained in:
parent
fd424a83c9
commit
83eaae6a73
4
files/test.sh
Executable file
4
files/test.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "I'm working!"
|
||||
pwd
|
5
go.mod
5
go.mod
@ -1,3 +1,8 @@
|
||||
module git.sdf.org/CRThaze/gfw
|
||||
|
||||
go 1.22.5
|
||||
|
||||
require (
|
||||
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5 // indirect
|
||||
golang.org/x/sys v0.4.0 // indirect
|
||||
)
|
||||
|
4
go.sum
Normal file
4
go.sum
Normal file
@ -0,0 +1,4 @@
|
||||
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5 h1:A0NsYy4lDBZAC6QiYeJ4N+XuHIKBpyhAVRMHRQZKTeQ=
|
||||
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5/go.mod h1:gG3RZAMXCa/OTes6rr9EwusmR1OH1tDDy+cg9c5YliY=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
26
main.go
Normal file
26
main.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"log"
|
||||
)
|
||||
|
||||
//go:embed files/*
|
||||
var content embed.FS
|
||||
|
||||
func main() {
|
||||
gfw, err := NewGFW(GFWConfig{
|
||||
EmbedFS: content,
|
||||
DefaultExecutable: "test.sh",
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to create GFW: %v", err)
|
||||
}
|
||||
if err := gfw.Mount(); err != nil {
|
||||
log.Fatalf("Unable to mount GFW:, %v", err)
|
||||
}
|
||||
defer gfw.Unmount()
|
||||
if err := gfw.Execute(); err != nil {
|
||||
log.Fatalf("Failed to execute: %v", err)
|
||||
}
|
||||
}
|
171
wrap.go
171
wrap.go
@ -1 +1,170 @@
|
||||
package gfw
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse"
|
||||
fuseFS "bazil.org/fuse/fs"
|
||||
)
|
||||
|
||||
type FS struct {
|
||||
fsys fs.FS
|
||||
}
|
||||
|
||||
func (f *FS) Root() (fuseFS.Node, error) {
|
||||
return &Dir{fsys: f.fsys}, nil
|
||||
}
|
||||
|
||||
type Dir struct {
|
||||
fsys fs.FS
|
||||
}
|
||||
|
||||
func (d *Dir) Attr(ctx context.Context, attr *fuse.Attr) error {
|
||||
attr.Mode = os.ModeDir | 0o555
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Dir) Lookup(name string) (fuseFS.Node, error) {
|
||||
file, err := d.fsys.Open(name)
|
||||
if err != nil {
|
||||
return nil, fuse.ToErrno(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
return &Dir{fsys: d.fsys}, nil
|
||||
}
|
||||
|
||||
return &File{file: file, size: uint64(stat.Size())}, nil
|
||||
}
|
||||
|
||||
type File struct {
|
||||
file fs.File
|
||||
size uint64
|
||||
}
|
||||
|
||||
func (f *File) Attr(ctx context.Context, attr *fuse.Attr) error {
|
||||
attr.Mode = 0o444
|
||||
attr.Size = f.size
|
||||
attr.Mtime = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
// func (f *File) ReadAll() ([]byte, error) {
|
||||
// return fs.ReadFile(f.file)
|
||||
// }
|
||||
|
||||
type GFWConfig struct {
|
||||
EmbedFS embed.FS
|
||||
DefaultExecutable string
|
||||
OtherExecutables []string
|
||||
Mountpoint string
|
||||
}
|
||||
|
||||
type GFW interface {
|
||||
Mount() error
|
||||
Unmount() error
|
||||
Execute(...string) error
|
||||
}
|
||||
|
||||
type gfw struct {
|
||||
fs embed.FS
|
||||
conn *fuse.Conn
|
||||
mounted bool
|
||||
mountpoint string
|
||||
defaultExecutable string
|
||||
executables map[string]struct{}
|
||||
}
|
||||
|
||||
func (g *gfw) Mount() error {
|
||||
if g.mounted {
|
||||
return fmt.Errorf("Already mounted.")
|
||||
}
|
||||
tempDir := os.TempDir()
|
||||
if strings.HasSuffix(g.mountpoint, "/*") {
|
||||
tempDir = strings.TrimSuffix(g.mountpoint, "/*")
|
||||
g.mountpoint = ""
|
||||
}
|
||||
if g.mountpoint == "" {
|
||||
if dir, err := os.MkdirTemp(tempDir, "*"); err == nil {
|
||||
g.mountpoint = dir
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if conn, err := fuse.Mount(g.mountpoint); err == nil {
|
||||
g.conn = conn
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
if err := fuseFS.Serve(g.conn, &FS{fsys: g.fs}); err != nil {
|
||||
return err
|
||||
}
|
||||
g.mounted = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *gfw) Unmount() error {
|
||||
if err := fuse.Unmount(g.mountpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
return g.conn.Close()
|
||||
}
|
||||
|
||||
func (g *gfw) Execute(execAndArgs ...string) error {
|
||||
if !g.mounted {
|
||||
return fmt.Errorf("GFW is not mounted.")
|
||||
}
|
||||
if len(g.executables) == 0 {
|
||||
return fmt.Errorf("No registerd executables.")
|
||||
}
|
||||
execName := g.defaultExecutable
|
||||
args := []string{}
|
||||
if len(execAndArgs) > 0 {
|
||||
execName = execAndArgs[0]
|
||||
if _, ok := g.executables[execName]; !ok {
|
||||
return fmt.Errorf("Unregisterd executable.")
|
||||
}
|
||||
if len(execAndArgs) > 1 {
|
||||
args = execAndArgs[1:]
|
||||
}
|
||||
}
|
||||
execName = path.Join(g.mountpoint, execName)
|
||||
cmd := exec.Command(execName, args[1:]...)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewGFW(conf GFWConfig) (GFW, error) {
|
||||
if conf.OtherExecutables == nil {
|
||||
conf.OtherExecutables = []string{}
|
||||
if conf.DefaultExecutable != "" {
|
||||
conf.OtherExecutables = append(conf.OtherExecutables, conf.DefaultExecutable)
|
||||
}
|
||||
}
|
||||
g := gfw{
|
||||
fs: conf.EmbedFS,
|
||||
mountpoint: conf.Mountpoint,
|
||||
defaultExecutable: conf.DefaultExecutable,
|
||||
executables: map[string]struct{}{},
|
||||
}
|
||||
for _, e := range conf.OtherExecutables {
|
||||
g.executables[e] = struct{}{}
|
||||
}
|
||||
return &g, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user