aboutsummaryrefslogtreecommitdiffhomepage
path: root/helper/proc/files.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-11-12 23:12:38 +0900
committerOphestra <cat@gensokyo.uk>2025-11-12 23:16:13 +0900
commitf347d44c2281f507e3786aa498f634bfa4c92d84 (patch)
treefe85b41d5f6a5e308b87585f46efd64f90221e2b /helper/proc/files.go
parentb5630f6883c874d458d9ae3c666cfb7ae5e3121d (diff)
internal/helper: relocate from helper
This package is ugly and is pending removal only kept alive by xdg-dbus-proxy. Its exported symbols are made available until v0.4.0 where it will be removed for #24. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'helper/proc/files.go')
-rw-r--r--helper/proc/files.go162
1 files changed, 0 insertions, 162 deletions
diff --git a/helper/proc/files.go b/helper/proc/files.go
deleted file mode 100644
index 0612718e..00000000
--- a/helper/proc/files.go
+++ /dev/null
@@ -1,162 +0,0 @@
-package proc
-
-import (
- "context"
- "os"
- "os/exec"
- "sync/atomic"
- "syscall"
- "testing"
- "time"
-)
-
-var FulfillmentTimeout = 2 * time.Second
-
-func init() {
- if testing.Testing() {
- FulfillmentTimeout *= 10
- }
-}
-
-// A File is an extra file with deferred initialisation.
-type File interface {
- // Init initialises File state. Init must not be called more than once.
- Init(fd uintptr, v **os.File) uintptr
- // Fd returns the fd value set on initialisation.
- Fd() uintptr
- // ErrCount returns count of error values emitted during fulfillment.
- ErrCount() int
- // Fulfill is called prior to process creation and must populate its corresponding file address.
- // Calls to dispatchErr must match the return value of ErrCount.
- // Fulfill must not be called more than once.
- Fulfill(ctx context.Context, dispatchErr func(error)) error
-}
-
-// ExtraFilesPre is a linked list storing addresses of [os.File].
-type ExtraFilesPre struct {
- n *ExtraFilesPre
- v *os.File
-}
-
-// Append grows the list by one entry and returns an address of the address of [os.File] stored in the new entry.
-func (f *ExtraFilesPre) Append() (uintptr, **os.File) { return f.append(3) }
-
-// Files returns a slice pointing to a continuous segment of memory containing all addresses stored in f in order.
-func (f *ExtraFilesPre) Files() []*os.File { return f.copy(make([]*os.File, 0, f.len())) }
-
-func (f *ExtraFilesPre) append(i uintptr) (uintptr, **os.File) {
- if f.n == nil {
- f.n = new(ExtraFilesPre)
- return i, &f.v
- }
- return f.n.append(i + 1)
-}
-func (f *ExtraFilesPre) len() uintptr {
- if f == nil {
- return 0
- }
- return f.n.len() + 1
-}
-func (f *ExtraFilesPre) copy(e []*os.File) []*os.File {
- if f == nil {
- // the public methods ensure the first call is never nil;
- // the last element is unused, slice it off here
- return e[:len(e)-1]
- }
- return f.n.copy(append(e, f.v))
-}
-
-// Fulfill calls the [File.Fulfill] method on all files, starts cmd and blocks until all fulfillment completes.
-func Fulfill(ctx context.Context,
- v *[]*os.File, start func() error,
- files []File, extraFiles *ExtraFilesPre,
-) (err error) {
- var ecs int
- for _, o := range files {
- ecs += o.ErrCount()
- }
- ec := make(chan error, ecs)
-
- c, cancel := context.WithTimeout(ctx, FulfillmentTimeout)
- defer cancel()
-
- for _, f := range files {
- err = f.Fulfill(c, makeDispatchErr(f, ec))
- if err != nil {
- return
- }
- }
-
- *v = extraFiles.Files()
- if err = start(); err != nil {
- return
- }
-
- for ecs > 0 {
- select {
- case err = <-ec:
- ecs--
- if err != nil {
- break
- }
- case <-ctx.Done():
- err = syscall.ECANCELED
- break
- }
- }
- return
-}
-
-// InitFile initialises f as part of the slice extraFiles points to,
-// and returns its final fd value.
-func InitFile(f File, extraFiles *ExtraFilesPre) (fd uintptr) { return f.Init(extraFiles.Append()) }
-
-// BaseFile implements the Init method of the File interface and provides indirect access to extra file state.
-type BaseFile struct {
- fd uintptr
- v **os.File
-}
-
-func (f *BaseFile) Init(fd uintptr, v **os.File) uintptr {
- if v == nil || fd < 3 {
- panic("invalid extra file initial state")
- }
- if f.v != nil {
- panic("extra file initialised twice")
- }
- f.fd, f.v = fd, v
- return fd
-}
-
-func (f *BaseFile) Fd() uintptr {
- if f.v == nil {
- panic("use of uninitialised extra file")
- }
- return f.fd
-}
-
-func (f *BaseFile) Set(v *os.File) {
- *f.v = v // runtime guards against use before init
-}
-
-func makeDispatchErr(f File, ec chan<- error) func(error) {
- c := new(atomic.Int32)
- c.Store(int32(f.ErrCount()))
- return func(err error) {
- if c.Add(-1) < 0 {
- panic("unexpected error dispatches")
- }
- ec <- err
- }
-}
-
-func ExtraFile(cmd *exec.Cmd, f *os.File) (fd uintptr) {
- return ExtraFileSlice(&cmd.ExtraFiles, f)
-}
-
-func ExtraFileSlice(extraFiles *[]*os.File, f *os.File) (fd uintptr) {
- // ExtraFiles: If non-nil, entry i becomes file descriptor 3+i.
- fd = uintptr(3 + len(*extraFiles))
- *extraFiles = append(*extraFiles, f)
- return
-}