mirror of
https://github.com/rclone/rclone.git
synced 2025-04-19 01:59:00 +08:00
Merge 1dc85e5fcaec5c7c8a5dbb5a914935bb84b2fd6a into e0d477804b583163b4b5696d24a2ccf8c0bb11e3
This commit is contained in:
commit
c74a5ad9cf
@ -7,7 +7,10 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
// OpenFile is the generalized open call; most users will use Open or Create
|
||||
@ -27,6 +30,14 @@ func OpenFile(path string, mode int, perm os.FileMode) (*os.File, error) {
|
||||
if len(path) == 0 {
|
||||
return nil, syscall.ERROR_FILE_NOT_FOUND
|
||||
}
|
||||
|
||||
// For windows the max path length is 260 characters
|
||||
// if the LongPathsEnabled is not set
|
||||
// https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
|
||||
if !strings.HasPrefix(path, `\\?\`) && !IsLongPathsEnabled() && len(path) >= 260 {
|
||||
return nil, &os.PathError{Path: path, Op: "open", Err: errors.New("path length 260 or higher")}
|
||||
}
|
||||
|
||||
pathp, err := syscall.UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -100,3 +111,24 @@ func IsReserved(path string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsLongPathsEnabled checks if the current have the LongPathsEnabled enabled
|
||||
func IsLongPathsEnabled() bool {
|
||||
// Read registry
|
||||
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\FileSystem`, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
s, _, err := k.GetIntegerValue("LongPathsEnabled")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if s == 0x00000001 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
21
lib/file/file_windows_test.go
Normal file
21
lib/file/file_windows_test.go
Normal file
@ -0,0 +1,21 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFileOpenMaxPathLength(t *testing.T) {
|
||||
// Skip if the long path is enabled
|
||||
if IsLongPathsEnabled() {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
path := `C:\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path`
|
||||
_, err := OpenFile(path, 0644, 0644)
|
||||
assert.Error(t, err, "mkdir: Max path length can't exceed 260")
|
||||
}
|
@ -3,8 +3,10 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
@ -17,6 +19,13 @@ import (
|
||||
// Based on source code from golang's os.MkdirAll
|
||||
// (https://github.com/golang/go/blob/master/src/os/path.go)
|
||||
func MkdirAll(path string, perm os.FileMode) error {
|
||||
// For windows the max path length is 260 characters
|
||||
// if the LongPathsEnabled is not set
|
||||
// https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
|
||||
if !strings.HasPrefix(path, `\\?\`) && !IsLongPathsEnabled() && len(path) >= 260 {
|
||||
return &os.PathError{Path: path, Op: "open", Err: errors.New("path length 260 or higher")}
|
||||
}
|
||||
|
||||
// Fast path: if we can tell whether path is a directory or file, stop with success or error.
|
||||
dir, err := os.Stat(path)
|
||||
if err == nil {
|
||||
|
@ -159,3 +159,14 @@ func TestMkdirAllOnUnusedNetworkHost(t *testing.T) {
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
func TestMkdirMaxPathLength(t *testing.T) {
|
||||
// Skip if the long path is enabled
|
||||
if IsLongPathsEnabled() {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
path := `C:\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path\my\path`
|
||||
err := MkdirAll(path, 0777)
|
||||
assert.Error(t, err, "mkdir: Max path length can't exceed 260")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user