mirror of
https://github.com/rclone/rclone.git
synced 2025-06-24 14:01:31 +02:00
serve nfs: change the format of --nfs-cache-type symlink file handles
This is an backwards incompatible change which will invalidate the current handles. This change adds a 4 byte big endian length prefix to the handles so we can in future suffix extra info on the handles. This needed to be 4 bytes as Linux does not like File handles which aren't multiples of 4 bytes long.
This commit is contained in:
parent
533c6438f3
commit
fe84cbdc9d
@ -27,6 +27,7 @@ package nfs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -85,6 +86,31 @@ func (dh *diskHandler) makeSymlinkCache() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prefixes a []byte with its length as a 4-byte big-endian integer.
|
||||||
|
func addLengthPrefix(data []byte) []byte {
|
||||||
|
length := uint32(len(data))
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err := binary.Write(buf, binary.BigEndian, length)
|
||||||
|
if err != nil {
|
||||||
|
// This should never fail
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
buf.Write(data)
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes the 4-byte big-endian length prefix from a []byte.
|
||||||
|
func removeLengthPrefix(data []byte) ([]byte, error) {
|
||||||
|
if len(data) < 4 {
|
||||||
|
return nil, errors.New("file handle too short")
|
||||||
|
}
|
||||||
|
length := binary.BigEndian.Uint32(data[:4])
|
||||||
|
if int(length) != len(data)-4 {
|
||||||
|
return nil, errors.New("file handle invalid length")
|
||||||
|
}
|
||||||
|
return data[4 : 4+length], nil
|
||||||
|
}
|
||||||
|
|
||||||
// Write the fullPath into cachePath returning the possibly updated fh
|
// Write the fullPath into cachePath returning the possibly updated fh
|
||||||
//
|
//
|
||||||
// This writes the fullPath into the file with the cachePath given and
|
// This writes the fullPath into the file with the cachePath given and
|
||||||
@ -115,7 +141,8 @@ func (dh *diskHandler) symlinkCacheWrite(fh []byte, cachePath string, fullPath s
|
|||||||
dh.handleType = handle.Type()
|
dh.handleType = handle.Type()
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle.Bytes(), nil
|
// Adjust the raw handle so it has a length prefix
|
||||||
|
return addLengthPrefix(handle.Bytes()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the contents of (fh, cachePath)
|
// Read the contents of (fh, cachePath)
|
||||||
@ -128,6 +155,12 @@ func (dh *diskHandler) symlinkCacheWrite(fh []byte, cachePath string, fullPath s
|
|||||||
func (dh *diskHandler) symlinkCacheRead(fh []byte, cachePath string) (fullPath []byte, err error) {
|
func (dh *diskHandler) symlinkCacheRead(fh []byte, cachePath string) (fullPath []byte, err error) {
|
||||||
//defer log.Trace(nil, "fh=%x, cachePath=%q", fh, cachePath)("fullPath=%q, err=%v", &fullPath, &err)
|
//defer log.Trace(nil, "fh=%x, cachePath=%q", fh, cachePath)("fullPath=%q, err=%v", &fullPath, &err)
|
||||||
|
|
||||||
|
// First check and remove the file handle prefix length
|
||||||
|
fh, err = removeLengthPrefix(fh)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("symlink cache open by handle at: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Find the file with the handle passed in
|
// Find the file with the handle passed in
|
||||||
handle := unix.NewFileHandle(dh.handleType, fh)
|
handle := unix.NewFileHandle(dh.handleType, fh)
|
||||||
fd, err := unix.OpenByHandleAt(unix.AT_FDCWD, handle, unix.O_RDONLY|unix.O_PATH|unix.O_NOFOLLOW) // needs O_PATH for symlinks
|
fd, err := unix.OpenByHandleAt(unix.AT_FDCWD, handle, unix.O_RDONLY|unix.O_PATH|unix.O_NOFOLLOW) // needs O_PATH for symlinks
|
||||||
|
Loading…
x
Reference in New Issue
Block a user