Blame


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