| |
| |
| |
|
|
| |
|
|
| package syscall |
|
|
| import ( |
| "errors" |
| "internal/byteorder" |
| ) |
|
|
| var ( |
| ErrShortStat = errors.New("stat buffer too short") |
| ErrBadStat = errors.New("malformed stat buffer") |
| ErrBadName = errors.New("bad character in file name") |
| ) |
|
|
| |
| type Qid struct { |
| Path uint64 |
| Vers uint32 |
| Type uint8 |
| } |
|
|
| |
| type Dir struct { |
| |
| Type uint16 |
| Dev uint32 |
|
|
| |
| Qid Qid |
| Mode uint32 |
| Atime uint32 |
| Mtime uint32 |
| Length int64 |
| Name string |
| Uid string |
| Gid string |
| Muid string |
| } |
|
|
| var nullDir = Dir{ |
| Type: ^uint16(0), |
| Dev: ^uint32(0), |
| Qid: Qid{ |
| Path: ^uint64(0), |
| Vers: ^uint32(0), |
| Type: ^uint8(0), |
| }, |
| Mode: ^uint32(0), |
| Atime: ^uint32(0), |
| Mtime: ^uint32(0), |
| Length: ^int64(0), |
| } |
|
|
| |
| |
| func (d *Dir) Null() { *d = nullDir } |
|
|
| |
| |
| |
| func (d *Dir) Marshal(b []byte) (n int, err error) { |
| n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid) |
| if n > len(b) { |
| return n, ErrShortStat |
| } |
|
|
| for _, c := range d.Name { |
| if c == '/' { |
| return n, ErrBadName |
| } |
| } |
|
|
| b = pbit16(b, uint16(n)-2) |
| b = pbit16(b, d.Type) |
| b = pbit32(b, d.Dev) |
| b = pbit8(b, d.Qid.Type) |
| b = pbit32(b, d.Qid.Vers) |
| b = pbit64(b, d.Qid.Path) |
| b = pbit32(b, d.Mode) |
| b = pbit32(b, d.Atime) |
| b = pbit32(b, d.Mtime) |
| b = pbit64(b, uint64(d.Length)) |
| b = pstring(b, d.Name) |
| b = pstring(b, d.Uid) |
| b = pstring(b, d.Gid) |
| b = pstring(b, d.Muid) |
|
|
| return n, nil |
| } |
|
|
| |
| |
| |
| |
| |
| func UnmarshalDir(b []byte) (*Dir, error) { |
| if len(b) < STATFIXLEN { |
| return nil, ErrShortStat |
| } |
| size, buf := gbit16(b) |
| if len(b) != int(size)+2 { |
| return nil, ErrBadStat |
| } |
| b = buf |
|
|
| var d Dir |
| d.Type, b = gbit16(b) |
| d.Dev, b = gbit32(b) |
| d.Qid.Type, b = gbit8(b) |
| d.Qid.Vers, b = gbit32(b) |
| d.Qid.Path, b = gbit64(b) |
| d.Mode, b = gbit32(b) |
| d.Atime, b = gbit32(b) |
| d.Mtime, b = gbit32(b) |
|
|
| n, b := gbit64(b) |
| d.Length = int64(n) |
|
|
| var ok bool |
| if d.Name, b, ok = gstring(b); !ok { |
| return nil, ErrBadStat |
| } |
| if d.Uid, b, ok = gstring(b); !ok { |
| return nil, ErrBadStat |
| } |
| if d.Gid, b, ok = gstring(b); !ok { |
| return nil, ErrBadStat |
| } |
| if d.Muid, b, ok = gstring(b); !ok { |
| return nil, ErrBadStat |
| } |
|
|
| return &d, nil |
| } |
|
|
| |
| func pbit8(b []byte, v uint8) []byte { |
| b[0] = byte(v) |
| return b[1:] |
| } |
|
|
| |
| func pbit16(b []byte, v uint16) []byte { |
| byteorder.LEPutUint16(b, v) |
| return b[2:] |
| } |
|
|
| |
| func pbit32(b []byte, v uint32) []byte { |
| byteorder.LEPutUint32(b, v) |
| return b[4:] |
| } |
|
|
| |
| func pbit64(b []byte, v uint64) []byte { |
| byteorder.LEPutUint64(b, v) |
| return b[8:] |
| } |
|
|
| |
| |
| func pstring(b []byte, s string) []byte { |
| b = pbit16(b, uint16(len(s))) |
| n := copy(b, s) |
| return b[n:] |
| } |
|
|
| |
| func gbit8(b []byte) (uint8, []byte) { |
| return uint8(b[0]), b[1:] |
| } |
|
|
| |
| |
| |
| func gbit16(b []byte) (uint16, []byte) { |
| return byteorder.LEUint16(b), b[2:] |
| } |
|
|
| |
| func gbit32(b []byte) (uint32, []byte) { |
| return byteorder.LEUint32(b), b[4:] |
| } |
|
|
| |
| func gbit64(b []byte) (uint64, []byte) { |
| return byteorder.LEUint64(b), b[8:] |
| } |
|
|
| |
| |
| |
| func gstring(b []byte) (string, []byte, bool) { |
| n, b := gbit16(b) |
| if int(n) > len(b) { |
| return "", b, false |
| } |
| return string(b[:n]), b[n:], true |
| } |
|
|