aboutsummaryrefslogtreecommitdiffhomepage
path: root/container/errors.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-08-29 01:06:12 +0900
committerOphestra <cat@gensokyo.uk>2025-08-29 01:06:12 +0900
commit84ad9791e2f373d5869b2da6675c70f23deac8a0 (patch)
treeb5c5b661287c62d62d4ec3dbf08f947df1677e70 /container/errors.go
parentb14690aa77b3d5f86c4d1b1965675d6d82789e32 (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.go60
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}
+ }
+}