minikube/third_party/go9p/clnt_read.go

134 lines
2.8 KiB
Go

// Copyright 2009 The Go9p Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package go9p
import (
"io"
)
// Reads count bytes starting from offset from the file associated with the fid.
// Returns a slice with the data read, if the operation was successful, or an
// Error.
func (clnt *Clnt) Read(fid *Fid, offset uint64, count uint32) ([]byte, error) {
if count > fid.Iounit {
count = fid.Iounit
}
tc := clnt.NewFcall()
err := PackTread(tc, fid.Fid, offset, count)
if err != nil {
return nil, err
}
rc, err := clnt.Rpc(tc)
if err != nil {
return nil, err
}
return rc.Data, nil
}
// Reads up to len(buf) bytes from the File. Returns the number
// of bytes read, or an Error.
func (file *File) Read(buf []byte) (int, error) {
n, err := file.ReadAt(buf, int64(file.offset))
if err == nil {
file.offset += uint64(n)
}
return n, err
}
// Reads up to len(buf) bytes from the file starting from offset.
// Returns the number of bytes read, or an Error.
func (file *File) ReadAt(buf []byte, offset int64) (int, error) {
b, err := file.Fid.Clnt.Read(file.Fid, uint64(offset), uint32(len(buf)))
if err != nil {
return 0, err
}
if len(b) == 0 {
return 0, io.EOF
}
copy(buf, b)
return len(b), nil
}
// Reads exactly len(buf) bytes from the File starting from offset.
// Returns the number of bytes read (could be less than len(buf) if
// end-of-file is reached), or an Error.
func (file *File) Readn(buf []byte, offset uint64) (int, error) {
ret := 0
for len(buf) > 0 {
n, err := file.ReadAt(buf, int64(offset))
if err != nil {
return 0, err
}
if n == 0 {
break
}
buf = buf[n:]
offset += uint64(n)
ret += n
}
return ret, nil
}
// Reads the content of the directory associated with the File.
// Returns an array of maximum num entries (if num is 0, returns
// all entries from the directory). If the operation fails, returns
// an Error.
func (file *File) Readdir(num int) ([]*Dir, error) {
buf := make([]byte, file.Fid.Clnt.Msize-IOHDRSZ)
dirs := make([]*Dir, 32)
pos := 0
offset := file.offset
defer func() {
file.offset = offset
}()
for {
n, err := file.Read(buf)
if err != nil && err != io.EOF {
return nil, err
}
if n == 0 {
break
}
for b := buf[0:n]; len(b) > 0; {
d, _, _, perr := UnpackDir(b, file.Fid.Clnt.Dotu)
if perr != nil {
// If we have unpacked anything, it is almost certainly
// a too-short buffer. So return what we got.
if pos > 0 {
return dirs[0:pos], nil
}
return nil, perr
}
b = b[d.Size+2:]
offset += uint64(d.Size + 2)
if pos >= len(dirs) {
s := make([]*Dir, len(dirs)+32)
copy(s, dirs)
dirs = s
}
dirs[pos] = d
pos++
if num != 0 && pos >= num {
break
}
}
}
return dirs[0:pos], nil
}