Blame


1 64abb42a 2018-04-10 noreply package ufs
2 64abb42a 2018-04-10 noreply
3 64abb42a 2018-04-10 noreply import (
4 64abb42a 2018-04-10 noreply "context"
5 64abb42a 2018-04-10 noreply "io"
6 64abb42a 2018-04-10 noreply "io/ioutil"
7 64abb42a 2018-04-10 noreply "os"
8 64abb42a 2018-04-10 noreply "os/user"
9 64abb42a 2018-04-10 noreply "path/filepath"
10 64abb42a 2018-04-10 noreply "strconv"
11 64abb42a 2018-04-10 noreply "sync"
12 64abb42a 2018-04-10 noreply "syscall"
13 64abb42a 2018-04-10 noreply
14 c55b00ed 2021-12-31 op "git.omarpolo.com/go-p9p"
15 64abb42a 2018-04-10 noreply )
16 64abb42a 2018-04-10 noreply
17 64abb42a 2018-04-10 noreply type session struct {
18 64abb42a 2018-04-10 noreply sync.Mutex
19 64abb42a 2018-04-10 noreply rootRef *FileRef
20 64abb42a 2018-04-10 noreply refs map[p9p.Fid]*FileRef
21 64abb42a 2018-04-10 noreply }
22 64abb42a 2018-04-10 noreply
23 64abb42a 2018-04-10 noreply func NewSession(ctx context.Context, root string) (p9p.Session, error) {
24 64abb42a 2018-04-10 noreply return &session{
25 64abb42a 2018-04-10 noreply rootRef: &FileRef{Path: root},
26 64abb42a 2018-04-10 noreply refs: make(map[p9p.Fid]*FileRef),
27 64abb42a 2018-04-10 noreply }, nil
28 64abb42a 2018-04-10 noreply }
29 64abb42a 2018-04-10 noreply
30 64abb42a 2018-04-10 noreply func (sess *session) getRef(fid p9p.Fid) (*FileRef, error) {
31 64abb42a 2018-04-10 noreply sess.Lock()
32 64abb42a 2018-04-10 noreply defer sess.Unlock()
33 64abb42a 2018-04-10 noreply
34 64abb42a 2018-04-10 noreply if fid == p9p.NOFID {
35 64abb42a 2018-04-10 noreply return nil, p9p.ErrUnknownfid
36 64abb42a 2018-04-10 noreply }
37 64abb42a 2018-04-10 noreply
38 64abb42a 2018-04-10 noreply ref, found := sess.refs[fid]
39 64abb42a 2018-04-10 noreply if !found {
40 64abb42a 2018-04-10 noreply return nil, p9p.ErrUnknownfid
41 64abb42a 2018-04-10 noreply }
42 64abb42a 2018-04-10 noreply
43 64abb42a 2018-04-10 noreply if err := ref.Stat(); err != nil {
44 64abb42a 2018-04-10 noreply return nil, err
45 64abb42a 2018-04-10 noreply }
46 64abb42a 2018-04-10 noreply
47 64abb42a 2018-04-10 noreply return ref, nil
48 64abb42a 2018-04-10 noreply }
49 64abb42a 2018-04-10 noreply
50 64abb42a 2018-04-10 noreply func (sess *session) newRef(fid p9p.Fid, path string) (*FileRef, error) {
51 64abb42a 2018-04-10 noreply sess.Lock()
52 64abb42a 2018-04-10 noreply defer sess.Unlock()
53 64abb42a 2018-04-10 noreply
54 64abb42a 2018-04-10 noreply if fid == p9p.NOFID {
55 64abb42a 2018-04-10 noreply return nil, p9p.ErrUnknownfid
56 64abb42a 2018-04-10 noreply }
57 64abb42a 2018-04-10 noreply
58 64abb42a 2018-04-10 noreply _, found := sess.refs[fid]
59 64abb42a 2018-04-10 noreply if found {
60 64abb42a 2018-04-10 noreply return nil, p9p.ErrDupfid
61 64abb42a 2018-04-10 noreply }
62 64abb42a 2018-04-10 noreply
63 64abb42a 2018-04-10 noreply ref := &FileRef{Path: path}
64 64abb42a 2018-04-10 noreply if err := ref.Stat(); err != nil {
65 64abb42a 2018-04-10 noreply return nil, err
66 64abb42a 2018-04-10 noreply }
67 64abb42a 2018-04-10 noreply
68 64abb42a 2018-04-10 noreply sess.refs[fid] = ref
69 64abb42a 2018-04-10 noreply return ref, nil
70 64abb42a 2018-04-10 noreply }
71 64abb42a 2018-04-10 noreply
72 64abb42a 2018-04-10 noreply func (sess *session) Auth(ctx context.Context, afid p9p.Fid, uname, aname string) (p9p.Qid, error) {
73 64abb42a 2018-04-10 noreply // TODO: AuthInit?
74 64abb42a 2018-04-10 noreply return p9p.Qid{}, nil //p9p.MessageRerror{Ename: "no auth"}
75 64abb42a 2018-04-10 noreply }
76 64abb42a 2018-04-10 noreply
77 64abb42a 2018-04-10 noreply func (sess *session) Attach(ctx context.Context, fid, afid p9p.Fid, uname, aname string) (p9p.Qid, error) {
78 64abb42a 2018-04-10 noreply if uname == "" {
79 64abb42a 2018-04-10 noreply return p9p.Qid{}, p9p.MessageRerror{Ename: "no user"}
80 64abb42a 2018-04-10 noreply }
81 64abb42a 2018-04-10 noreply
82 64abb42a 2018-04-10 noreply // TODO: AuthCheck?
83 64abb42a 2018-04-10 noreply
84 64abb42a 2018-04-10 noreply // if afid > 0 {
85 64abb42a 2018-04-10 noreply // return p9p.Qid{}, p9p.MessageRerror{Ename: "attach: no auth"}
86 64abb42a 2018-04-10 noreply // }
87 64abb42a 2018-04-10 noreply
88 64abb42a 2018-04-10 noreply if aname == "" {
89 64abb42a 2018-04-10 noreply aname = sess.rootRef.Path
90 64abb42a 2018-04-10 noreply }
91 64abb42a 2018-04-10 noreply
92 64abb42a 2018-04-10 noreply ref, err := sess.newRef(fid, aname)
93 64abb42a 2018-04-10 noreply if err != nil {
94 64abb42a 2018-04-10 noreply return p9p.Qid{}, err
95 64abb42a 2018-04-10 noreply }
96 64abb42a 2018-04-10 noreply
97 64abb42a 2018-04-10 noreply return ref.Info.Qid, nil
98 64abb42a 2018-04-10 noreply }
99 64abb42a 2018-04-10 noreply
100 64abb42a 2018-04-10 noreply func (sess *session) Clunk(ctx context.Context, fid p9p.Fid) error {
101 64abb42a 2018-04-10 noreply ref, err := sess.getRef(fid)
102 64abb42a 2018-04-10 noreply if err != nil {
103 64abb42a 2018-04-10 noreply return err
104 64abb42a 2018-04-10 noreply }
105 64abb42a 2018-04-10 noreply
106 64abb42a 2018-04-10 noreply ref.Lock()
107 64abb42a 2018-04-10 noreply defer ref.Unlock()
108 64abb42a 2018-04-10 noreply if ref.File != nil {
109 64abb42a 2018-04-10 noreply ref.File.Close()
110 64abb42a 2018-04-10 noreply }
111 64abb42a 2018-04-10 noreply
112 64abb42a 2018-04-10 noreply sess.Lock()
113 64abb42a 2018-04-10 noreply defer sess.Unlock()
114 64abb42a 2018-04-10 noreply delete(sess.refs, fid)
115 64abb42a 2018-04-10 noreply
116 64abb42a 2018-04-10 noreply return nil
117 64abb42a 2018-04-10 noreply }
118 64abb42a 2018-04-10 noreply
119 64abb42a 2018-04-10 noreply func (sess *session) Remove(ctx context.Context, fid p9p.Fid) error {
120 64abb42a 2018-04-10 noreply defer sess.Clunk(ctx, fid)
121 64abb42a 2018-04-10 noreply
122 64abb42a 2018-04-10 noreply ref, err := sess.getRef(fid)
123 64abb42a 2018-04-10 noreply if err != nil {
124 64abb42a 2018-04-10 noreply return err
125 64abb42a 2018-04-10 noreply }
126 64abb42a 2018-04-10 noreply
127 64abb42a 2018-04-10 noreply // TODO: check write perms on parent
128 64abb42a 2018-04-10 noreply
129 64abb42a 2018-04-10 noreply return os.Remove(ref.Path)
130 64abb42a 2018-04-10 noreply }
131 64abb42a 2018-04-10 noreply
132 64abb42a 2018-04-10 noreply func (sess *session) Walk(ctx context.Context, fid p9p.Fid, newfid p9p.Fid, names ...string) ([]p9p.Qid, error) {
133 64abb42a 2018-04-10 noreply var qids []p9p.Qid
134 64abb42a 2018-04-10 noreply
135 64abb42a 2018-04-10 noreply ref, err := sess.getRef(fid)
136 64abb42a 2018-04-10 noreply if err != nil {
137 64abb42a 2018-04-10 noreply return qids, err
138 64abb42a 2018-04-10 noreply }
139 64abb42a 2018-04-10 noreply
140 64abb42a 2018-04-10 noreply newref, err := sess.newRef(newfid, ref.Path)
141 64abb42a 2018-04-10 noreply if err != nil {
142 64abb42a 2018-04-10 noreply return qids, err
143 64abb42a 2018-04-10 noreply }
144 64abb42a 2018-04-10 noreply
145 64abb42a 2018-04-10 noreply path := newref.Path
146 64abb42a 2018-04-10 noreply for _, name := range names {
147 64abb42a 2018-04-10 noreply newpath := filepath.Join(path, name)
148 64abb42a 2018-04-10 noreply r := &FileRef{Path: newpath}
149 64abb42a 2018-04-10 noreply if err := r.Stat(); err != nil {
150 64abb42a 2018-04-10 noreply break
151 64abb42a 2018-04-10 noreply }
152 64abb42a 2018-04-10 noreply qids = append(qids, r.Info.Qid)
153 64abb42a 2018-04-10 noreply path = newpath
154 64abb42a 2018-04-10 noreply }
155 64abb42a 2018-04-10 noreply
156 64abb42a 2018-04-10 noreply newref.Path = path
157 64abb42a 2018-04-10 noreply return qids, nil
158 64abb42a 2018-04-10 noreply }
159 64abb42a 2018-04-10 noreply
160 64abb42a 2018-04-10 noreply func (sess *session) Read(ctx context.Context, fid p9p.Fid, p []byte, offset int64) (n int, err error) {
161 64abb42a 2018-04-10 noreply ref, err := sess.getRef(fid)
162 64abb42a 2018-04-10 noreply if err != nil {
163 64abb42a 2018-04-10 noreply return 0, err
164 64abb42a 2018-04-10 noreply }
165 64abb42a 2018-04-10 noreply
166 64abb42a 2018-04-10 noreply ref.Lock()
167 64abb42a 2018-04-10 noreply defer ref.Unlock()
168 64abb42a 2018-04-10 noreply
169 64abb42a 2018-04-10 noreply if ref.IsDir() {
170 64abb42a 2018-04-10 noreply if offset == 0 && ref.Readdir == nil {
171 64abb42a 2018-04-10 noreply files, err := ioutil.ReadDir(ref.Path)
172 64abb42a 2018-04-10 noreply if err != nil {
173 64abb42a 2018-04-10 noreply return 0, err
174 64abb42a 2018-04-10 noreply }
175 64abb42a 2018-04-10 noreply var dirs []p9p.Dir
176 64abb42a 2018-04-10 noreply for _, info := range files {
177 64abb42a 2018-04-10 noreply dirs = append(dirs, dirFromInfo(info))
178 64abb42a 2018-04-10 noreply }
179 64abb42a 2018-04-10 noreply ref.Readdir = p9p.NewFixedReaddir(p9p.NewCodec(), dirs)
180 64abb42a 2018-04-10 noreply }
181 64abb42a 2018-04-10 noreply if ref.Readdir == nil {
182 64abb42a 2018-04-10 noreply return 0, p9p.ErrBadoffset
183 64abb42a 2018-04-10 noreply }
184 64abb42a 2018-04-10 noreply return ref.Readdir.Read(ctx, p, offset)
185 64abb42a 2018-04-10 noreply }
186 64abb42a 2018-04-10 noreply
187 64abb42a 2018-04-10 noreply if ref.File == nil {
188 64abb42a 2018-04-10 noreply return 0, p9p.MessageRerror{Ename: "no file open"} //p9p.ErrClosed
189 64abb42a 2018-04-10 noreply }
190 64abb42a 2018-04-10 noreply
191 64abb42a 2018-04-10 noreply n, err = ref.File.ReadAt(p, offset)
192 64abb42a 2018-04-10 noreply if err != nil && err != io.EOF {
193 64abb42a 2018-04-10 noreply return n, err
194 64abb42a 2018-04-10 noreply }
195 64abb42a 2018-04-10 noreply return n, nil
196 64abb42a 2018-04-10 noreply }
197 64abb42a 2018-04-10 noreply
198 64abb42a 2018-04-10 noreply func (sess *session) Write(ctx context.Context, fid p9p.Fid, p []byte, offset int64) (n int, err error) {
199 64abb42a 2018-04-10 noreply ref, err := sess.getRef(fid)
200 64abb42a 2018-04-10 noreply if err != nil {
201 64abb42a 2018-04-10 noreply return 0, err
202 64abb42a 2018-04-10 noreply }
203 64abb42a 2018-04-10 noreply
204 64abb42a 2018-04-10 noreply ref.Lock()
205 64abb42a 2018-04-10 noreply defer ref.Unlock()
206 64abb42a 2018-04-10 noreply if ref.File == nil {
207 64abb42a 2018-04-10 noreply return 0, p9p.ErrClosed
208 64abb42a 2018-04-10 noreply }
209 64abb42a 2018-04-10 noreply
210 64abb42a 2018-04-10 noreply return ref.File.WriteAt(p, offset)
211 64abb42a 2018-04-10 noreply }
212 64abb42a 2018-04-10 noreply
213 64abb42a 2018-04-10 noreply func (sess *session) Open(ctx context.Context, fid p9p.Fid, mode p9p.Flag) (p9p.Qid, uint32, error) {
214 64abb42a 2018-04-10 noreply ref, err := sess.getRef(fid)
215 64abb42a 2018-04-10 noreply if err != nil {
216 64abb42a 2018-04-10 noreply return p9p.Qid{}, 0, err
217 64abb42a 2018-04-10 noreply }
218 64abb42a 2018-04-10 noreply
219 64abb42a 2018-04-10 noreply ref.Lock()
220 64abb42a 2018-04-10 noreply defer ref.Unlock()
221 64abb42a 2018-04-10 noreply f, err := os.OpenFile(ref.Path, oflags(mode), 0)
222 64abb42a 2018-04-10 noreply if err != nil {
223 64abb42a 2018-04-10 noreply return p9p.Qid{}, 0, err
224 64abb42a 2018-04-10 noreply }
225 64abb42a 2018-04-10 noreply ref.File = f
226 64abb42a 2018-04-10 noreply return ref.Info.Qid, 0, nil
227 64abb42a 2018-04-10 noreply }
228 64abb42a 2018-04-10 noreply
229 64abb42a 2018-04-10 noreply func (sess *session) Create(ctx context.Context, parent p9p.Fid, name string, perm uint32, mode p9p.Flag) (p9p.Qid, uint32, error) {
230 64abb42a 2018-04-10 noreply ref, err := sess.getRef(parent)
231 64abb42a 2018-04-10 noreply if err != nil {
232 64abb42a 2018-04-10 noreply return p9p.Qid{}, 0, err
233 64abb42a 2018-04-10 noreply }
234 64abb42a 2018-04-10 noreply
235 64abb42a 2018-04-10 noreply newpath := filepath.Join(ref.Path, name)
236 64abb42a 2018-04-10 noreply
237 64abb42a 2018-04-10 noreply var file *os.File
238 64abb42a 2018-04-10 noreply switch {
239 64abb42a 2018-04-10 noreply case perm&p9p.DMDIR != 0:
240 64abb42a 2018-04-10 noreply err = os.Mkdir(newpath, os.FileMode(perm&0777))
241 64abb42a 2018-04-10 noreply
242 64abb42a 2018-04-10 noreply case perm&p9p.DMSYMLINK != 0:
243 64abb42a 2018-04-10 noreply case perm&p9p.DMNAMEDPIPE != 0:
244 64abb42a 2018-04-10 noreply case perm&p9p.DMDEVICE != 0:
245 64abb42a 2018-04-10 noreply err = p9p.MessageRerror{Ename: "not implemented"}
246 64abb42a 2018-04-10 noreply
247 64abb42a 2018-04-10 noreply default:
248 64abb42a 2018-04-10 noreply file, err = os.OpenFile(newpath, oflags(mode)|os.O_CREATE, os.FileMode(perm&0777))
249 64abb42a 2018-04-10 noreply }
250 64abb42a 2018-04-10 noreply
251 64abb42a 2018-04-10 noreply if file == nil && err == nil {
252 64abb42a 2018-04-10 noreply file, err = os.OpenFile(newpath, oflags(mode), 0)
253 64abb42a 2018-04-10 noreply }
254 64abb42a 2018-04-10 noreply
255 64abb42a 2018-04-10 noreply if err != nil {
256 64abb42a 2018-04-10 noreply return p9p.Qid{}, 0, err
257 64abb42a 2018-04-10 noreply }
258 64abb42a 2018-04-10 noreply
259 64abb42a 2018-04-10 noreply ref.Lock()
260 64abb42a 2018-04-10 noreply defer ref.Unlock()
261 64abb42a 2018-04-10 noreply ref.Path = newpath
262 64abb42a 2018-04-10 noreply ref.File = file
263 64abb42a 2018-04-10 noreply if err := ref.statLocked(); err != nil {
264 64abb42a 2018-04-10 noreply return p9p.Qid{}, 0, err
265 64abb42a 2018-04-10 noreply }
266 64abb42a 2018-04-10 noreply return ref.Info.Qid, 0, err
267 64abb42a 2018-04-10 noreply }
268 64abb42a 2018-04-10 noreply
269 64abb42a 2018-04-10 noreply func (sess *session) Stat(ctx context.Context, fid p9p.Fid) (p9p.Dir, error) {
270 64abb42a 2018-04-10 noreply ref, err := sess.getRef(fid)
271 64abb42a 2018-04-10 noreply if err != nil {
272 64abb42a 2018-04-10 noreply return p9p.Dir{}, err
273 64abb42a 2018-04-10 noreply }
274 64abb42a 2018-04-10 noreply return ref.Info, nil
275 64abb42a 2018-04-10 noreply }
276 64abb42a 2018-04-10 noreply
277 64abb42a 2018-04-10 noreply func (sess *session) WStat(ctx context.Context, fid p9p.Fid, dir p9p.Dir) error {
278 64abb42a 2018-04-10 noreply ref, err := sess.getRef(fid)
279 64abb42a 2018-04-10 noreply if err != nil {
280 64abb42a 2018-04-10 noreply return err
281 64abb42a 2018-04-10 noreply }
282 64abb42a 2018-04-10 noreply
283 64abb42a 2018-04-10 noreply if dir.Mode != ^uint32(0) {
284 64abb42a 2018-04-10 noreply // TODO: 9P2000.u: DMSETUID DMSETGID
285 64abb42a 2018-04-10 noreply err := os.Chmod(ref.Path, os.FileMode(dir.Mode&0777))
286 64abb42a 2018-04-10 noreply if err != nil {
287 64abb42a 2018-04-10 noreply return err
288 64abb42a 2018-04-10 noreply }
289 64abb42a 2018-04-10 noreply }
290 64abb42a 2018-04-10 noreply
291 64abb42a 2018-04-10 noreply if dir.UID != "" || dir.GID != "" {
292 64abb42a 2018-04-10 noreply usr, err := user.Lookup(dir.UID)
293 64abb42a 2018-04-10 noreply if err != nil {
294 64abb42a 2018-04-10 noreply return err
295 64abb42a 2018-04-10 noreply }
296 64abb42a 2018-04-10 noreply uid, err := strconv.Atoi(usr.Uid)
297 64abb42a 2018-04-10 noreply if err != nil {
298 64abb42a 2018-04-10 noreply return err
299 64abb42a 2018-04-10 noreply }
300 64abb42a 2018-04-10 noreply grp, err := user.LookupGroup(dir.GID)
301 64abb42a 2018-04-10 noreply if err != nil {
302 64abb42a 2018-04-10 noreply return err
303 64abb42a 2018-04-10 noreply }
304 64abb42a 2018-04-10 noreply gid, err := strconv.Atoi(grp.Gid)
305 64abb42a 2018-04-10 noreply if err != nil {
306 64abb42a 2018-04-10 noreply return err
307 64abb42a 2018-04-10 noreply }
308 64abb42a 2018-04-10 noreply if err := os.Chown(ref.Path, uid, gid); err != nil {
309 64abb42a 2018-04-10 noreply return err
310 64abb42a 2018-04-10 noreply }
311 64abb42a 2018-04-10 noreply }
312 64abb42a 2018-04-10 noreply
313 64abb42a 2018-04-10 noreply if dir.Name != "" {
314 64abb42a 2018-04-10 noreply newpath := filepath.Join(filepath.Dir(ref.Path), dir.Name)
315 64abb42a 2018-04-10 noreply if err := syscall.Rename(ref.Path, newpath); err != nil {
316 64abb42a 2018-04-10 noreply return nil
317 64abb42a 2018-04-10 noreply }
318 64abb42a 2018-04-10 noreply ref.Lock()
319 64abb42a 2018-04-10 noreply defer ref.Unlock()
320 64abb42a 2018-04-10 noreply ref.Path = newpath
321 64abb42a 2018-04-10 noreply }
322 64abb42a 2018-04-10 noreply
323 64abb42a 2018-04-10 noreply if dir.Length != ^uint64(0) {
324 64abb42a 2018-04-10 noreply if err := os.Truncate(ref.Path, int64(dir.Length)); err != nil {
325 64abb42a 2018-04-10 noreply return err
326 64abb42a 2018-04-10 noreply }
327 64abb42a 2018-04-10 noreply }
328 64abb42a 2018-04-10 noreply
329 64abb42a 2018-04-10 noreply // If either mtime or atime need to be changed, then
330 64abb42a 2018-04-10 noreply // we must change both.
331 64abb42a 2018-04-10 noreply //if dir.ModTime != time.Time{} || dir.AccessTime != ^uint32(0) {
332 64abb42a 2018-04-10 noreply // mt, at := time.Unix(int64(dir.Mtime), 0), time.Unix(int64(dir.Atime), 0)
333 64abb42a 2018-04-10 noreply // if cmt, cat := (dir.Mtime == ^uint32(0)), (dir.Atime == ^uint32(0)); cmt || cat {
334 64abb42a 2018-04-10 noreply // st, e := os.Stat(fid.path)
335 64abb42a 2018-04-10 noreply // if e != nil {
336 64abb42a 2018-04-10 noreply // req.RespondError(toError(e))
337 64abb42a 2018-04-10 noreply // return
338 64abb42a 2018-04-10 noreply // }
339 64abb42a 2018-04-10 noreply // switch cmt {
340 64abb42a 2018-04-10 noreply // case true:
341 64abb42a 2018-04-10 noreply // mt = st.ModTime()
342 64abb42a 2018-04-10 noreply // default:
343 64abb42a 2018-04-10 noreply // at = atime(st.Sys().(*syscall.Stat_t))
344 64abb42a 2018-04-10 noreply // }
345 64abb42a 2018-04-10 noreply // }
346 64abb42a 2018-04-10 noreply // e := os.Chtimes(fid.path, at, mt)
347 64abb42a 2018-04-10 noreply // if e != nil {
348 64abb42a 2018-04-10 noreply // req.RespondError(toError(e))
349 64abb42a 2018-04-10 noreply // return
350 64abb42a 2018-04-10 noreply // }
351 64abb42a 2018-04-10 noreply //}
352 64abb42a 2018-04-10 noreply return nil
353 64abb42a 2018-04-10 noreply }
354 64abb42a 2018-04-10 noreply
355 64abb42a 2018-04-10 noreply func (sess *session) Version() (msize int, version string) {
356 64abb42a 2018-04-10 noreply return p9p.DefaultMSize, p9p.DefaultVersion
357 64abb42a 2018-04-10 noreply }