diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-08-29 01:06:12 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-08-29 01:06:12 +0900 |
| commit | 84ad9791e2f373d5869b2da6675c70f23deac8a0 (patch) | |
| tree | b5c5b661287c62d62d4ec3dbf08f947df1677e70 /container/errors.go | |
| parent | b14690aa77b3d5f86c4d1b1965675d6d82789e32 (diff) | |
container: wrap mount syscall errno
This is the first step to deprecating the generalised error wrapping error message pattern.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'container/errors.go')
| -rw-r--r-- | container/errors.go | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/container/errors.go b/container/errors.go new file mode 100644 index 00000000..12cb3b95 --- /dev/null +++ b/container/errors.go @@ -0,0 +1,60 @@ +package container + +import ( + "errors" + "os" + "syscall" +) + +type MountError struct { + Source, Target, Fstype string + + Flags uintptr + Data string + syscall.Errno +} + +func (e *MountError) Unwrap() error { + if e.Errno == 0 { + return nil + } + return e.Errno +} + +func (e *MountError) Error() string { + if e.Flags&syscall.MS_BIND != 0 { + if e.Flags&syscall.MS_REMOUNT != 0 { + return "remount " + e.Target + ": " + e.Errno.Error() + } + return "bind " + e.Source + " on " + e.Target + ": " + e.Errno.Error() + } + + if e.Fstype != FstypeNULL { + return "mount " + e.Fstype + " on " + e.Target + ": " + e.Errno.Error() + } + + // fallback case: if this is reached, the conditions for it to occur should be handled above + return "mount " + e.Target + ": " + e.Errno.Error() +} + +// errnoFallback returns the concrete errno from an error, or a [os.PathError] fallback. +func errnoFallback(op, path string, err error) (syscall.Errno, *os.PathError) { + var errno syscall.Errno + if !errors.As(err, &errno) { + return 0, &os.PathError{Op: op, Path: path, Err: err} + } + return errno, nil +} + +// mount wraps syscall.Mount for error handling. +func mount(source, target, fstype string, flags uintptr, data string) error { + err := syscall.Mount(source, target, fstype, flags, data) + if err == nil { + return nil + } + if errno, pathError := errnoFallback("mount", target, err); pathError != nil { + return pathError + } else { + return &MountError{source, target, fstype, flags, data, errno} + } +} |
