fix(platform): support Windows storage and native filesystem boundaries
This commit is contained in:
1 parent
3726423338
commit
e239fff253
24 files changed
+355
-51
No files matched your search
@@ -0,0 +1,36 @@
|
||||
package fileutil
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAvailableBytes(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
available, err := AvailableBytes(root)
|
||||
if err != nil || available == 0 {
|
||||
t.Fatalf("available space: %d, %v", available, err)
|
||||
}
|
||||
if _, err := AvailableBytes(filepath.Join(root, "missing")); err == nil {
|
||||
t.Fatal("missing directory accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLocalPath(t *testing.T) {
|
||||
for _, name := range []string{"notes/中文 note.md", "vault/.rawmark/tree-icons.json"} {
|
||||
if !IsLocalPath(name) {
|
||||
t.Fatalf("valid path rejected: %s", name)
|
||||
}
|
||||
}
|
||||
for _, name := range []string{"", "../outside", "/absolute"} {
|
||||
if IsLocalPath(name) {
|
||||
t.Fatalf("nonlocal path accepted: %s", name)
|
||||
}
|
||||
}
|
||||
for _, name := range []string{"C:note.md", "note.md:stream", "CON", "a/NUL.txt", "a/note. ", "a/note.", "a?/note.md", "a/line\n.md"} {
|
||||
if got := IsLocalPath(name); got != (runtime.GOOS != "windows") {
|
||||
t.Fatalf("native path %q: %v", name, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package fileutil
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IsLocalPath also rejects Windows aliases and invalid native filename characters.
|
||||
func IsLocalPath(name string) bool {
|
||||
if !filepath.IsLocal(name) {
|
||||
return false
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
if strings.ContainsAny(name, `<>:"\|?*`) {
|
||||
return false
|
||||
}
|
||||
for _, c := range name {
|
||||
if c < 32 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, part := range strings.Split(name, "/") {
|
||||
if strings.HasSuffix(part, " ") || strings.HasSuffix(part, ".") {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//go:build !windows
|
||||
|
||||
package fileutil
|
||||
|
||||
import "syscall"
|
||||
|
||||
// AvailableBytes returns disk space available to the current user.
|
||||
func AvailableBytes(dir string) (uint64, error) {
|
||||
var stat syscall.Statfs_t
|
||||
if err := syscall.Statfs(dir, &stat); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return stat.Bavail * uint64(stat.Bsize), nil
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package fileutil
|
||||
|
||||
import "golang.org/x/sys/windows"
|
||||
|
||||
// AvailableBytes returns disk space available to the current user.
|
||||
func AvailableBytes(dir string) (uint64, error) {
|
||||
name, err := windows.UTF16PtrFromString(dir)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var available uint64
|
||||
err = windows.GetDiskFreeSpaceEx(name, &available, nil, nil)
|
||||
return available, err
|
||||
}
|
||||
Reference in new issue
Block a user