Source file
src/tawesoft.co.uk/go/drop/inheritable.go
Documentation:
src/tawesoft.co.uk/go/drop/inheritable.go
1 package drop
2
3 import (
4 "errors"
5 "fmt"
6 "net"
7 "os"
8 "strings"
9 )
10
11
12
13 type Inheritable interface {
14
15 String() string
16
17
18 Open() (*os.File, error)
19
20
21 Inherit(*os.File) error
22
23
24 Close() error
25 }
26
27
28
29 type InheritableFile struct {
30 path string
31 flags int
32 uid int
33 gid int
34 mode os.FileMode
35 handle *os.File
36 }
37
38
39
40
41
42
43
44
45
46
47
48 func NewInheritableFile(path string, flags int, uid int, gid int, mode os.FileMode) *InheritableFile {
49 return &InheritableFile{
50 path: path,
51 flags: flags,
52 uid: uid,
53 gid: gid,
54 mode: mode,
55 }
56 }
57
58 func (h InheritableFile) String() string {
59 return fmt.Sprintf("<InheritableFile %q>", h.path)
60 }
61
62 func (h *InheritableFile) Open() (*os.File, error) {
63 f, err := os.OpenFile(h.path, h.flags, 0000)
64 if err != nil { return nil, err }
65
66 err = rootSetMode(h.path, h.uid, h.gid, h.mode)
67 if err != nil {
68 f.Close()
69 return nil, err
70 }
71
72 h.handle = f
73
74 return f, nil
75 }
76
77 func (h *InheritableFile) Inherit(f *os.File) error {
78 f.Seek(0, 0)
79 h.handle = f
80 return nil
81 }
82
83 func (h InheritableFile) Handle() *os.File {
84 return h.handle
85 }
86
87 func (h InheritableFile) Close() error {
88 if h.handle == nil { return nil }
89 return h.handle.Close()
90 }
91
92
93
94
95
96
97 type InheritableNetListener struct {
98 network string
99 address string
100 uid int
101 gid int
102 mode os.FileMode
103 handle net.Listener
104 fileHandle *os.File
105 }
106
107 func NewInheritableTCPListener(address string) *InheritableNetListener {
108 return &InheritableNetListener{
109 network: "tcp",
110 address: address,
111 }
112 }
113
114
115
116
117
118
119
120
121
122
123 func NewInheritableUnixListener(address string, uid int, gid int, mode os.FileMode) *InheritableNetListener {
124 return &InheritableNetListener{
125 network: "unix",
126 address: address,
127 uid: uid,
128 gid: gid,
129 mode: mode,
130 }
131 }
132
133 func (h InheritableNetListener) String() string {
134 return fmt.Sprintf("<InheritableNetListener (%s) %q>", h.network, h.address)
135 }
136
137 func (h *InheritableNetListener) Open() (*os.File, error) {
138 nl, err := net.Listen(h.network, h.address)
139 if err != nil { return nil, err }
140
141 h.handle = nl
142
143 if strings.HasPrefix(h.network, "tcp") {
144 if fl, err := nl.(*net.TCPListener).File(); err != nil {
145 nl.Close()
146 return nil, fmt.Errorf("error obtaining TCPListener File handle: %+v", err)
147 } else {
148 return fl, nil
149 }
150 } else if strings.HasPrefix(h.network, "unix") {
151 rootSetMode(h.address, h.uid, h.gid, h.mode)
152
153 if fl, err := nl.(*net.UnixListener).File(); err != nil {
154 nl.Close()
155 return nil, fmt.Errorf("error obtaining UnixListener File handle: %+v", err)
156 } else {
157 return fl, nil
158 }
159 }
160
161 nl.Close()
162 return nil, fmt.Errorf("unsupported network %v", h.network)
163 }
164
165 func (h *InheritableNetListener) Inherit(f *os.File) error {
166 fl, err := net.FileListener(f)
167 if err != nil { return err }
168 h.handle = fl
169 return nil
170 }
171
172 func (h InheritableNetListener) Handle() net.Listener {
173 return h.handle
174 }
175
176 func (h *InheritableNetListener) Close() error {
177 var errs []string
178 if h.fileHandle != nil {
179 err := h.fileHandle.Close()
180 if err != nil {
181 errs = append(errs, fmt.Sprintf("error closing file handle: %v", err))
182 }
183 }
184 if h.handle != nil {
185 err := h.handle.Close()
186 if err != nil {
187 errs = append(errs, fmt.Sprintf("error closing listener: %v", err))
188 }
189 }
190
191 if errs == nil { return nil }
192 return errors.New(strings.Join(errs, "; "))
193 }
194
View as plain text