2024-10-16 01:31:23 +09:00
|
|
|
package system
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
|
2024-10-20 19:50:13 +09:00
|
|
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
2024-10-16 01:31:23 +09:00
|
|
|
)
|
|
|
|
|
|
|
|
// Ensure the existence and mode of a directory.
|
2024-10-23 12:34:16 +09:00
|
|
|
func (sys *I) Ensure(name string, perm os.FileMode) *I {
|
2024-10-16 01:31:23 +09:00
|
|
|
sys.lock.Lock()
|
|
|
|
defer sys.lock.Unlock()
|
|
|
|
|
|
|
|
sys.ops = append(sys.ops, &Mkdir{User, name, perm, false})
|
2024-10-23 12:34:16 +09:00
|
|
|
|
|
|
|
return sys
|
2024-10-16 01:31:23 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
// Ephemeral ensures the temporary existence and mode of a directory through the life of et.
|
2024-10-23 12:34:16 +09:00
|
|
|
func (sys *I) Ephemeral(et Enablement, name string, perm os.FileMode) *I {
|
2024-10-16 01:31:23 +09:00
|
|
|
sys.lock.Lock()
|
|
|
|
defer sys.lock.Unlock()
|
|
|
|
|
|
|
|
sys.ops = append(sys.ops, &Mkdir{et, name, perm, true})
|
2024-10-23 12:34:16 +09:00
|
|
|
|
|
|
|
return sys
|
2024-10-16 01:31:23 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
type Mkdir struct {
|
2024-10-16 14:38:57 +09:00
|
|
|
et Enablement
|
2024-10-16 01:31:23 +09:00
|
|
|
path string
|
|
|
|
perm os.FileMode
|
|
|
|
ephemeral bool
|
|
|
|
}
|
|
|
|
|
2024-10-16 14:38:57 +09:00
|
|
|
func (m *Mkdir) Type() Enablement {
|
2024-10-16 01:31:23 +09:00
|
|
|
return m.et
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Mkdir) apply(_ *I) error {
|
2024-10-21 20:47:02 +09:00
|
|
|
fmsg.VPrintln("ensuring directory", m)
|
2024-10-16 01:31:23 +09:00
|
|
|
|
|
|
|
// 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) {
|
2024-10-21 20:47:02 +09:00
|
|
|
fmsg.VPrintln("destroying ephemeral directory", m)
|
2024-10-16 01:31:23 +09:00
|
|
|
return fmsg.WrapErrorSuffix(os.Remove(m.path),
|
|
|
|
fmt.Sprintf("cannot remove ephemeral directory %q:", m.path))
|
|
|
|
} else {
|
2024-10-21 20:47:02 +09:00
|
|
|
fmsg.VPrintln("skipping ephemeral directory", m)
|
2024-10-16 01:31:23 +09:00
|
|
|
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 {
|
2024-10-17 16:37:23 +09:00
|
|
|
t := "Ensure"
|
|
|
|
if m.ephemeral {
|
|
|
|
t = TypeString(m.Type())
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("mode: %s type: %s path: %q", m.perm.String(), t, m.path)
|
2024-10-16 01:31:23 +09:00
|
|
|
}
|