//go:build amd64 || arm64 package machine import ( "encoding/json" "fmt" "os" "strings" "github.com/containers/podman/v5/pkg/machine/connection" "github.com/containers/storage/pkg/ioutils" ) // GetDevNullFiles returns pointers to Read-only and Write-only DevNull files func GetDevNullFiles() (*os.File, *os.File, error) { dnr, err := os.OpenFile(os.DevNull, os.O_RDONLY, 0755) if err != nil { return nil, nil, err } dnw, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0755) if err != nil { if e := dnr.Close(); e != nil { err = e } return nil, nil, err } return dnr, dnw, nil } // WaitAPIAndPrintInfo prints info about the machine and does a ping test on the // API socket func WaitAPIAndPrintInfo(forwardState APIForwardingState, name, helper, forwardSock string, noInfo, rootful bool) { suffix := "" var fmtString string if name != DefaultMachineName { suffix = " " + name } if forwardState == NoForwarding { return } WaitAndPingAPI(forwardSock) if !noInfo { fmt.Printf("API forwarding listening on: %s\n", forwardSock) if forwardState == DockerGlobal { fmt.Printf("Docker API clients default to this address. You do not need to set DOCKER_HOST.\n\n") } else { stillString := "still " switch forwardState { case NotInstalled: fmtString = ` The system helper service is not installed; the default Docker API socket address can't be used by podman. ` if len(helper) < 1 { fmt.Print(fmtString) } else { fmtString += `If you would like to install it, run the following commands: sudo %s install podman machine stop%[2]s; podman machine start%[2]s ` fmt.Printf(fmtString, helper, suffix) } case MachineLocal: fmt.Printf("\nAnother process was listening on the default Docker API socket address.\n") case ClaimUnsupported: fallthrough default: stillString = "" } fmtString = `You can %sconnect Docker API clients by setting DOCKER_HOST using the following command in your terminal session: %s ` prefix := "" if !strings.Contains(forwardSock, "://") { prefix = "unix://" } fmt.Printf(fmtString, stillString, GetEnvSetString("DOCKER_HOST", prefix+forwardSock)) } } } func PrintRootlessWarning(name string) { suffix := "" if name != DefaultMachineName { suffix = " " + name } fmtString := ` This machine is currently configured in rootless mode. If your containers require root permissions (e.g. ports < 1024), or if you run into compatibility issues with non-podman clients, you can switch using the following command: podman machine set --rootful%s ` fmt.Printf(fmtString, suffix) } // SetRootful modifies the machine's default connection to be either rootful or // rootless func SetRootful(rootful bool, name, rootfulName string) error { return connection.UpdateConnectionIfDefault(rootful, name, rootfulName) } // WriteConfig writes the machine's JSON config file func WriteConfig(configPath string, v VM) error { opts := &ioutils.AtomicFileWriterOptions{ExplicitCommit: true} w, err := ioutils.NewAtomicFileWriterWithOpts(configPath, 0644, opts) if err != nil { return err } defer w.Close() enc := json.NewEncoder(w) enc.SetIndent("", " ") if err := enc.Encode(v); err != nil { return err } // Commit the changes to disk if no errors return w.Commit() }