79 lines
1.7 KiB
Go
79 lines
1.7 KiB
Go
package app
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"syscall"
|
|
|
|
"github.com/pelletier/go-toml/v2"
|
|
)
|
|
|
|
// UpdateAccessConfig preserves all existing settings, ownership and permissions.
|
|
// It never opens the data directory; callers can prepare a candidate while serving.
|
|
func UpdateAccessConfig(path, listen string, additions []string, allowLAN bool) error {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cfg := DefaultConfig()
|
|
if err = toml.NewDecoder(bytes.NewReader(data)).DisallowUnknownFields().Decode(&cfg); err != nil {
|
|
return err
|
|
}
|
|
if listen != "" {
|
|
cfg.Listen = listen
|
|
}
|
|
cfg.AllowLANHTTP = cfg.AllowLANHTTP || allowLAN
|
|
for _, raw := range additions {
|
|
base, e := normalizeAccessURL(raw)
|
|
if e != nil {
|
|
return e
|
|
}
|
|
found := false
|
|
for _, existing := range cfg.accessOrigins() {
|
|
if base == existing {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
cfg.AccessURLs = append(cfg.AccessURLs, base)
|
|
}
|
|
}
|
|
if err = cfg.Validate(); err != nil {
|
|
return err
|
|
}
|
|
encoded, err := toml.Marshal(cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out, err := os.CreateTemp(filepath.Dir(path), ".access-config-*.toml")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer os.Remove(out.Name())
|
|
defer out.Close()
|
|
if stat, ok := info.Sys().(*syscall.Stat_t); ok {
|
|
if err = out.Chown(int(stat.Uid), int(stat.Gid)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err = out.Chmod(info.Mode().Perm()); err != nil {
|
|
return err
|
|
}
|
|
if _, err = out.Write(encoded); err != nil {
|
|
return err
|
|
}
|
|
if err = out.Sync(); err != nil {
|
|
return err
|
|
}
|
|
if err = out.Close(); err != nil {
|
|
return err
|
|
}
|
|
return os.Rename(out.Name(), path)
|
|
}
|