package proot import ( "context" "errors" "fmt" bindext "sirherobrine23.com.br/go-bds/exec/v2/proot/extensions/bind" prootext "sirherobrine23.com.br/go-bds/exec/v2/proot/extensions/extensions" qemuext "sirherobrine23.com.br/go-bds/exec/v2/proot/extensions/qemu" ) type preparedExtensions struct { config prootext.Config cleanups []func() error } func (pr *Proot) prepareExtensions() (*preparedExtensions, error) { runtimeConfig := &preparedExtensions{ config: prootext.Config{ Rootfs: pr.Rootfs, Binds: pr.Binds, DefaultBinds: pr.DefaultBinds, }.Clone(), } ctx := context.Background() for _, ext := range pr.Extensions { if ext == nil { continue } switch ext.Type() { case prootext.ExtensionTypePath, prootext.ExtensionTypeExec: default: return nil, errors.Join(runtimeConfig.cleanup(), fmt.Errorf("proot extension %q: unsupported type %q", ext.Name(), ext.Type())) } cleanup, err := ext.Apply(ctx, &runtimeConfig.config) if err != nil { return nil, errors.Join(runtimeConfig.cleanup(), fmt.Errorf("proot extension %q: %w", ext.Name(), err)) } if cleanup != nil { runtimeConfig.cleanups = append(runtimeConfig.cleanups, cleanup) } } if err := pr.applyLegacyBinds(ctx, &runtimeConfig.config); err != nil { return nil, errors.Join(runtimeConfig.cleanup(), err) } if err := pr.applyLegacyQemu(ctx, &runtimeConfig.config); err != nil { return nil, errors.Join(runtimeConfig.cleanup(), err) } return runtimeConfig, nil } func (pr *Proot) applyLegacyQemu(ctx context.Context, config *prootext.Config) error { if pr.Qemu == "" { return nil } _, err := qemuext.New(pr.Qemu).Apply(ctx, config) if err != nil { return fmt.Errorf("proot extension %q: %w", "qemu", err) } return nil } func (pr *Proot) applyLegacyBinds(ctx context.Context, config *prootext.Config) error { bindings, err := bindext.DefaultBindings(config.DefaultBinds) if err != nil { return err } for host, guests := range config.Binds { for _, guest := range guests { bindings = append(bindings, bindext.Binding{Host: host, Guest: guest}) } } if len(bindings) == 0 { return nil } _, err = bindext.New(bindings...).Apply(ctx, config) if err != nil { return fmt.Errorf("proot extension %q: %w", "bind", err) } return nil } func (p *preparedExtensions) cleanup() error { if p == nil { return nil } var err error for i := len(p.cleanups) - 1; i >= 0; i-- { err = errors.Join(err, p.cleanups[i]()) } p.cleanups = nil return err }