File: serve_windows.go

package info (click to toggle)
podman 5.4.2%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 23,124 kB
  • sloc: sh: 6,119; perl: 2,710; python: 2,258; ansic: 1,556; makefile: 1,022; xml: 121; ruby: 42; awk: 12; csh: 8
file content (94 lines) | stat: -rw-r--r-- 2,430 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package plan9

import (
	"fmt"
	"net"
	"os"
	"path/filepath"

	"github.com/hugelgupf/p9/fsimpl/localfs"
	"github.com/hugelgupf/p9/p9"
	"github.com/sirupsen/logrus"
)

type Server struct {
	server *p9.Server
	// TODO: Once server has a proper Close() we don't need this.
	// This is basically just a short-circuit to actually close the server
	// without that ability.
	listener net.Listener
	// Errors from the server being started will come out here.
	errChan chan error
}

// Expose a single directory (and all children) via the given net.Listener.
// Directory given must be an absolute path and must exist.
func New9pServer(listener net.Listener, exposeDir string) (*Server, error) {
	// Verify that exposeDir makes sense.
	if !filepath.IsAbs(exposeDir) {
		return nil, fmt.Errorf("path to expose to machine must be absolute: %s", exposeDir)
	}
	stat, err := os.Stat(exposeDir)
	if err != nil {
		return nil, fmt.Errorf("cannot stat path to expose to machine: %w", err)
	}
	if !stat.IsDir() {
		return nil, fmt.Errorf("path to expose to machine must be a directory: %s", exposeDir)
	}

	server := p9.NewServer(localfs.Attacher(exposeDir), []p9.ServerOpt{}...)
	if server == nil {
		return nil, fmt.Errorf("p9.NewServer returned nil")
	}

	errChan := make(chan error)

	// TODO: Use a channel to pass back this if it occurs within a
	// reasonable timeframe.
	go func() {
		errChan <- server.Serve(listener)
		close(errChan)
	}()

	toReturn := new(Server)
	toReturn.listener = listener
	toReturn.server = server
	toReturn.errChan = errChan

	// Just before returning, check to see if we got an error off server
	// startup.
	select {
	case err := <-errChan:
		return nil, fmt.Errorf("starting 9p server: %w", err)
	default:
		logrus.Infof("Successfully started 9p server for directory %s", exposeDir)
	}

	return toReturn, nil
}

// Stop a running server.
// Please note that this does *BAD THINGS* to clients if they are still running
// when the server stops. Processes get stuck in I/O deep sleep and zombify, and
// nothing I do save restarting the VM can remove the zombies.
func (s *Server) Stop() error {
	if s.server != nil {
		if err := s.listener.Close(); err != nil {
			return err
		}
		s.server = nil
	}

	return nil
}

// Wait for an error from a running server.
func (s *Server) WaitForError() error {
	if s.server != nil {
		err := <-s.errChan
		return err
	}

	// Server already down, return nil
	return nil
}