From dbb21cc48952b096dfa329b626059b0a6c72b21e Mon Sep 17 00:00:00 2001 From: Ronald G Minnich Date: Wed, 2 Jul 2025 15:52:02 -0700 Subject: [PATCH 1/3] Truncate: do not use O_EXCL on Plan 9 Signed-off-by: Ronald G Minnich --- file.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/file.go b/file.go index c3f1911..7a47c79 100644 --- a/file.go +++ b/file.go @@ -6,6 +6,7 @@ import ( "io" "math" "os" + "runtime" "time" "github.com/go-git/go-billy/v5" @@ -249,7 +250,11 @@ func (s *SetFileAttributes) Apply(changer billy.Change, fs billy.Filesystem, fil if curr.Mode()&os.ModeSymlink != 0 { return &NFSStatusError{NFSStatusNotSupp, os.ErrInvalid} } - fp, err := fs.OpenFile(file, os.O_WRONLY|os.O_EXCL, 0) + flags := os.O_WRONLY + if runtime.GOOS != "plan9" { + flags |= os.O_EXCL + } + fp, err := fs.OpenFile(file, flags, 0) if errors.Is(err, os.ErrPermission) { return &NFSStatusError{NFSStatusAccess, err} } else if err != nil { From 2f2b5e457af451a9f424502f042593146224feea Mon Sep 17 00:00:00 2001 From: Ronald G Minnich Date: Wed, 9 Jul 2025 09:25:37 -0700 Subject: [PATCH 2/3] Lstat: do not Log.Errorf for os.ErrNotExist Lots of programs (including git) do an Lstat to test file existence. This can produce a lot of not-very-useful spew. Just return nil for this error. This makes the package more usable. Signed-off-by: Ronald G Minnich --- file.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/file.go b/file.go index 7a47c79..c605bf2 100644 --- a/file.go +++ b/file.go @@ -134,6 +134,13 @@ func ToFileAttribute(info os.FileInfo, filePath string) *FileAttribute { func tryStat(fs billy.Filesystem, path []string) *FileAttribute { fullPath := fs.Join(path...) attrs, err := fs.Lstat(fullPath) + + // Programs frequently use Lstat to test for file existence. + // In this case, just return nil, without the Log. + if errors.Is(err, os.ErrNotExist) { + return nil + } + if err != nil || attrs == nil { Log.Errorf("err loading attrs for %s: %v", fs.Join(path...), err) return nil From 6cd629d06e00dfaf9639fa12ba63dee35c73b82d Mon Sep 17 00:00:00 2001 From: Ronald G Minnich Date: Wed, 9 Jul 2025 09:28:28 -0700 Subject: [PATCH 3/3] Create: warn, but do not error, when Exclusive is requested Exclusive over NFS has always been a dicey situation, and failing breaks lots of things for which it is mainly best-effort (e.g. git); if it does not work, that is ok. Print a warning message, but continue with the operation. Signed-off-by: Ronald G Minnich --- nfs_oncreate.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nfs_oncreate.go b/nfs_oncreate.go index 63d7901..54990bb 100644 --- a/nfs_oncreate.go +++ b/nfs_oncreate.go @@ -39,9 +39,8 @@ func onCreate(ctx context.Context, w *response, userHandle Handler) error { if err := xdr.Read(w.req.Body, &verf); err != nil { return &NFSStatusError{NFSStatusInval, err} } - Log.Errorf("failing create to indicate lack of support for 'exclusive' mode.") - // TODO: support 'exclusive' mode. - return &NFSStatusError{NFSStatusNotSupp, os.ErrPermission} + attrs = &SetFileAttributes{} + Log.Printf("%q: request for unimplemented 'exclusive' mode.", obj.Filename) } else { // invalid return &NFSStatusError{NFSStatusNotSupp, os.ErrInvalid}