mirror of
https://github.com/rclone/rclone.git
synced 2025-04-19 18:31:10 +08: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 (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@ -85,6 +86,31 @@ func (dh *diskHandler) makeSymlinkCache() error {
|
||||
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
|
||||
//
|
||||
// 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()
|
||||
}
|
||||
|
||||
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)
|
||||
@ -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) {
|
||||
//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
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user