func (c *clientFile) GetAttr(req AttrMask) (QID, AttrMask, Attr, error) {
	if atomic.LoadUint32(&c.closed) != 0 {
		return QID{}, AttrMask{}, Attr{}, linux.EBADF
	}
	rgetattr := rgetattr{}
	if err := c.client.sendRecv(&tgetattr{fid: c.fid, AttrMask: req}, &rgetattr); err != nil {
		return QID{}, AttrMask{}, Attr{}, err
	}
	return rgetattr.QID, rgetattr.Valid, rgetattr.Attr, nil
}
GetAttr implements File.GetAttr.
package p9
import (
	"fmt"
	"io"
	"log"
	"runtime"
	"sync/atomic"
	"github.com/hugelgupf/p9/internal/linux"
)
func (c *Client) Attach(name string) (File, error) {
	id, ok := c.fidPool.Get()
	if !ok {
		return nil, ErrOutOfFIDs
	}
	rattach := rattach{}
	if err := c.sendRecv(&tattach{fid: fid(id), Auth: tauth{AttachName: name, Authenticationfid: noFID, UID: NoUID}}, &rattach); err != nil {
		c.fidPool.Put(id)
		return nil, err
	}
	return c.newFile(fid(id)), nil
}
func (c *Client) newFile(fid fid) *clientFile {
	cf := &clientFile{
		client: c,
		fid:    fid,
	}
	runtime.SetFinalizer(cf, (*clientFile).Close)
	return cf
}
type clientFile struct {
	client *Client
	fid fid
	closed uint32
}
func (c *clientFile) Walk(names []string) ([]QID, File, error) {
	if atomic.LoadUint32(&c.closed) != 0 {
		return nil, nil, linux.EBADF
	}
	id, ok := c.client.fidPool.Get()
	if !ok {
		return nil, nil, ErrOutOfFIDs
	}
	rwalk := rwalk{}
	if err := c.client.sendRecv(&twalk{fid: c.fid, newFID: fid(id), Names: names}, &rwalk); err != nil {
		c.client.fidPool.Put(id)
		return nil, nil, err
	}
	return rwalk.QIDs, c.client.newFile(fid(id)), nil
}
func (c *clientFile) WalkGetAttr(components []string) ([]QID, File, AttrMask, Attr, error) {
	if atomic.LoadUint32(&c.closed) != 0 {
		return nil, nil, AttrMask{}, Attr{}, linux.EBADF
	}
	if !versionSupportsTwalkgetattr(c.client.version) {
		qids, file, err := c.Walk(components)
		if err != nil {
			return nil, nil, AttrMask{}, Attr{}, err
		}
		_, valid, attr, err := file.GetAttr(AttrMaskAll)
		if err != nil {
			file.Close()
			return nil, nil, AttrMask{}, Attr{}, err
		}
		return qids, file, valid, attr, nil
	}
	id, ok := c.client.fidPool.Get()
	if !ok {
		return nil, nil, AttrMask{}, Attr{}, ErrOutOfFIDs
	}
	rwalkgetattr := rwalkgetattr{}
	if err := c.client.sendRecv(&twalkgetattr{fid: c.fid, newFID: fid(id), Names: components}, &rwalkgetattr); err != nil {
		c.client.fidPool.Put(id)
		return nil, nil, AttrMask{}, Attr{}, err
	}
	return rwalkgetattr.QIDs, c.client.newFile(fid(id)), rwalkgetattr.Valid, rwalkgetattr.Attr, nil
}
func (c *clientFile) StatFS() (FSStat, error) {
	if atomic.LoadUint32(&c.closed) != 0 {
		return FSStat{}, linux.EBADF
	}
	rstatfs := rstatfs{}
	if err := c.client.sendRecv(&tstatfs{fid: c.fid}, &rstatfs); err != nil {
		return FSStat{}, err
	}
	return rstatfs.FSStat, nil
}
func (c *clientFile) FSync() error {
	if atomic.LoadUint32(&c.closed) != 0 {
		return linux.EBADF
	}
	return c.client.sendRecv(&tfsync{fid: c.fid}, &rfsync{})
}