rclone/cmd/serve/nfs/server.go
nielash 5638a3841f serve nfs: fix writing files via Finder on macOS - fixes #7503
Before this change, writing files to an `nfsmount` via Finder on macOS would
cause critical errors, rendering `nfsmount` effectively unusable on macOS. This
change fixes the issue so that writes via Finder should be possible.

The issue was primarily caused by the handler's HandleLimit being set to -1. -1 is
the correct default for a NullAuthHandler, but not for a CachingHandler, which
interprets -1 not as "no limit" but as "no cache".

This change sets a high default of 1000000, and gives the user control over it
with a new --nfs-cache-handle-limit flag (available in both `serve nfs` and
`nfsmount`. A minimum of 5 is enforced, as any lower than this will be
insufficient to support directory listing.
2024-02-18 05:08:59 -05:00

61 lines
1.4 KiB
Go

//go:build unix
// +build unix
package nfs
import (
"context"
"net"
nfs "github.com/willscott/go-nfs"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/vfs"
"github.com/rclone/rclone/vfs/vfscommon"
)
// Server contains everything to run the Server
type Server struct {
opt Options
handler nfs.Handler
ctx context.Context // for global config
listener net.Listener
}
// NewServer creates a new server
func NewServer(ctx context.Context, vfs *vfs.VFS, opt *Options) (s *Server, err error) {
if vfs.Opt.CacheMode == vfscommon.CacheModeOff {
fs.LogPrintf(fs.LogLevelWarning, ctx, "NFS writes don't work without a cache, the filesystem will be served read-only")
}
// Our NFS server doesn't have any authentication, we run it on localhost and random port by default
if opt.ListenAddr == "" {
opt.ListenAddr = "localhost:"
}
s = &Server{
ctx: ctx,
opt: *opt,
}
s.handler = newHandler(vfs, opt)
s.listener, err = net.Listen("tcp", s.opt.ListenAddr)
if err != nil {
fs.Errorf(nil, "NFS server failed to listen: %v\n", err)
}
return
}
// Addr returns the listening address of the server
func (s *Server) Addr() net.Addr {
return s.listener.Addr()
}
// Shutdown stops the server
func (s *Server) Shutdown() error {
return s.listener.Close()
}
// Serve starts the server
func (s *Server) Serve() (err error) {
fs.Logf(nil, "NFS Server running at %s\n", s.listener.Addr())
return nfs.Serve(s.listener, s.handler)
}