From 5af6cbae2cfc9e86e96cbb5d1695e0b932b7401e Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Thu, 4 Dec 2014 12:08:04 +0100 Subject: [PATCH] Verify Windows support, report appropriate errors when unsupported --- internal/symlinks/symlink.go | 58 +++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/internal/symlinks/symlink.go b/internal/symlinks/symlink.go index 19a039de8..30d597f84 100644 --- a/internal/symlinks/symlink.go +++ b/internal/symlinks/symlink.go @@ -16,7 +16,9 @@ package symlinks import ( + "errors" "os" + "path/filepath" "runtime" "github.com/syncthing/syncthing/internal/osutil" @@ -24,10 +26,19 @@ import ( ) var ( - Supported = true + Supported = false + ErrUnsupported = errors.New("symlinks not supported") ) +func init() { + Supported = symlinksSupported() +} + func Read(path string) (string, uint32, error) { + if !Supported { + return "", 0, ErrUnsupported + } + var mode uint32 stat, err := os.Stat(path) if err != nil { @@ -41,6 +52,10 @@ func Read(path string) (string, uint32, error) { } func IsSymlink(path string) (bool, error) { + if !Supported { + return false, ErrUnsupported + } + lstat, err := os.Lstat(path) if err != nil { return false, err @@ -49,6 +64,10 @@ func IsSymlink(path string) (bool, error) { } func Create(target, source string, flags uint32) error { + if !Supported { + return ErrUnsupported + } + return os.Symlink(osutil.NativeFilename(target), source) } @@ -58,6 +77,10 @@ func ChangeType(path string, flags uint32) error { return nil } + if !Supported { + return ErrUnsupported + } + target, cflags, err := Read(path) if err != nil { return err @@ -80,3 +103,36 @@ func ChangeType(path string, flags uint32) error { return Create(target, path, flags) }, path) } + +func symlinksSupported() bool { + if runtime.GOOS != "windows" { + // Symlinks are supported. In practice there may be deviations (FAT + // filesystems etc), but these get handled and reported as the errors + // they are when they happen. + return true + } + + // We try to create a symlink and verify that it looks like we expected. + // Needs administrator priviledges and a version higher than XP. + + base := os.TempDir() + path := filepath.Join(base, "syncthing-symlink-test") + defer os.Remove(path) + + err := Create(base, path, protocol.FlagDirectory) + if err != nil { + return false + } + + isLink, err := IsSymlink(path) + if err != nil || !isLink { + return false + } + + target, flags, err := Read(path) + if err != nil || osutil.NativeFilename(target) != base || flags&protocol.FlagDirectory == 0 { + return false + } + + return true +}