Files
2025-07-28 00:24:34 -03:00

177 lines
5.0 KiB
Go

package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"os"
"os/signal"
"path/filepath"
"sirherobrine23.com.br/Sirherobrine23/cgofuse/fs"
"sirherobrine23.com.br/go-bds/overlayfs"
)
type arrayFlags []string
// String is an implementation of the flag.Value interface
func (i *arrayFlags) String() string {
return fmt.Sprintf("%v", *i)
}
// Set is an implementation of the flag.Value interface
func (i *arrayFlags) Set(value string) error {
*i = append(*i, value)
return nil
}
var (
Config = flag.String("config", "", "config gile")
Target = flag.String("target", "target", "Target folder to mount")
Upper = flag.String("upper", "", "Upper folder to write modifications")
Work = flag.String("work", "", "Work folder to write temporary files")
Lower = arrayFlags{}
)
func main() {
flag.Var(&Lower, "lower", "Lower folder to read")
flag.Parse()
// Mounting config
var overlayFSConfig *overlayfs.Overlayfs
if *Config == "" {
overlayFSConfig = overlayfs.NewOverlayFS(*Target, *Upper, *Work, Lower...)
} else {
var jsConfig map[string]any
data, err := os.ReadFile(*Config)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
} else if err = json.Unmarshal(data, &jsConfig); err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
}
dirBase := filepath.Dir(*Config)
overlayFSConfig = new(overlayfs.Overlayfs)
for key, value := range jsConfig {
var ok bool
switch key {
case "target":
if overlayFSConfig.Target, ok = value.(string); !ok {
fmt.Fprintln(os.Stderr, "Config: target must be a string")
os.Exit(1)
return
}
overlayFSConfig.Target = filepath.Join(dirBase, overlayFSConfig.Target)
case "upper":
if overlayFSConfig.Upper, ok = value.(string); !ok {
fmt.Fprintln(os.Stderr, "Config: upper must be a string")
os.Exit(1)
return
}
overlayFSConfig.Upper = filepath.Join(dirBase, overlayFSConfig.Upper)
case "work":
if overlayFSConfig.Workdir, ok = value.(string); !ok {
fmt.Fprintln(os.Stderr, "Config: work must be a string")
os.Exit(1)
return
}
overlayFSConfig.Workdir = filepath.Join(dirBase, overlayFSConfig.Workdir)
case "lower":
for index, lower := range value.([]any) {
value, ok := lower.(string)
if !ok {
fmt.Fprintf(os.Stderr, "Config: lower[%d] must be a string\n", index)
os.Exit(1)
return
}
overlayFSConfig.Lower = append(overlayFSConfig.Lower, filepath.Join(dirBase, value))
}
case "lower_mkdir":
// [string, {name: string, type: "file"|"dir"}...]
if lowerMkdir, ok := value.([]any); ok && len(lowerMkdir) > 0 {
for _, v := range lowerMkdir {
var mkdirPath string
for _, value := range v.([]any) {
switch v := value.(type) {
case string:
mkdirPath = filepath.Join(dirBase, v)
overlayFSConfig.Lower = append(overlayFSConfig.Lower, filepath.Join(dirBase, v))
case map[string]any:
name, ok := v["name"].(string)
if !ok {
continue
}
ftype, ok := v["type"].(string)
if !ok {
continue
}
mkdirPath := filepath.Join(mkdirPath, name)
switch ftype {
case "file":
os.MkdirAll(filepath.Join(mkdirPath, filepath.Dir(mkdirPath)), 0777)
os.WriteFile(mkdirPath, []byte{}, 0666)
case "dir":
os.MkdirAll(mkdirPath, 0777)
}
}
}
}
}
}
}
}
for _, folderPath := range append(overlayFSConfig.Lower, overlayFSConfig.Target, overlayFSConfig.Upper, overlayFSConfig.Workdir) {
if folderPath == "" {
continue
} else if _, err := os.Stat(folderPath); os.IsNotExist(err) {
if err = os.MkdirAll(folderPath, 0777); err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
}
}
}
wd, _ := os.Getwd()
if !filepath.IsAbs(overlayFSConfig.Target) {
overlayFSConfig.Target = filepath.Join(wd, overlayFSConfig.Target)
}
if overlayFSConfig.Upper != "" && !filepath.IsAbs(overlayFSConfig.Upper) {
overlayFSConfig.Upper = filepath.Join(wd, overlayFSConfig.Upper)
}
if overlayFSConfig.Workdir != "" && !filepath.IsAbs(overlayFSConfig.Workdir) {
overlayFSConfig.Workdir = filepath.Join(wd, overlayFSConfig.Workdir)
}
for index, lowPath := range overlayFSConfig.Lower {
if !filepath.IsAbs(lowPath) {
overlayFSConfig.Lower[index] = filepath.Join(wd, lowPath)
}
}
d, _ := json.MarshalIndent(overlayFSConfig, "", " ")
println(string(d))
fmt.Fprintf(os.Stderr, "Mount overlayfs into %q\n", overlayFSConfig.Target)
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
defer stop()
fs := fs.New(overlayFSConfig.Target, overlayFSConfig)
if err := fs.Mount(ctx); err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
return
}
fmt.Fprintf(os.Stderr, "Mounted overlayfs\n")
<-ctx.Done()
fmt.Fprintf(os.Stderr, "Unmount overlayfs\n")
fs.Done()
fmt.Fprintf(os.Stderr, "Unmounted overlayfs\n")
}