| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- package firewall
- import (
- "errors"
- "fmt"
- "os"
- "path/filepath"
- )
- func stageFile(path string, data []byte) (string, error) {
- f, err := os.CreateTemp(filepath.Dir(path), ".debtik-*")
- if err != nil {
- return "", err
- }
- name := f.Name()
- _, err = f.Write(data)
- if err == nil {
- err = f.Sync()
- }
- closed := f.Close()
- if err == nil {
- err = closed
- }
- if err != nil {
- os.Remove(name)
- return "", err
- }
- return name, nil
- }
- func writeAtomic(path string, data []byte) error {
- name, err := stageFile(path, data)
- if err != nil {
- return err
- }
- defer os.Remove(name)
- return os.Rename(name, path)
- }
- func saveFileGroup(files map[string][]byte) error {
- staged := map[string]string{}
- original := map[string][]byte{}
- exists := map[string]bool{}
- defer func() {
- for _, name := range staged {
- os.Remove(name)
- }
- }()
- for path, data := range files {
- old, err := os.ReadFile(path)
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- exists[path] = err == nil
- original[path] = old
- name, err := stageFile(path, data)
- if err != nil {
- return err
- }
- staged[path] = name
- }
- var renamed []string
- for path, name := range staged {
- if err := os.Rename(name, path); err != nil {
- failures := []error{err}
- for _, oldPath := range renamed {
- var restore error
- if exists[oldPath] {
- restore = writeAtomic(oldPath, original[oldPath])
- } else {
- restore = os.Remove(oldPath)
- }
- if restore != nil {
- failures = append(failures, fmt.Errorf("restore %s: %w", oldPath, restore))
- }
- }
- return errors.Join(failures...)
- }
- renamed = append(renamed, path)
- }
- return nil
- }
|