hst: replace internal/app error
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Test / Create distribution (push) Successful in 43s
				
			
		
			
				
	
				Test / Hpkg (push) Successful in 4m3s
				
			
		
			
				
	
				Test / Sandbox (race detector) (push) Successful in 4m36s
				
			
		
			
				
	
				Test / Hakurei (race detector) (push) Successful in 5m17s
				
			
		
			
				
	
				Test / Sandbox (push) Successful in 1m27s
				
			
		
			
				
	
				Test / Hakurei (push) Successful in 2m15s
				
			
		
			
				
	
				Test / Flake checks (push) Successful in 1m28s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 43s
				
			Test / Hpkg (push) Successful in 4m3s
				
			Test / Sandbox (race detector) (push) Successful in 4m36s
				
			Test / Hakurei (race detector) (push) Successful in 5m17s
				
			Test / Sandbox (push) Successful in 1m27s
				
			Test / Hakurei (push) Successful in 2m15s
				
			Test / Flake checks (push) Successful in 1m28s
				
			This turns out to still be quite useful across internal/app and its relatives. Perhaps a cleaner replacement for baseError. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
		
							parent
							
								
									1cdc6b4246
								
							
						
					
					
						commit
						8690419c2d
					
				
							
								
								
									
										30
									
								
								hst/hst.go
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								hst/hst.go
									
									
									
									
									
								
							| @ -2,12 +2,42 @@ | |||||||
| package hst | package hst | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"net" | ||||||
|  | 	"os" | ||||||
|  | 
 | ||||||
| 	"hakurei.app/container" | 	"hakurei.app/container" | ||||||
| 	"hakurei.app/container/seccomp" | 	"hakurei.app/container/seccomp" | ||||||
| 	"hakurei.app/system" | 	"hakurei.app/system" | ||||||
| 	"hakurei.app/system/dbus" | 	"hakurei.app/system/dbus" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // An AppError is returned while starting an app according to [hst.Config]. | ||||||
|  | type AppError struct { | ||||||
|  | 	Step string | ||||||
|  | 	Err  error | ||||||
|  | 	Msg  string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (e *AppError) Error() string { return e.Err.Error() } | ||||||
|  | func (e *AppError) Unwrap() error { return e.Err } | ||||||
|  | func (e *AppError) Message() string { | ||||||
|  | 	if e.Msg != "" { | ||||||
|  | 		return e.Msg | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch { | ||||||
|  | 	case errors.As(e.Err, new(*os.PathError)), | ||||||
|  | 		errors.As(e.Err, new(*os.LinkError)), | ||||||
|  | 		errors.As(e.Err, new(*os.SyscallError)), | ||||||
|  | 		errors.As(e.Err, new(*net.OpError)): | ||||||
|  | 		return "cannot " + e.Error() | ||||||
|  | 
 | ||||||
|  | 	default: | ||||||
|  | 		return "cannot " + e.Step + ": " + e.Error() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Paths contains environment-dependent paths used by hakurei. | // Paths contains environment-dependent paths used by hakurei. | ||||||
| type Paths struct { | type Paths struct { | ||||||
| 	// temporary directory returned by [os.TempDir] (usually `/tmp`) | 	// temporary directory returned by [os.TempDir] (usually `/tmp`) | ||||||
|  | |||||||
| @ -2,11 +2,93 @@ package hst_test | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
|  | 	"errors" | ||||||
|  | 	"net" | ||||||
|  | 	"os" | ||||||
|  | 	"syscall" | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
|  | 	"hakurei.app/container" | ||||||
|  | 	"hakurei.app/container/stub" | ||||||
| 	"hakurei.app/hst" | 	"hakurei.app/hst" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | func TestAppError(t *testing.T) { | ||||||
|  | 	testCases := []struct { | ||||||
|  | 		name    string | ||||||
|  | 		err     error | ||||||
|  | 		s       string | ||||||
|  | 		message string | ||||||
|  | 		is, isF error | ||||||
|  | 	}{ | ||||||
|  | 		{"message", &hst.AppError{Step: "obtain uid from hsu", Err: stub.UniqueError(0), | ||||||
|  | 			Msg: "the setuid helper is missing: /run/wrappers/bin/hsu"}, | ||||||
|  | 			"unique error 0 injected by the test suite", | ||||||
|  | 			"the setuid helper is missing: /run/wrappers/bin/hsu", | ||||||
|  | 			stub.UniqueError(0), os.ErrNotExist}, | ||||||
|  | 
 | ||||||
|  | 		{"os.PathError", &hst.AppError{Step: "passthrough os.PathError", | ||||||
|  | 			Err: &os.PathError{Op: "stat", Path: "/proc/nonexistent", Err: os.ErrNotExist}}, | ||||||
|  | 			"stat /proc/nonexistent: file does not exist", | ||||||
|  | 			"cannot stat /proc/nonexistent: file does not exist", | ||||||
|  | 			os.ErrNotExist, stub.UniqueError(0xdeadbeef)}, | ||||||
|  | 
 | ||||||
|  | 		{"os.LinkError", &hst.AppError{Step: "passthrough os.LinkError", | ||||||
|  | 			Err: &os.LinkError{Op: "link", Old: "/proc/self", New: "/proc/nonexistent", Err: os.ErrNotExist}}, | ||||||
|  | 			"link /proc/self /proc/nonexistent: file does not exist", | ||||||
|  | 			"cannot link /proc/self /proc/nonexistent: file does not exist", | ||||||
|  | 			os.ErrNotExist, stub.UniqueError(0xdeadbeef)}, | ||||||
|  | 
 | ||||||
|  | 		{"os.SyscallError", &hst.AppError{Step: "passthrough os.SyscallError", | ||||||
|  | 			Err: &os.SyscallError{Syscall: "meow", Err: syscall.ENOSYS}}, | ||||||
|  | 			"meow: function not implemented", | ||||||
|  | 			"cannot meow: function not implemented", | ||||||
|  | 			syscall.ENOSYS, syscall.ENOTRECOVERABLE}, | ||||||
|  | 
 | ||||||
|  | 		{"net.OpError", &hst.AppError{Step: "passthrough net.OpError", | ||||||
|  | 			Err: &net.OpError{Op: "dial", Net: "cat", Err: net.UnknownNetworkError("cat")}}, | ||||||
|  | 			"dial cat: unknown network cat", | ||||||
|  | 			"cannot dial cat: unknown network cat", | ||||||
|  | 			net.UnknownNetworkError("cat"), syscall.ENOTRECOVERABLE}, | ||||||
|  | 
 | ||||||
|  | 		{"default", &hst.AppError{Step: "initialise container configuration", Err: stub.UniqueError(1)}, | ||||||
|  | 			"unique error 1 injected by the test suite", | ||||||
|  | 			"cannot initialise container configuration: unique error 1 injected by the test suite", | ||||||
|  | 			stub.UniqueError(1), os.ErrInvalid}, | ||||||
|  | 	} | ||||||
|  | 	for _, tc := range testCases { | ||||||
|  | 		t.Run(tc.name, func(t *testing.T) { | ||||||
|  | 			t.Run("error", func(t *testing.T) { | ||||||
|  | 				if got := tc.err.Error(); got != tc.s { | ||||||
|  | 					t.Errorf("Error: %s, want %s", got, tc.s) | ||||||
|  | 				} | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			t.Run("message", func(t *testing.T) { | ||||||
|  | 				gotMessage, gotMessageOk := container.GetErrorMessage(tc.err) | ||||||
|  | 				if want := tc.message != "\x00"; gotMessageOk != want { | ||||||
|  | 					t.Errorf("GetErrorMessage: ok = %v, want %v", gotMessage, want) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if gotMessageOk { | ||||||
|  | 					if gotMessage != tc.message { | ||||||
|  | 						t.Errorf("GetErrorMessage: %s, want %s", gotMessage, tc.message) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			t.Run("is", func(t *testing.T) { | ||||||
|  | 				if !errors.Is(tc.err, tc.is) { | ||||||
|  | 					t.Errorf("Is: unexpected false for %v", tc.is) | ||||||
|  | 				} | ||||||
|  | 				if errors.Is(tc.err, tc.isF) { | ||||||
|  | 					t.Errorf("Is: unexpected true for %v", tc.isF) | ||||||
|  | 				} | ||||||
|  | 			}) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestTemplate(t *testing.T) { | func TestTemplate(t *testing.T) { | ||||||
| 	const want = `{ | 	const want = `{ | ||||||
| 	"id": "org.chromium.Chromium", | 	"id": "org.chromium.Chromium", | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import ( | |||||||
| 	"log" | 	"log" | ||||||
| 
 | 
 | ||||||
| 	"hakurei.app/container" | 	"hakurei.app/container" | ||||||
|  | 	"hakurei.app/hst" | ||||||
| 	"hakurei.app/internal/hlog" | 	"hakurei.app/internal/hlog" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -30,7 +31,7 @@ func PrintRunStateErr(rs *RunState, runErr error) (code int) { | |||||||
| 				} else { | 				} else { | ||||||
| 					// InnerErr is returned by c.Save(&sd, seal.ct), and are always unwrapped | 					// InnerErr is returned by c.Save(&sd, seal.ct), and are always unwrapped | ||||||
| 					printMessageError("error returned during revert:", | 					printMessageError("error returned during revert:", | ||||||
| 						&FinaliseError{Step: "save process state", Err: se.InnerErr}) | 						&hst.AppError{Step: "save process state", Err: se.InnerErr}) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -133,7 +134,7 @@ func (e *StateStoreError) equiv(step string) error { | |||||||
| 	if e.Inner && e.InnerErr == nil && e.DoErr == nil && e.OpErr == nil && errors.Join(e.Errs...) == nil { | 	if e.Inner && e.InnerErr == nil && e.DoErr == nil && e.OpErr == nil && errors.Join(e.Errs...) == nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} else { | 	} else { | ||||||
| 		return &FinaliseError{Step: step, Err: e} | 		return &hst.AppError{Step: step, Err: e} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"hakurei.app/container" | 	"hakurei.app/container" | ||||||
|  | 	"hakurei.app/hst" | ||||||
| 	"hakurei.app/internal" | 	"hakurei.app/internal" | ||||||
| 	"hakurei.app/internal/app/state" | 	"hakurei.app/internal/app/state" | ||||||
| 	"hakurei.app/internal/hlog" | 	"hakurei.app/internal/hlog" | ||||||
| @ -119,7 +120,7 @@ func (seal *Outcome) Run(rs *RunState) error { | |||||||
| 
 | 
 | ||||||
| 	var e *gob.Encoder | 	var e *gob.Encoder | ||||||
| 	if fd, encoder, err := container.Setup(&cmd.ExtraFiles); err != nil { | 	if fd, encoder, err := container.Setup(&cmd.ExtraFiles); err != nil { | ||||||
| 		return &FinaliseError{Step: "create shim setup pipe", Err: err} | 		return &hst.AppError{Step: "create shim setup pipe", Err: err} | ||||||
| 	} else { | 	} else { | ||||||
| 		e = encoder | 		e = encoder | ||||||
| 		cmd.Env = []string{ | 		cmd.Env = []string{ | ||||||
| @ -139,7 +140,7 @@ func (seal *Outcome) Run(rs *RunState) error { | |||||||
| 	hlog.Verbosef("setuid helper at %s", hsuPath) | 	hlog.Verbosef("setuid helper at %s", hsuPath) | ||||||
| 	hlog.Suspend() | 	hlog.Suspend() | ||||||
| 	if err := cmd.Start(); err != nil { | 	if err := cmd.Start(); err != nil { | ||||||
| 		return &FinaliseError{Step: "start setuid wrapper", Err: err} | 		return &hst.AppError{Step: "start setuid wrapper", Err: err} | ||||||
| 	} | 	} | ||||||
| 	rs.setStart() | 	rs.setStart() | ||||||
| 
 | 
 | ||||||
| @ -159,7 +160,7 @@ func (seal *Outcome) Run(rs *RunState) error { | |||||||
| 	case err := <-setupErr: | 	case err := <-setupErr: | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			hlog.Resume() | 			hlog.Resume() | ||||||
| 			return &FinaliseError{Step: "transmit shim config", Err: err} | 			return &hst.AppError{Step: "transmit shim config", Err: err} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	case <-ctx.Done(): | 	case <-ctx.Done(): | ||||||
|  | |||||||
| @ -8,7 +8,6 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
| 	"io/fs" | 	"io/fs" | ||||||
| 	"net" |  | ||||||
| 	"os" | 	"os" | ||||||
| 	"slices" | 	"slices" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| @ -28,35 +27,9 @@ import ( | |||||||
| 	"hakurei.app/system/wayland" | 	"hakurei.app/system/wayland" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // A FinaliseError is returned while finalising a [hst.Config] outcome. |  | ||||||
| type FinaliseError struct { |  | ||||||
| 	Step string |  | ||||||
| 	Err  error |  | ||||||
| 	Msg  string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (e *FinaliseError) Error() string { return e.Err.Error() } |  | ||||||
| func (e *FinaliseError) Unwrap() error { return e.Err } |  | ||||||
| func (e *FinaliseError) Message() string { |  | ||||||
| 	if e.Msg != "" { |  | ||||||
| 		return e.Msg |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	switch { |  | ||||||
| 	case errors.As(e.Err, new(*os.PathError)), |  | ||||||
| 		errors.As(e.Err, new(*os.LinkError)), |  | ||||||
| 		errors.As(e.Err, new(*os.SyscallError)), |  | ||||||
| 		errors.As(e.Err, new(*net.OpError)): |  | ||||||
| 		return "cannot " + e.Error() |  | ||||||
| 
 |  | ||||||
| 	default: |  | ||||||
| 		return "cannot " + e.Step + ": " + e.Error() |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func newWithMessage(msg string) error { return newWithMessageError(msg, os.ErrInvalid) } | func newWithMessage(msg string) error { return newWithMessageError(msg, os.ErrInvalid) } | ||||||
| func newWithMessageError(msg string, err error) error { | func newWithMessageError(msg string, err error) error { | ||||||
| 	return &FinaliseError{Step: "finalise", Err: err, Msg: msg} | 	return &hst.AppError{Step: "finalise", Err: err, Msg: msg} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // An Outcome is the runnable state of a hakurei container via [hst.Config]. | // An Outcome is the runnable state of a hakurei container via [hst.Config]. | ||||||
| @ -188,7 +161,7 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 		// encode initial configuration for state tracking | 		// encode initial configuration for state tracking | ||||||
| 		ct := new(bytes.Buffer) | 		ct := new(bytes.Buffer) | ||||||
| 		if err := gob.NewEncoder(ct).Encode(config); err != nil { | 		if err := gob.NewEncoder(ct).Encode(config); err != nil { | ||||||
| 			return &FinaliseError{Step: "encode initial config", Err: err} | 			return &hst.AppError{Step: "encode initial config", Err: err} | ||||||
| 		} | 		} | ||||||
| 		seal.ct = ct | 		seal.ct = ct | ||||||
| 	} | 	} | ||||||
| @ -238,7 +211,7 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 		if config.Path == nil { | 		if config.Path == nil { | ||||||
| 			if len(config.Args) > 0 { | 			if len(config.Args) > 0 { | ||||||
| 				if p, err := sys.LookPath(config.Args[0]); err != nil { | 				if p, err := sys.LookPath(config.Args[0]); err != nil { | ||||||
| 					return &FinaliseError{Step: "look up executable file", Err: err} | 					return &hst.AppError{Step: "look up executable file", Err: err} | ||||||
| 				} else if config.Path, err = container.NewAbs(p); err != nil { | 				} else if config.Path, err = container.NewAbs(p); err != nil { | ||||||
| 					return newWithMessageError(err.Error(), err) | 					return newWithMessageError(err.Error(), err) | ||||||
| 				} | 				} | ||||||
| @ -304,7 +277,7 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 		seal.container, seal.env, err = newContainer(config.Container, sys, seal.id.String(), &uid, &gid) | 		seal.container, seal.env, err = newContainer(config.Container, sys, seal.id.String(), &uid, &gid) | ||||||
| 		seal.waitDelay = config.Container.WaitDelay | 		seal.waitDelay = config.Container.WaitDelay | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return &FinaliseError{Step: "initialise container configuration", Err: err} | 			return &hst.AppError{Step: "initialise container configuration", Err: err} | ||||||
| 		} | 		} | ||||||
| 		if len(config.Args) == 0 { | 		if len(config.Args) == 0 { | ||||||
| 			config.Args = []string{config.Path.String()} | 			config.Args = []string{config.Path.String()} | ||||||
| @ -427,7 +400,7 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 			if socketPath != nil { | 			if socketPath != nil { | ||||||
| 				if _, err := sys.Stat(socketPath.String()); err != nil { | 				if _, err := sys.Stat(socketPath.String()); err != nil { | ||||||
| 					if !errors.Is(err, fs.ErrNotExist) { | 					if !errors.Is(err, fs.ErrNotExist) { | ||||||
| 						return &FinaliseError{Step: fmt.Sprintf("access X11 socket %q", socketPath), Err: err} | 						return &hst.AppError{Step: fmt.Sprintf("access X11 socket %q", socketPath), Err: err} | ||||||
| 					} | 					} | ||||||
| 				} else { | 				} else { | ||||||
| 					seal.sys.UpdatePermType(system.EX11, socketPath.String(), acl.Read, acl.Write, acl.Execute) | 					seal.sys.UpdatePermType(system.EX11, socketPath.String(), acl.Read, acl.Write, acl.Execute) | ||||||
| @ -451,14 +424,14 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 
 | 
 | ||||||
| 		if _, err := sys.Stat(pulseRuntimeDir.String()); err != nil { | 		if _, err := sys.Stat(pulseRuntimeDir.String()); err != nil { | ||||||
| 			if !errors.Is(err, fs.ErrNotExist) { | 			if !errors.Is(err, fs.ErrNotExist) { | ||||||
| 				return &FinaliseError{Step: fmt.Sprintf("access PulseAudio directory %q", pulseRuntimeDir), Err: err} | 				return &hst.AppError{Step: fmt.Sprintf("access PulseAudio directory %q", pulseRuntimeDir), Err: err} | ||||||
| 			} | 			} | ||||||
| 			return newWithMessage(fmt.Sprintf("PulseAudio directory %q not found", pulseRuntimeDir)) | 			return newWithMessage(fmt.Sprintf("PulseAudio directory %q not found", pulseRuntimeDir)) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if s, err := sys.Stat(pulseSocket.String()); err != nil { | 		if s, err := sys.Stat(pulseSocket.String()); err != nil { | ||||||
| 			if !errors.Is(err, fs.ErrNotExist) { | 			if !errors.Is(err, fs.ErrNotExist) { | ||||||
| 				return &FinaliseError{Step: fmt.Sprintf("access PulseAudio socket %q", pulseSocket), Err: err} | 				return &hst.AppError{Step: fmt.Sprintf("access PulseAudio socket %q", pulseSocket), Err: err} | ||||||
| 			} | 			} | ||||||
| 			return newWithMessage(fmt.Sprintf("PulseAudio directory %q found but socket does not exist", pulseRuntimeDir)) | 			return newWithMessage(fmt.Sprintf("PulseAudio directory %q found but socket does not exist", pulseRuntimeDir)) | ||||||
| 		} else { | 		} else { | ||||||
| @ -482,7 +455,7 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 			// from environment | 			// from environment | ||||||
| 			if p, ok := sys.LookupEnv(pulseCookie); ok { | 			if p, ok := sys.LookupEnv(pulseCookie); ok { | ||||||
| 				if a, err := container.NewAbs(p); err != nil { | 				if a, err := container.NewAbs(p); err != nil { | ||||||
| 					return &FinaliseError{Step: paLocateStep, Err: err} | 					return &hst.AppError{Step: paLocateStep, Err: err} | ||||||
| 				} else { | 				} else { | ||||||
| 					// this takes precedence, do not verify whether the file is accessible | 					// this takes precedence, do not verify whether the file is accessible | ||||||
| 					paCookiePath = a | 					paCookiePath = a | ||||||
| @ -493,7 +466,7 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 			// $HOME/.pulse-cookie | 			// $HOME/.pulse-cookie | ||||||
| 			if p, ok := sys.LookupEnv(home); ok { | 			if p, ok := sys.LookupEnv(home); ok { | ||||||
| 				if a, err := container.NewAbs(p); err != nil { | 				if a, err := container.NewAbs(p); err != nil { | ||||||
| 					return &FinaliseError{Step: paLocateStep, Err: err} | 					return &hst.AppError{Step: paLocateStep, Err: err} | ||||||
| 				} else { | 				} else { | ||||||
| 					paCookiePath = a.Append(".pulse-cookie") | 					paCookiePath = a.Append(".pulse-cookie") | ||||||
| 				} | 				} | ||||||
| @ -501,7 +474,7 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 				if s, err := sys.Stat(paCookiePath.String()); err != nil { | 				if s, err := sys.Stat(paCookiePath.String()); err != nil { | ||||||
| 					paCookiePath = nil | 					paCookiePath = nil | ||||||
| 					if !errors.Is(err, fs.ErrNotExist) { | 					if !errors.Is(err, fs.ErrNotExist) { | ||||||
| 						return &FinaliseError{Step: "access PulseAudio cookie", Err: err} | 						return &hst.AppError{Step: "access PulseAudio cookie", Err: err} | ||||||
| 					} | 					} | ||||||
| 					// fallthrough | 					// fallthrough | ||||||
| 				} else if s.IsDir() { | 				} else if s.IsDir() { | ||||||
| @ -514,14 +487,14 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 			// $XDG_CONFIG_HOME/pulse/cookie | 			// $XDG_CONFIG_HOME/pulse/cookie | ||||||
| 			if p, ok := sys.LookupEnv(xdgConfigHome); ok { | 			if p, ok := sys.LookupEnv(xdgConfigHome); ok { | ||||||
| 				if a, err := container.NewAbs(p); err != nil { | 				if a, err := container.NewAbs(p); err != nil { | ||||||
| 					return &FinaliseError{Step: paLocateStep, Err: err} | 					return &hst.AppError{Step: paLocateStep, Err: err} | ||||||
| 				} else { | 				} else { | ||||||
| 					paCookiePath = a.Append("pulse", "cookie") | 					paCookiePath = a.Append("pulse", "cookie") | ||||||
| 				} | 				} | ||||||
| 				if s, err := sys.Stat(paCookiePath.String()); err != nil { | 				if s, err := sys.Stat(paCookiePath.String()); err != nil { | ||||||
| 					paCookiePath = nil | 					paCookiePath = nil | ||||||
| 					if !errors.Is(err, fs.ErrNotExist) { | 					if !errors.Is(err, fs.ErrNotExist) { | ||||||
| 						return &FinaliseError{Step: "access PulseAudio cookie", Err: err} | 						return &hst.AppError{Step: "access PulseAudio cookie", Err: err} | ||||||
| 					} | 					} | ||||||
| 					// fallthrough | 					// fallthrough | ||||||
| 				} else if s.IsDir() { | 				} else if s.IsDir() { | ||||||
| @ -609,7 +582,7 @@ func (seal *Outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co | |||||||
| 	seal.container.Env = make([]string, 0, len(seal.env)) | 	seal.container.Env = make([]string, 0, len(seal.env)) | ||||||
| 	for k, v := range seal.env { | 	for k, v := range seal.env { | ||||||
| 		if strings.IndexByte(k, '=') != -1 { | 		if strings.IndexByte(k, '=') != -1 { | ||||||
| 			return &FinaliseError{Step: "flatten environment", Err: syscall.EINVAL, | 			return &hst.AppError{Step: "flatten environment", Err: syscall.EINVAL, | ||||||
| 				Msg: fmt.Sprintf("invalid environment variable %s", k)} | 				Msg: fmt.Sprintf("invalid environment variable %s", k)} | ||||||
| 		} | 		} | ||||||
| 		seal.container.Env = append(seal.container.Env, k+"="+v) | 		seal.container.Env = append(seal.container.Env, k+"="+v) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user