Blame


1 4b33cdd0 2015-11-30 stephen.d package main
2 4b33cdd0 2015-11-30 stephen.d
3 4b33cdd0 2015-11-30 stephen.d import (
4 4b33cdd0 2015-11-30 stephen.d "bytes"
5 c55b00ed 2021-12-31 op "context"
6 4b33cdd0 2015-11-30 stephen.d "flag"
7 4b33cdd0 2015-11-30 stephen.d "fmt"
8 4b33cdd0 2015-11-30 stephen.d "io"
9 4b33cdd0 2015-11-30 stephen.d "log"
10 4b33cdd0 2015-11-30 stephen.d "net"
11 4b33cdd0 2015-11-30 stephen.d "net/http"
12 4b33cdd0 2015-11-30 stephen.d _ "net/http/pprof"
13 4b33cdd0 2015-11-30 stephen.d "os"
14 4b33cdd0 2015-11-30 stephen.d "path"
15 4b33cdd0 2015-11-30 stephen.d "strings"
16 4b33cdd0 2015-11-30 stephen.d "text/tabwriter"
17 4b33cdd0 2015-11-30 stephen.d "time"
18 4b33cdd0 2015-11-30 stephen.d
19 c55b00ed 2021-12-31 op "git.omarpolo.com/go-p9p"
20 4b33cdd0 2015-11-30 stephen.d "github.com/chzyer/readline"
21 4b33cdd0 2015-11-30 stephen.d )
22 4b33cdd0 2015-11-30 stephen.d
23 4b33cdd0 2015-11-30 stephen.d var addr string
24 4b33cdd0 2015-11-30 stephen.d
25 4b33cdd0 2015-11-30 stephen.d func init() {
26 4b33cdd0 2015-11-30 stephen.d flag.StringVar(&addr, "addr", ":5640", "addr of 9p service")
27 4b33cdd0 2015-11-30 stephen.d }
28 4b33cdd0 2015-11-30 stephen.d
29 4b33cdd0 2015-11-30 stephen.d func main() {
30 4b33cdd0 2015-11-30 stephen.d go func() {
31 4b33cdd0 2015-11-30 stephen.d log.Println(http.ListenAndServe("localhost:6060", nil))
32 4b33cdd0 2015-11-30 stephen.d }()
33 4b33cdd0 2015-11-30 stephen.d
34 4b33cdd0 2015-11-30 stephen.d ctx := context.Background()
35 4b33cdd0 2015-11-30 stephen.d log.SetFlags(0)
36 4b33cdd0 2015-11-30 stephen.d flag.Parse()
37 4b33cdd0 2015-11-30 stephen.d
38 4b33cdd0 2015-11-30 stephen.d proto := "tcp"
39 4b33cdd0 2015-11-30 stephen.d if strings.HasPrefix(addr, "unix:") {
40 4b33cdd0 2015-11-30 stephen.d proto = "unix"
41 4b33cdd0 2015-11-30 stephen.d addr = addr[5:]
42 4b33cdd0 2015-11-30 stephen.d }
43 4b33cdd0 2015-11-30 stephen.d
44 4b33cdd0 2015-11-30 stephen.d log.Println("dialing", addr)
45 4b33cdd0 2015-11-30 stephen.d conn, err := net.Dial(proto, addr)
46 4b33cdd0 2015-11-30 stephen.d if err != nil {
47 4b33cdd0 2015-11-30 stephen.d log.Fatal(err)
48 4b33cdd0 2015-11-30 stephen.d }
49 4b33cdd0 2015-11-30 stephen.d
50 4b33cdd0 2015-11-30 stephen.d csession, err := p9p.NewSession(ctx, conn)
51 4b33cdd0 2015-11-30 stephen.d if err != nil {
52 4b33cdd0 2015-11-30 stephen.d log.Fatalln(err)
53 4b33cdd0 2015-11-30 stephen.d }
54 4b33cdd0 2015-11-30 stephen.d
55 4b33cdd0 2015-11-30 stephen.d commander := &fsCommander{
56 4b33cdd0 2015-11-30 stephen.d ctx: context.Background(),
57 4b33cdd0 2015-11-30 stephen.d session: csession,
58 4b33cdd0 2015-11-30 stephen.d pwd: "/",
59 4b33cdd0 2015-11-30 stephen.d stdout: os.Stdout,
60 4b33cdd0 2015-11-30 stephen.d stderr: os.Stderr,
61 4b33cdd0 2015-11-30 stephen.d }
62 4b33cdd0 2015-11-30 stephen.d
63 4b33cdd0 2015-11-30 stephen.d completer := readline.NewPrefixCompleter(
64 4b33cdd0 2015-11-30 stephen.d readline.PcItem("ls"),
65 4b33cdd0 2015-11-30 stephen.d // readline.PcItem("find"),
66 4b33cdd0 2015-11-30 stephen.d readline.PcItem("stat"),
67 4b33cdd0 2015-11-30 stephen.d readline.PcItem("cat"),
68 4b33cdd0 2015-11-30 stephen.d readline.PcItem("cd"),
69 4b33cdd0 2015-11-30 stephen.d readline.PcItem("pwd"),
70 4b33cdd0 2015-11-30 stephen.d )
71 4b33cdd0 2015-11-30 stephen.d
72 4b33cdd0 2015-11-30 stephen.d rl, err := readline.NewEx(&readline.Config{
73 4b33cdd0 2015-11-30 stephen.d HistoryFile: ".history",
74 4b33cdd0 2015-11-30 stephen.d AutoComplete: completer,
75 4b33cdd0 2015-11-30 stephen.d })
76 4b33cdd0 2015-11-30 stephen.d if err != nil {
77 4b33cdd0 2015-11-30 stephen.d log.Fatalln(err)
78 4b33cdd0 2015-11-30 stephen.d }
79 4b33cdd0 2015-11-30 stephen.d commander.readline = rl
80 4b33cdd0 2015-11-30 stephen.d
81 4b33cdd0 2015-11-30 stephen.d msize, version := commander.session.Version()
82 4b33cdd0 2015-11-30 stephen.d if err != nil {
83 4b33cdd0 2015-11-30 stephen.d log.Fatalln(err)
84 4b33cdd0 2015-11-30 stephen.d }
85 4b33cdd0 2015-11-30 stephen.d log.Println("9p version", version, msize)
86 4b33cdd0 2015-11-30 stephen.d
87 4b33cdd0 2015-11-30 stephen.d // attach root
88 4b33cdd0 2015-11-30 stephen.d commander.nextfid = 1
89 4b33cdd0 2015-11-30 stephen.d if _, err := commander.session.Attach(commander.ctx, commander.nextfid, p9p.NOFID, "anyone", "/"); err != nil {
90 4b33cdd0 2015-11-30 stephen.d log.Fatalln(err)
91 4b33cdd0 2015-11-30 stephen.d }
92 4b33cdd0 2015-11-30 stephen.d commander.rootfid = commander.nextfid
93 4b33cdd0 2015-11-30 stephen.d commander.nextfid++
94 4b33cdd0 2015-11-30 stephen.d
95 4b33cdd0 2015-11-30 stephen.d // clone the pwd fid so we can clunk it
96 4b33cdd0 2015-11-30 stephen.d if _, err := commander.session.Walk(commander.ctx, commander.rootfid, commander.nextfid); err != nil {
97 4b33cdd0 2015-11-30 stephen.d log.Fatalln(err)
98 4b33cdd0 2015-11-30 stephen.d }
99 4b33cdd0 2015-11-30 stephen.d commander.pwdfid = commander.nextfid
100 4b33cdd0 2015-11-30 stephen.d commander.nextfid++
101 4b33cdd0 2015-11-30 stephen.d
102 4b33cdd0 2015-11-30 stephen.d for {
103 4b33cdd0 2015-11-30 stephen.d commander.readline.SetPrompt(fmt.Sprintf("%s 🐳 > ", commander.pwd))
104 4b33cdd0 2015-11-30 stephen.d
105 4b33cdd0 2015-11-30 stephen.d line, err := rl.Readline()
106 4b33cdd0 2015-11-30 stephen.d if err != nil {
107 4b33cdd0 2015-11-30 stephen.d log.Fatalln("error: ", err)
108 4b33cdd0 2015-11-30 stephen.d }
109 4b33cdd0 2015-11-30 stephen.d
110 4b33cdd0 2015-11-30 stephen.d if line == "" {
111 4b33cdd0 2015-11-30 stephen.d continue
112 4b33cdd0 2015-11-30 stephen.d }
113 4b33cdd0 2015-11-30 stephen.d
114 4b33cdd0 2015-11-30 stephen.d args := strings.Fields(line)
115 4b33cdd0 2015-11-30 stephen.d
116 4b33cdd0 2015-11-30 stephen.d name := args[0]
117 4b33cdd0 2015-11-30 stephen.d var cmd func(ctx context.Context, args ...string) error
118 4b33cdd0 2015-11-30 stephen.d
119 4b33cdd0 2015-11-30 stephen.d switch name {
120 4b33cdd0 2015-11-30 stephen.d case "ls":
121 4b33cdd0 2015-11-30 stephen.d cmd = commander.cmdls
122 4b33cdd0 2015-11-30 stephen.d case "cd":
123 4b33cdd0 2015-11-30 stephen.d cmd = commander.cmdcd
124 4b33cdd0 2015-11-30 stephen.d case "pwd":
125 4b33cdd0 2015-11-30 stephen.d cmd = commander.cmdpwd
126 4b33cdd0 2015-11-30 stephen.d case "cat":
127 4b33cdd0 2015-11-30 stephen.d cmd = commander.cmdcat
128 4b33cdd0 2015-11-30 stephen.d case "stat":
129 4b33cdd0 2015-11-30 stephen.d cmd = commander.cmdstat
130 4b33cdd0 2015-11-30 stephen.d default:
131 4b33cdd0 2015-11-30 stephen.d cmd = func(ctx context.Context, args ...string) error {
132 4b33cdd0 2015-11-30 stephen.d return fmt.Errorf("command not implemented")
133 4b33cdd0 2015-11-30 stephen.d }
134 4b33cdd0 2015-11-30 stephen.d }
135 4b33cdd0 2015-11-30 stephen.d
136 4b33cdd0 2015-11-30 stephen.d ctx, _ = context.WithTimeout(commander.ctx, 5*time.Second)
137 4b33cdd0 2015-11-30 stephen.d if err := cmd(ctx, args[1:]...); err != nil {
138 4b33cdd0 2015-11-30 stephen.d if err == p9p.ErrClosed {
139 4b33cdd0 2015-11-30 stephen.d log.Println("connection closed, shutting down")
140 4b33cdd0 2015-11-30 stephen.d return
141 4b33cdd0 2015-11-30 stephen.d }
142 4b33cdd0 2015-11-30 stephen.d
143 4b33cdd0 2015-11-30 stephen.d log.Printf("👹 %s: %v", name, err)
144 4b33cdd0 2015-11-30 stephen.d }
145 4b33cdd0 2015-11-30 stephen.d }
146 4b33cdd0 2015-11-30 stephen.d }
147 4b33cdd0 2015-11-30 stephen.d
148 4b33cdd0 2015-11-30 stephen.d type fsCommander struct {
149 4b33cdd0 2015-11-30 stephen.d ctx context.Context
150 4b33cdd0 2015-11-30 stephen.d session p9p.Session
151 4b33cdd0 2015-11-30 stephen.d pwd string
152 4b33cdd0 2015-11-30 stephen.d pwdfid p9p.Fid
153 4b33cdd0 2015-11-30 stephen.d rootfid p9p.Fid
154 4b33cdd0 2015-11-30 stephen.d
155 4b33cdd0 2015-11-30 stephen.d nextfid p9p.Fid
156 4b33cdd0 2015-11-30 stephen.d
157 4b33cdd0 2015-11-30 stephen.d readline *readline.Instance
158 4b33cdd0 2015-11-30 stephen.d stdout io.Writer
159 4b33cdd0 2015-11-30 stephen.d stderr io.Writer
160 4b33cdd0 2015-11-30 stephen.d }
161 4b33cdd0 2015-11-30 stephen.d
162 4b33cdd0 2015-11-30 stephen.d func (c *fsCommander) cmdls(ctx context.Context, args ...string) error {
163 4b33cdd0 2015-11-30 stephen.d ps := []string{c.pwd}
164 4b33cdd0 2015-11-30 stephen.d if len(args) > 0 {
165 4b33cdd0 2015-11-30 stephen.d ps = args
166 4b33cdd0 2015-11-30 stephen.d }
167 4b33cdd0 2015-11-30 stephen.d
168 4b33cdd0 2015-11-30 stephen.d wr := tabwriter.NewWriter(c.stdout, 0, 8, 8, ' ', 0)
169 4b33cdd0 2015-11-30 stephen.d
170 4b33cdd0 2015-11-30 stephen.d for _, p := range ps {
171 4b33cdd0 2015-11-30 stephen.d // create a header if have more than one path.
172 4b33cdd0 2015-11-30 stephen.d if len(ps) > 1 {
173 4b33cdd0 2015-11-30 stephen.d fmt.Fprintln(wr, p+":")
174 4b33cdd0 2015-11-30 stephen.d }
175 4b33cdd0 2015-11-30 stephen.d
176 4b33cdd0 2015-11-30 stephen.d if !path.IsAbs(p) {
177 4b33cdd0 2015-11-30 stephen.d p = path.Join(c.pwd, p)
178 4b33cdd0 2015-11-30 stephen.d }
179 4b33cdd0 2015-11-30 stephen.d
180 4b33cdd0 2015-11-30 stephen.d targetfid := c.nextfid
181 4b33cdd0 2015-11-30 stephen.d c.nextfid++
182 4b33cdd0 2015-11-30 stephen.d components := strings.Split(strings.Trim(p, "/"), "/")
183 4b33cdd0 2015-11-30 stephen.d if _, err := c.session.Walk(ctx, c.rootfid, targetfid, components...); err != nil {
184 4b33cdd0 2015-11-30 stephen.d return err
185 4b33cdd0 2015-11-30 stephen.d }
186 4b33cdd0 2015-11-30 stephen.d defer c.session.Clunk(ctx, targetfid)
187 4b33cdd0 2015-11-30 stephen.d
188 4b33cdd0 2015-11-30 stephen.d _, iounit, err := c.session.Open(ctx, targetfid, p9p.OREAD)
189 4b33cdd0 2015-11-30 stephen.d if err != nil {
190 4b33cdd0 2015-11-30 stephen.d return err
191 4b33cdd0 2015-11-30 stephen.d }
192 4b33cdd0 2015-11-30 stephen.d
193 4b33cdd0 2015-11-30 stephen.d if iounit < 1 {
194 4b33cdd0 2015-11-30 stephen.d msize, _ := c.session.Version()
195 4b33cdd0 2015-11-30 stephen.d iounit = uint32(msize - 24) // size of message max minus fcall io header (Rread)
196 4b33cdd0 2015-11-30 stephen.d }
197 4b33cdd0 2015-11-30 stephen.d
198 4b33cdd0 2015-11-30 stephen.d p := make([]byte, iounit)
199 4b33cdd0 2015-11-30 stephen.d
200 4b33cdd0 2015-11-30 stephen.d n, err := c.session.Read(ctx, targetfid, p, 0)
201 4b33cdd0 2015-11-30 stephen.d if err != nil {
202 4b33cdd0 2015-11-30 stephen.d return err
203 4b33cdd0 2015-11-30 stephen.d }
204 4b33cdd0 2015-11-30 stephen.d
205 4b33cdd0 2015-11-30 stephen.d rd := bytes.NewReader(p[:n])
206 4b33cdd0 2015-11-30 stephen.d codec := p9p.NewCodec() // TODO(stevvooe): Need way to resolve codec based on session.
207 4b33cdd0 2015-11-30 stephen.d for {
208 4b33cdd0 2015-11-30 stephen.d var d p9p.Dir
209 4b33cdd0 2015-11-30 stephen.d if err := p9p.DecodeDir(codec, rd, &d); err != nil {
210 4b33cdd0 2015-11-30 stephen.d if err == io.EOF {
211 4b33cdd0 2015-11-30 stephen.d break
212 4b33cdd0 2015-11-30 stephen.d }
213 4b33cdd0 2015-11-30 stephen.d
214 4b33cdd0 2015-11-30 stephen.d return err
215 4b33cdd0 2015-11-30 stephen.d }
216 4b33cdd0 2015-11-30 stephen.d
217 4b33cdd0 2015-11-30 stephen.d fmt.Fprintf(wr, "%v\t%v\t%v\t%s\n", os.FileMode(d.Mode), d.Length, d.ModTime, d.Name)
218 4b33cdd0 2015-11-30 stephen.d }
219 4b33cdd0 2015-11-30 stephen.d
220 4b33cdd0 2015-11-30 stephen.d if len(ps) > 1 {
221 4b33cdd0 2015-11-30 stephen.d fmt.Fprintln(wr, "")
222 4b33cdd0 2015-11-30 stephen.d }
223 4b33cdd0 2015-11-30 stephen.d }
224 4b33cdd0 2015-11-30 stephen.d
225 4b33cdd0 2015-11-30 stephen.d // all output is dumped only after success.
226 4b33cdd0 2015-11-30 stephen.d return wr.Flush()
227 4b33cdd0 2015-11-30 stephen.d }
228 4b33cdd0 2015-11-30 stephen.d
229 4b33cdd0 2015-11-30 stephen.d func (c *fsCommander) cmdcd(ctx context.Context, args ...string) error {
230 4b33cdd0 2015-11-30 stephen.d var p string
231 4b33cdd0 2015-11-30 stephen.d switch len(args) {
232 4b33cdd0 2015-11-30 stephen.d case 0:
233 4b33cdd0 2015-11-30 stephen.d p = "/"
234 4b33cdd0 2015-11-30 stephen.d case 1:
235 4b33cdd0 2015-11-30 stephen.d p = args[0]
236 4b33cdd0 2015-11-30 stephen.d default:
237 4b33cdd0 2015-11-30 stephen.d return fmt.Errorf("cd: invalid args: %v", args)
238 4b33cdd0 2015-11-30 stephen.d }
239 4b33cdd0 2015-11-30 stephen.d
240 4b33cdd0 2015-11-30 stephen.d if !path.IsAbs(p) {
241 4b33cdd0 2015-11-30 stephen.d p = path.Join(c.pwd, p)
242 4b33cdd0 2015-11-30 stephen.d }
243 4b33cdd0 2015-11-30 stephen.d
244 4b33cdd0 2015-11-30 stephen.d targetfid := c.nextfid
245 4b33cdd0 2015-11-30 stephen.d c.nextfid++
246 4b33cdd0 2015-11-30 stephen.d components := strings.Split(strings.TrimSpace(strings.Trim(p, "/")), "/")
247 4b33cdd0 2015-11-30 stephen.d if _, err := c.session.Walk(c.ctx, c.rootfid, targetfid, components...); err != nil {
248 4b33cdd0 2015-11-30 stephen.d return err
249 4b33cdd0 2015-11-30 stephen.d }
250 4b33cdd0 2015-11-30 stephen.d defer c.session.Clunk(c.ctx, c.pwdfid)
251 4b33cdd0 2015-11-30 stephen.d
252 4b33cdd0 2015-11-30 stephen.d log.Println("cd", p, targetfid)
253 4b33cdd0 2015-11-30 stephen.d c.pwd = p
254 4b33cdd0 2015-11-30 stephen.d c.pwdfid = targetfid
255 4b33cdd0 2015-11-30 stephen.d
256 4b33cdd0 2015-11-30 stephen.d return nil
257 4b33cdd0 2015-11-30 stephen.d }
258 4b33cdd0 2015-11-30 stephen.d
259 4b33cdd0 2015-11-30 stephen.d func (c *fsCommander) cmdstat(ctx context.Context, args ...string) error {
260 4b33cdd0 2015-11-30 stephen.d ps := []string{c.pwd}
261 4b33cdd0 2015-11-30 stephen.d if len(args) > 0 {
262 4b33cdd0 2015-11-30 stephen.d ps = args
263 4b33cdd0 2015-11-30 stephen.d }
264 4b33cdd0 2015-11-30 stephen.d
265 4b33cdd0 2015-11-30 stephen.d wr := tabwriter.NewWriter(c.stdout, 0, 8, 8, ' ', 0)
266 4b33cdd0 2015-11-30 stephen.d
267 4b33cdd0 2015-11-30 stephen.d for _, p := range ps {
268 4b33cdd0 2015-11-30 stephen.d targetfid := c.nextfid
269 4b33cdd0 2015-11-30 stephen.d c.nextfid++
270 4b33cdd0 2015-11-30 stephen.d components := strings.Split(strings.Trim(p, "/"), "/")
271 4b33cdd0 2015-11-30 stephen.d if _, err := c.session.Walk(ctx, c.rootfid, targetfid, components...); err != nil {
272 4b33cdd0 2015-11-30 stephen.d return err
273 4b33cdd0 2015-11-30 stephen.d }
274 4b33cdd0 2015-11-30 stephen.d defer c.session.Clunk(ctx, targetfid)
275 4b33cdd0 2015-11-30 stephen.d
276 4b33cdd0 2015-11-30 stephen.d d, err := c.session.Stat(ctx, targetfid)
277 4b33cdd0 2015-11-30 stephen.d if err != nil {
278 4b33cdd0 2015-11-30 stephen.d return err
279 4b33cdd0 2015-11-30 stephen.d }
280 4b33cdd0 2015-11-30 stephen.d
281 4b33cdd0 2015-11-30 stephen.d fmt.Fprintf(wr, "%v\t%v\t%v\t%s\n", os.FileMode(d.Mode), d.Length, d.ModTime, d.Name)
282 4b33cdd0 2015-11-30 stephen.d }
283 4b33cdd0 2015-11-30 stephen.d
284 4b33cdd0 2015-11-30 stephen.d return wr.Flush()
285 4b33cdd0 2015-11-30 stephen.d }
286 4b33cdd0 2015-11-30 stephen.d
287 4b33cdd0 2015-11-30 stephen.d func (c *fsCommander) cmdpwd(ctx context.Context, args ...string) error {
288 4b33cdd0 2015-11-30 stephen.d if len(args) != 0 {
289 4b33cdd0 2015-11-30 stephen.d return fmt.Errorf("pwd takes no arguments")
290 4b33cdd0 2015-11-30 stephen.d }
291 4b33cdd0 2015-11-30 stephen.d
292 4b33cdd0 2015-11-30 stephen.d fmt.Println(c.pwd)
293 4b33cdd0 2015-11-30 stephen.d return nil
294 4b33cdd0 2015-11-30 stephen.d }
295 4b33cdd0 2015-11-30 stephen.d
296 4b33cdd0 2015-11-30 stephen.d func (c *fsCommander) cmdcat(ctx context.Context, args ...string) error {
297 4b33cdd0 2015-11-30 stephen.d var p string
298 4b33cdd0 2015-11-30 stephen.d switch len(args) {
299 4b33cdd0 2015-11-30 stephen.d case 0:
300 4b33cdd0 2015-11-30 stephen.d p = "/"
301 4b33cdd0 2015-11-30 stephen.d case 1:
302 4b33cdd0 2015-11-30 stephen.d p = args[0]
303 4b33cdd0 2015-11-30 stephen.d default:
304 4b33cdd0 2015-11-30 stephen.d return fmt.Errorf("cd: invalid args: %v", args)
305 4b33cdd0 2015-11-30 stephen.d }
306 4b33cdd0 2015-11-30 stephen.d
307 4b33cdd0 2015-11-30 stephen.d if !path.IsAbs(p) {
308 4b33cdd0 2015-11-30 stephen.d p = path.Join(c.pwd, p)
309 4b33cdd0 2015-11-30 stephen.d }
310 4b33cdd0 2015-11-30 stephen.d
311 4b33cdd0 2015-11-30 stephen.d targetfid := c.nextfid
312 4b33cdd0 2015-11-30 stephen.d c.nextfid++
313 4b33cdd0 2015-11-30 stephen.d components := strings.Split(strings.TrimSpace(strings.Trim(p, "/")), "/")
314 4b33cdd0 2015-11-30 stephen.d if _, err := c.session.Walk(ctx, c.rootfid, targetfid, components...); err != nil {
315 4b33cdd0 2015-11-30 stephen.d return err
316 4b33cdd0 2015-11-30 stephen.d }
317 4b33cdd0 2015-11-30 stephen.d defer c.session.Clunk(ctx, c.pwdfid)
318 4b33cdd0 2015-11-30 stephen.d
319 4b33cdd0 2015-11-30 stephen.d _, iounit, err := c.session.Open(ctx, targetfid, p9p.OREAD)
320 4b33cdd0 2015-11-30 stephen.d if err != nil {
321 4b33cdd0 2015-11-30 stephen.d return err
322 4b33cdd0 2015-11-30 stephen.d }
323 4b33cdd0 2015-11-30 stephen.d
324 4b33cdd0 2015-11-30 stephen.d if iounit < 1 {
325 4b33cdd0 2015-11-30 stephen.d msize, _ := c.session.Version()
326 4b33cdd0 2015-11-30 stephen.d iounit = uint32(msize - 24) // size of message max minus fcall io header (Rread)
327 4b33cdd0 2015-11-30 stephen.d }
328 4b33cdd0 2015-11-30 stephen.d
329 4b33cdd0 2015-11-30 stephen.d b := make([]byte, iounit)
330 4b33cdd0 2015-11-30 stephen.d
331 4b33cdd0 2015-11-30 stephen.d n, err := c.session.Read(ctx, targetfid, b, 0)
332 4b33cdd0 2015-11-30 stephen.d if err != nil {
333 4b33cdd0 2015-11-30 stephen.d return err
334 4b33cdd0 2015-11-30 stephen.d }
335 4b33cdd0 2015-11-30 stephen.d
336 4b33cdd0 2015-11-30 stephen.d if _, err := os.Stdout.Write(b[:n]); err != nil {
337 4b33cdd0 2015-11-30 stephen.d return err
338 4b33cdd0 2015-11-30 stephen.d }
339 4b33cdd0 2015-11-30 stephen.d
340 4b33cdd0 2015-11-30 stephen.d os.Stdout.Write([]byte("\n"))
341 4b33cdd0 2015-11-30 stephen.d
342 4b33cdd0 2015-11-30 stephen.d return nil
343 4b33cdd0 2015-11-30 stephen.d }