This removes the requirement to call fmsg.Exit on every exit path, and enables direct use of the "log" package. However, fmsg.BeforeExit is still encouraged when possible to catch exit on suspended output. Signed-off-by: Ophestra <cat@gensokyo.uk>
89 lines
1.9 KiB
Go
89 lines
1.9 KiB
Go
package system
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
|
)
|
|
|
|
// Ensure the existence and mode of a directory.
|
|
func (sys *I) Ensure(name string, perm os.FileMode) *I {
|
|
sys.lock.Lock()
|
|
defer sys.lock.Unlock()
|
|
|
|
sys.ops = append(sys.ops, &Mkdir{User, name, perm, false})
|
|
|
|
return sys
|
|
}
|
|
|
|
// Ephemeral ensures the temporary existence and mode of a directory through the life of et.
|
|
func (sys *I) Ephemeral(et Enablement, name string, perm os.FileMode) *I {
|
|
sys.lock.Lock()
|
|
defer sys.lock.Unlock()
|
|
|
|
sys.ops = append(sys.ops, &Mkdir{et, name, perm, true})
|
|
|
|
return sys
|
|
}
|
|
|
|
type Mkdir struct {
|
|
et Enablement
|
|
path string
|
|
perm os.FileMode
|
|
ephemeral bool
|
|
}
|
|
|
|
func (m *Mkdir) Type() Enablement {
|
|
return m.et
|
|
}
|
|
|
|
func (m *Mkdir) apply(_ *I) error {
|
|
fmsg.Verbose("ensuring directory", m)
|
|
|
|
// create directory
|
|
err := os.Mkdir(m.path, m.perm)
|
|
if !errors.Is(err, os.ErrExist) {
|
|
return fmsg.WrapErrorSuffix(err,
|
|
fmt.Sprintf("cannot create directory %q:", m.path))
|
|
}
|
|
|
|
// directory exists, ensure mode
|
|
return fmsg.WrapErrorSuffix(os.Chmod(m.path, m.perm),
|
|
fmt.Sprintf("cannot change mode of %q to %s:", m.path, m.perm))
|
|
}
|
|
|
|
func (m *Mkdir) revert(_ *I, ec *Criteria) error {
|
|
if !m.ephemeral {
|
|
// skip non-ephemeral dir and do not log anything
|
|
return nil
|
|
}
|
|
|
|
if ec.hasType(m) {
|
|
fmsg.Verbose("destroying ephemeral directory", m)
|
|
return fmsg.WrapErrorSuffix(os.Remove(m.path),
|
|
fmt.Sprintf("cannot remove ephemeral directory %q:", m.path))
|
|
} else {
|
|
fmsg.Verbose("skipping ephemeral directory", m)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (m *Mkdir) Is(o Op) bool {
|
|
m0, ok := o.(*Mkdir)
|
|
return ok && m0 != nil && *m == *m0
|
|
}
|
|
|
|
func (m *Mkdir) Path() string {
|
|
return m.path
|
|
}
|
|
|
|
func (m *Mkdir) String() string {
|
|
t := "Ensure"
|
|
if m.ephemeral {
|
|
t = TypeString(m.Type())
|
|
}
|
|
return fmt.Sprintf("mode: %s type: %s path: %q", m.perm.String(), t, m.path)
|
|
}
|