diff --git a/windows-agent/internal/config/config_marshal.go b/windows-agent/internal/config/config_marshal.go index 0bbc5e530..fb83cc527 100644 --- a/windows-agent/internal/config/config_marshal.go +++ b/windows-agent/internal/config/config_marshal.go @@ -19,11 +19,18 @@ type marshalHelper struct { func (c *Config) load() (err error) { defer decorate.OnError(&err, "could not load data for Config") + // Backup the config in case the registry fails. + // This avoids partial loads. + l := c.landscape + s := c.subscription + if err := c.loadFile(); err != nil { return fmt.Errorf("could not load config from the chache file: %v", err) } if err := c.loadRegistry(); err != nil { + c.landscape = l + c.subscription = s return fmt.Errorf("could not load config from the registry: %v", err) } @@ -97,16 +104,44 @@ func readFromRegistry(r Registry, key uintptr, field string) (string, error) { func (c *Config) dump() (err error) { defer decorate.OnError(&err, "could not store Config data") - var errs error - if err := c.dumpRegistry(); err != nil { - errs = errors.Join(errs, err) + // Backup the file in case the registry write fails. + // This avoids partial writes + restore, err := makeBackup(c.cachePath) + if err != nil { + return err } if err := c.dumpFile(); err != nil { - errs = errors.Join(errs, err) + return err + } + + if err := c.dumpRegistry(); err != nil { + return errors.Join(err, restore()) + } + + return nil +} + +func makeBackup(backedUpPath string) (func() error, error) { + backupPath := backedUpPath + ".backup" + + // filterFsError is a small error to avoid having to do the errors.Is dance every time. + filterFsError := func(err error) error { + if errors.Is(err, fs.ErrNotExist) { + return nil + } + return err + } + + err := os.Rename(backedUpPath, backupPath) + if filterFsError(err) != nil { + return nil, fmt.Errorf("could not create backup: %v", err) } - return errs + return func() error { + err := os.Rename(backupPath, backedUpPath) + return filterFsError(err) + }, nil } func (c *Config) dumpRegistry() error {