nilium / go9p

Automatically exported from code.google.com/p/go9p [note: not the maintainer, just cloned for posterity]
Other
0 stars 0 forks source link

no seek method on clnt.File #33

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
clnt.File should implement io.Seeker to keep up the 'file' illusion.

Original issue reported on code.google.com by mischief@offblast.org on 30 Aug 2014 at 11:12

GoogleCodeExporter commented 9 years ago
i'm mimicking the behavior of the plan 9 kernel here, see 
/sys/src/9/port/sysfile.c:/^sseek

patch follows. Seek is what fixes this patch. NewFile and Fid.File are some 
convenience functions i believe should be committed too.
==============

diff -r 630c71178faf p/clnt/clnt.go
--- a/p/clnt/clnt.go    Wed May 14 13:19:14 2014 -0600
+++ b/p/clnt/clnt.go    Mon Sep 01 09:06:07 2014 +0000
@@ -74,6 +74,73 @@
    offset uint64
 }

+func NewFile(f *Fid, offset uint64) *File {
+   return &File{f, offset}
+}
+
+func (f *File) Fid() *Fid {
+   return f.fid
+}
+
+var Eisdir = &p.Error{"file is a directory", p.EIO}
+var Enegoff = &p.Error{"negative i/o offset", p.EIO}
+
+// Seek sets the offset for the next Read or Write to offset,
+// interpreted according to whence: 0 means relative to the origin of
+// the file, 1 means relative to the current offset, and 2 means
+// relative to the end.  Seek returns the new offset and an error, if
+// any.
+//
+// Seeking to a negative offset is an error, and results in Enegoff.
+// Seeking to 0 in a directory is only valid if whence is 0. Seek returns
+// Eisdir otherwise.
+func (f *File) Seek(offset int64, whence int) (int64, error) {
+   var off int64
+
+   switch whence {
+   case 0:
+       // origin
+       off = offset
+       if f.fid.Qid.Type&p.QTDIR > 0 && off != 0 {
+           return 0, Eisdir
+       }
+       if off < 0 {
+           return 0, Enegoff
+       }
+       f.offset = uint64(off)
+   case 1:
+       // current
+       if f.fid.Qid.Type&p.QTDIR > 0 {
+           return 0, Eisdir
+       }
+       off = offset + int64(f.offset)
+       if off < 0 {
+           return 0, Enegoff
+       }
+       f.offset = uint64(off)
+   case 2:
+       // end
+       if f.fid.Qid.Type&p.QTDIR > 0 {
+           return 0, Eisdir
+       }
+
+       dir, err := f.fid.Clnt.Stat(f.fid)
+       if err != nil {
+           return 0, &p.Error{"stat error in seek: " + err.Error(), p.EIO}
+       }
+
+       off = int64(dir.Length) + offset
+       if off < 0 {
+           return 0, Enegoff
+       }
+       f.offset = uint64(off)
+   default:
+       return 0, &p.Error{"bad whence in seek", p.EIO}
+   }
+
+   return off, nil
+}
+
 type pool struct {
    sync.Mutex
    need  int

Original comment by mischief@offblast.org on 1 Sep 2014 at 9:06

GoogleCodeExporter commented 9 years ago

Original comment by lion...@gmail.com on 5 Dec 2014 at 6:09