Skip to content

Commit fa448df

Browse files
committed
rename.
Cleaned up errors / writing of 'wcc' and 'postOpAttr'
1 parent 767fb8e commit fa448df

22 files changed

+343
-162
lines changed

conn.go

+10-11
Original file line numberDiff line numberDiff line change
@@ -158,16 +158,13 @@ func (c *conn) err(ctx context.Context, w *response, err error) error {
158158
return nil
159159
}
160160

161-
var rpcErr RPCError
162-
if errors.As(err, &rpcErr) {
163-
if writeErr := w.writeHeader(rpcErr.Code()); writeErr != nil {
164-
return writeErr
165-
}
166-
167-
body, _ := rpcErr.MarshalBinary()
168-
return w.Write(body)
161+
rpcErr := w.errorFmt(err)
162+
if writeErr := w.writeHeader(rpcErr.Code()); writeErr != nil {
163+
return writeErr
169164
}
170-
return w.writeHeader(ResponseCodeSystemErr)
165+
166+
body, _ := rpcErr.MarshalBinary()
167+
return w.Write(body)
171168
}
172169

173170
type request struct {
@@ -190,6 +187,7 @@ type response struct {
190187
writer *bytes.Buffer
191188
responded bool
192189
err error
190+
errorFmt func(error) RPCError
193191
req *request
194192
}
195193

@@ -321,8 +319,9 @@ func (c *conn) readRequestHeader(ctx context.Context, reader *bufio.Reader) (w *
321319
}
322320

323321
w = &response{
324-
conn: c,
325-
req: &req,
322+
conn: c,
323+
req: &req,
324+
errorFmt: basicErrorFormatter,
326325
// TODO: use a pool for these.
327326
writer: bytes.NewBuffer([]byte{}),
328327
}

errors.go

+35-37
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package nfs
33
import (
44
"encoding"
55
"encoding/binary"
6+
"errors"
67
"fmt"
78
)
89

@@ -152,6 +153,17 @@ func (r *ResponseCodeSystemError) MarshalBinary() (data []byte, err error) {
152153
return []byte{}, nil
153154
}
154155

156+
// basicErrorFormatter is the default error handler for response errors.
157+
// if the error is already formatted, it is directly written. Otherwise,
158+
// ResponseCodeSystemError is sent to the client.
159+
func basicErrorFormatter(err error) RPCError {
160+
var rpcErr RPCError
161+
if errors.As(err, &rpcErr) {
162+
return rpcErr
163+
}
164+
return &ResponseCodeSystemError{}
165+
}
166+
155167
// NFSStatusError represents an error at the NFS level.
156168
type NFSStatusError struct {
157169
NFSStatus
@@ -174,46 +186,32 @@ func (s *NFSStatusError) MarshalBinary() (data []byte, err error) {
174186
return resp[:], nil
175187
}
176188

177-
// NFSStatusErrorWithOpAttr is an NFS error where a 'post_op_attr' is expected
178-
type NFSStatusErrorWithOpAttr struct {
179-
NFSStatus
180-
}
181-
182-
// Error is The wrapped error
183-
func (s *NFSStatusErrorWithOpAttr) Error() string {
184-
return s.NFSStatus.String()
185-
}
186-
187-
// Code for NFS issues are successful RPC responses
188-
func (s *NFSStatusErrorWithOpAttr) Code() ResponseCode {
189-
return ResponseCodeSuccess
189+
// StatusErrorWithBody is an NFS error with a payload.
190+
type StatusErrorWithBody struct {
191+
NFSStatusError
192+
Body []byte
190193
}
191194

192-
// MarshalBinary - The binary form of the code.
193-
func (s *NFSStatusErrorWithOpAttr) MarshalBinary() (data []byte, err error) {
194-
var resp [8]byte
195-
binary.BigEndian.PutUint32(resp[0:4], uint32(s.NFSStatus))
196-
return resp[:], nil
195+
// MarshalBinary provides the wire format of the error response
196+
func (s *StatusErrorWithBody) MarshalBinary() (data []byte, err error) {
197+
head, err := s.NFSStatusError.MarshalBinary()
198+
return append(head, s.Body...), err
197199
}
198200

199-
// NFSStatusErrorWithWccData is an NFS error where a 'wcc_data' is expected
200-
type NFSStatusErrorWithWccData struct {
201-
NFSStatus
202-
}
203-
204-
// Error is The wrapped error
205-
func (s *NFSStatusErrorWithWccData) Error() string {
206-
return s.NFSStatus.String()
207-
}
208-
209-
// Code for NFS issues are successful RPC responses
210-
func (s *NFSStatusErrorWithWccData) Code() ResponseCode {
211-
return ResponseCodeSuccess
201+
// errFormatterWithBody appends a provided body to errors
202+
func errFormatterWithBody(body []byte) func(err error) RPCError {
203+
return func(err error) RPCError {
204+
var nfsErr NFSStatusError
205+
if errors.As(err, &nfsErr) {
206+
return &StatusErrorWithBody{nfsErr, body[:]}
207+
}
208+
return &ResponseCodeSystemError{}
209+
}
212210
}
213211

214-
// MarshalBinary - The binary form of the code.
215-
func (s *NFSStatusErrorWithWccData) MarshalBinary() (data []byte, err error) {
216-
var resp [12]byte
217-
binary.BigEndian.PutUint32(resp[0:4], uint32(s.NFSStatus))
218-
return resp[:], nil
219-
}
212+
var (
213+
opAttrErrorBody = [4]byte{}
214+
opAttrErrorFormatter = errFormatterWithBody(opAttrErrorBody[:])
215+
wccDataErrorBody = [8]byte{}
216+
wccDataErrorFormatter = errFormatterWithBody(wccDataErrorBody[:])
217+
)

file.go

+32-8
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (f FileAttribute) AsCache() *FileCacheAttribute {
8484
}
8585

8686
// ToFileAttribute creates an NFS fattr3 struct from an OS.FileInfo
87-
func ToFileAttribute(info os.FileInfo) FileAttribute {
87+
func ToFileAttribute(info os.FileInfo) *FileAttribute {
8888
f := FileAttribute{}
8989

9090
m := info.Mode()
@@ -122,19 +122,43 @@ func ToFileAttribute(info os.FileInfo) FileAttribute {
122122
f.Atime = ToNFSTime(info.ModTime())
123123
f.Mtime = f.Atime
124124
f.Ctime = f.Atime
125-
return f
125+
return &f
126126
}
127127

128-
// WritePostOpAttrs writes the `post_op_attr` representation of a files attributes
129-
func WritePostOpAttrs(writer io.Writer, fs billy.Filesystem, path []string) {
128+
// tryStat attempts to create a FileAttribute from a path.
129+
func tryStat(fs billy.Filesystem, path []string) *FileAttribute {
130130
attrs, err := fs.Stat(fs.Join(path...))
131131
if err != nil || attrs == nil {
132-
log.Printf("err writing attrs for %s: %v", fs.Join(path...), err)
132+
log.Printf("err loading attrs for %s: %v", fs.Join(path...), err)
133+
return nil
134+
}
135+
return ToFileAttribute(attrs)
136+
}
137+
138+
// WriteWcc writes the `wcc_data` representation of an object.
139+
func WriteWcc(writer io.Writer, pre *FileCacheAttribute, post *FileAttribute) {
140+
if pre == nil {
141+
_ = xdr.Write(writer, uint32(0))
142+
} else {
143+
_ = xdr.Write(writer, uint32(1))
144+
_ = xdr.Write(writer, *pre)
145+
}
146+
if post == nil {
133147
_ = xdr.Write(writer, uint32(0))
134-
return
148+
} else {
149+
_ = xdr.Write(writer, uint32(1))
150+
_ = xdr.Write(writer, *post)
151+
}
152+
}
153+
154+
// WritePostOpAttrs writes the `post_op_attr` representation of a files attributes
155+
func WritePostOpAttrs(writer io.Writer, post *FileAttribute) {
156+
if post == nil {
157+
_ = xdr.Write(writer, uint32(0))
158+
} else {
159+
_ = xdr.Write(writer, uint32(1))
160+
_ = xdr.Write(writer, *post)
135161
}
136-
_ = xdr.Write(writer, uint32(1))
137-
_ = xdr.Write(writer, ToFileAttribute(attrs))
138162
}
139163

140164
// SetFileAttributes represents a command to update some metadata

nfs.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ func init() {
2121
RegisterMessageHandler(nfsServiceID, uint32(NFSProcedureMkDir), onMkdir) // 9
2222
RegisterMessageHandler(nfsServiceID, uint32(NFSProcedureSymlink), onSymlink) // 10
2323
RegisterMessageHandler(nfsServiceID, uint32(NFSProcedureMkNod), onMknod) // 11
24-
// Remove // 12
25-
// Rmdir // 13
26-
// Rename // 14
24+
RegisterMessageHandler(nfsServiceID, uint32(NFSProcedureRemove), onRemove) // 12
25+
RegisterMessageHandler(nfsServiceID, uint32(NFSProcedureRmDir), onRmDir) // 13
26+
RegisterMessageHandler(nfsServiceID, uint32(NFSProcedureRename), onRename) // 14
2727
// Link // 15
2828
// ReadDir // 16
2929
RegisterMessageHandler(nfsServiceID, uint32(NFSProcedureReadDirPlus), onReadDirPlus) // 17

nfs_onaccess.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func onAccess(ctx context.Context, w *response, userHandle Handler) error {
2828
if err := xdr.Write(writer, uint32(NFSStatusOk)); err != nil {
2929
return err
3030
}
31-
WritePostOpAttrs(writer, fs, path)
31+
WritePostOpAttrs(writer, tryStat(fs, path))
3232

3333
if !billy.CapabilityCheck(fs, billy.WriteCapability) {
3434
mask = mask & (1 | 2 | 0x20)

nfs_oncommit.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
// onCommit - note this is a no-op, as we always push writes to the backing store.
1212
func onCommit(ctx context.Context, w *response, userHandle Handler) error {
13+
w.errorFmt = wccDataErrorFormatter
1314
handle, err := xdr.ReadOpaque(w.req.Body)
1415
if err != nil {
1516
// TODO: wrap
@@ -19,10 +20,10 @@ func onCommit(ctx context.Context, w *response, userHandle Handler) error {
1920

2021
fs, path, err := userHandle.FromHandle(handle)
2122
if err != nil {
22-
return &NFSStatusErrorWithWccData{NFSStatusStale}
23+
return &NFSStatusError{NFSStatusStale}
2324
}
2425
if !billy.CapabilityCheck(fs, billy.WriteCapability) {
25-
return &NFSStatusErrorWithWccData{NFSStatusServerFault}
26+
return &NFSStatusError{NFSStatusServerFault}
2627
}
2728

2829
writer := bytes.NewBuffer([]byte{})
@@ -34,7 +35,7 @@ func onCommit(ctx context.Context, w *response, userHandle Handler) error {
3435
if err := xdr.Write(writer, uint32(0)); err != nil {
3536
return err
3637
}
37-
WritePostOpAttrs(writer, fs, path)
38+
WritePostOpAttrs(writer, tryStat(fs, path))
3839
// write the 8 bytes of write verification.
3940
if err := xdr.Write(writer, w.Server.ID); err != nil {
4041
return err

nfs_oncreate.go

+15-14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const (
1515
)
1616

1717
func onCreate(ctx context.Context, w *response, userHandle Handler) error {
18+
w.errorFmt = wccDataErrorFormatter
1819
obj := DirOpArg{}
1920
err := xdr.Read(w.req.Body, &obj)
2021
if err != nil {
@@ -39,52 +40,52 @@ func onCreate(ctx context.Context, w *response, userHandle Handler) error {
3940
return err
4041
}
4142
// TODO: support 'exclusive' mode.
42-
return &NFSStatusErrorWithWccData{NFSStatusNotSupp}
43+
return &NFSStatusError{NFSStatusNotSupp}
4344
} else {
4445
// invalid
45-
return &NFSStatusErrorWithWccData{NFSStatusNotSupp}
46+
return &NFSStatusError{NFSStatusNotSupp}
4647
}
4748

4849
fs, path, err := userHandle.FromHandle(obj.Handle)
4950
if err != nil {
50-
return &NFSStatusErrorWithWccData{NFSStatusStale}
51+
return &NFSStatusError{NFSStatusStale}
5152
}
5253
if !billy.CapabilityCheck(fs, billy.WriteCapability) {
53-
return &NFSStatusErrorWithWccData{NFSStatusROFS}
54+
return &NFSStatusError{NFSStatusROFS}
5455
}
5556

5657
if len(string(obj.Filename)) > PathNameMax {
57-
return &NFSStatusErrorWithWccData{NFSStatusNameTooLong}
58+
return &NFSStatusError{NFSStatusNameTooLong}
5859
}
5960

6061
newFilePath := fs.Join(append(path, string(obj.Filename))...)
6162
if s, err := fs.Stat(newFilePath); err == nil {
6263
if s.IsDir() {
63-
return &NFSStatusErrorWithWccData{NFSStatusExist}
64+
return &NFSStatusError{NFSStatusExist}
6465
}
6566
if how == createModeGuarded {
66-
return &NFSStatusErrorWithWccData{NFSStatusExist}
67+
return &NFSStatusError{NFSStatusExist}
6768
}
6869
} else {
6970
if s, err := fs.Stat(fs.Join(path...)); err != nil {
70-
return &NFSStatusErrorWithWccData{NFSStatusAccess}
71+
return &NFSStatusError{NFSStatusAccess}
7172
} else if !s.IsDir() {
72-
return &NFSStatusErrorWithWccData{NFSStatusNotDir}
73+
return &NFSStatusError{NFSStatusNotDir}
7374
}
7475
}
7576

7677
file, err := fs.Create(newFilePath)
7778
if err != nil {
78-
return &NFSStatusErrorWithWccData{NFSStatusAccess}
79+
return &NFSStatusError{NFSStatusAccess}
7980
}
8081
if err := file.Close(); err != nil {
81-
return &NFSStatusErrorWithWccData{NFSStatusAccess}
82+
return &NFSStatusError{NFSStatusAccess}
8283
}
8384

8485
fp := userHandle.ToHandle(fs, append(path, file.Name()))
8586
changer := userHandle.Change(fs)
8687
if err := attrs.Apply(changer, fs, newFilePath); err != nil {
87-
return &NFSStatusErrorWithWccData{NFSStatusIO}
88+
return &NFSStatusError{NFSStatusIO}
8889
}
8990

9091
writer := bytes.NewBuffer([]byte{})
@@ -99,13 +100,13 @@ func onCreate(ctx context.Context, w *response, userHandle Handler) error {
99100
if err := xdr.Write(writer, fp); err != nil {
100101
return err
101102
}
102-
WritePostOpAttrs(writer, fs, append(path, file.Name()))
103+
WritePostOpAttrs(writer, tryStat(fs, append(path, file.Name())))
103104

104105
// dir_wcc (we don't include pre_op_attr)
105106
if err := xdr.Write(writer, uint32(0)); err != nil {
106107
return err
107108
}
108-
WritePostOpAttrs(writer, fs, path)
109+
WritePostOpAttrs(writer, tryStat(fs, path))
109110

110111
return w.Write(writer.Bytes())
111112
}

nfs_onfsinfo.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func onFSInfo(ctx context.Context, w *response, userHandle Handler) error {
3434
if err := xdr.Write(writer, uint32(NFSStatusOk)); err != nil {
3535
return err
3636
}
37-
WritePostOpAttrs(writer, fs, path)
37+
WritePostOpAttrs(writer, tryStat(fs, path))
3838

3939
type fsinfores struct {
4040
Rtmax uint32

nfs_onfsstat.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func onFSStat(ctx context.Context, w *response, userHandle Handler) error {
4242
if err := xdr.Write(writer, uint32(NFSStatusOk)); err != nil {
4343
return err
4444
}
45-
WritePostOpAttrs(writer, fs, path)
45+
WritePostOpAttrs(writer, tryStat(fs, path))
4646

4747
if err := xdr.Write(writer, defaults); err != nil {
4848
return err

0 commit comments

Comments
 (0)