aboutsummaryrefslogtreecommitdiffhomepage
path: root/sandbox/path.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-03-17 02:55:36 +0900
committerOphestra <cat@gensokyo.uk>2025-03-17 02:55:36 +0900
commit24618ab9a1524e8b8986a9bf67667288e642fcf1 (patch)
treeb3f2a71a2c9bedf937d0fec00092ad9133cb3ec9 /sandbox/path.go
parent9ce4706a0766880c072cccd2643d66f614a6a16b (diff)
sandbox: move out of internal
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'sandbox/path.go')
-rw-r--r--sandbox/path.go75
1 files changed, 75 insertions, 0 deletions
diff --git a/sandbox/path.go b/sandbox/path.go
new file mode 100644
index 00000000..6c5a6e2c
--- /dev/null
+++ b/sandbox/path.go
@@ -0,0 +1,75 @@
+package sandbox
+
+import (
+ "errors"
+ "io/fs"
+ "os"
+ "path"
+ "strings"
+ "syscall"
+)
+
+const (
+ hostPath = "/" + hostDir
+ hostDir = "host"
+ sysrootPath = "/" + sysrootDir
+ sysrootDir = "sysroot"
+)
+
+func toSysroot(name string) string {
+ name = strings.TrimLeftFunc(name, func(r rune) bool { return r == '/' })
+ return path.Join(sysrootPath, name)
+}
+
+func toHost(name string) string {
+ name = strings.TrimLeftFunc(name, func(r rune) bool { return r == '/' })
+ return path.Join(hostPath, name)
+}
+
+func realpathHost(name string) (string, error) {
+ source := toHost(name)
+ rp, err := os.Readlink(source)
+
+ if err != nil {
+ if errors.Is(err, syscall.EINVAL) {
+ // not a symlink
+ return name, nil
+ }
+ return "", err
+ }
+
+ if !path.IsAbs(rp) {
+ return name, nil
+ }
+ msg.Verbosef("path %q resolves to %q", name, rp)
+ return rp, nil
+}
+
+func createFile(name string, perm os.FileMode, content []byte) error {
+ if err := os.MkdirAll(path.Dir(name), 0755); err != nil {
+ return err
+ }
+ f, err := os.OpenFile(name, syscall.O_CREAT|syscall.O_EXCL|syscall.O_WRONLY, perm)
+ if err != nil {
+ return err
+ }
+ if content != nil {
+ _, err = f.Write(content)
+ }
+ return errors.Join(f.Close(), err)
+}
+
+func ensureFile(name string, perm os.FileMode) error {
+ fi, err := os.Stat(name)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ return err
+ }
+ return createFile(name, perm, nil)
+ }
+
+ if mode := fi.Mode(); mode&fs.ModeDir != 0 || mode&fs.ModeSymlink != 0 {
+ err = syscall.EISDIR
+ }
+ return err
+}