lib/symlinks need not depend on protocol
This commit is contained in:
@@ -11,7 +11,6 @@ package symlinks
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/syncthing/protocol"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
)
|
||||
|
||||
@@ -19,23 +18,24 @@ var (
|
||||
Supported = true
|
||||
)
|
||||
|
||||
func Read(path string) (string, uint32, error) {
|
||||
var mode uint32
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
mode = protocol.FlagSymlinkMissingTarget
|
||||
} else if stat.IsDir() {
|
||||
mode = protocol.FlagDirectory
|
||||
func Read(path string) (string, TargetType, error) {
|
||||
tt := TargetUnknown
|
||||
if stat, err := os.Stat(path); err == nil {
|
||||
if stat.IsDir() {
|
||||
tt = TargetDirectory
|
||||
} else {
|
||||
tt = TargetFile
|
||||
}
|
||||
}
|
||||
path, err = os.Readlink(path)
|
||||
path, err := os.Readlink(path)
|
||||
|
||||
return osutil.NormalizedFilename(path), mode, err
|
||||
return osutil.NormalizedFilename(path), tt, err
|
||||
}
|
||||
|
||||
func Create(source, target string, flags uint32) error {
|
||||
func Create(source, target string, tt TargetType) error {
|
||||
return os.Symlink(osutil.NativeFilename(target), source)
|
||||
}
|
||||
|
||||
func ChangeType(path string, flags uint32) error {
|
||||
func ChangeType(path string, tt TargetType) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -101,14 +101,14 @@ func (r *reparseData) SubstituteName() string {
|
||||
return string(utf16.Decode(r.buffer[offset : offset+length]))
|
||||
}
|
||||
|
||||
func Read(path string) (string, uint32, error) {
|
||||
func Read(path string) (string, TargetType, error) {
|
||||
ptr, err := syscall.UTF16PtrFromString(path)
|
||||
if err != nil {
|
||||
return "", protocol.FlagSymlinkMissingTarget, err
|
||||
return "", TargetUnknown, err
|
||||
}
|
||||
handle, err := syscall.CreateFile(ptr, 0, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS|Win32FileFlagOpenReparsePoint, 0)
|
||||
if err != nil || handle == syscall.InvalidHandle {
|
||||
return "", protocol.FlagSymlinkMissingTarget, err
|
||||
return "", TargetUnknown, err
|
||||
}
|
||||
defer syscall.Close(handle)
|
||||
var ret uint16
|
||||
@@ -116,21 +116,22 @@ func Read(path string) (string, uint32, error) {
|
||||
|
||||
r1, _, err := syscall.Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), Win32FsctlGetReparsePoint, 0, 0, uintptr(unsafe.Pointer(&data)), unsafe.Sizeof(data), uintptr(unsafe.Pointer(&ret)), 0, 0)
|
||||
if r1 == 0 {
|
||||
return "", protocol.FlagSymlinkMissingTarget, err
|
||||
return "", TargetUnknown, err
|
||||
}
|
||||
|
||||
var flags uint32
|
||||
attr, err := syscall.GetFileAttributes(ptr)
|
||||
if err != nil {
|
||||
flags = protocol.FlagSymlinkMissingTarget
|
||||
} else if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||
flags = protocol.FlagDirectory
|
||||
tt := TargetUnknown
|
||||
if attr, err := syscall.GetFileAttributes(ptr); err == nil {
|
||||
if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||
tt = TargetDirectory
|
||||
} else {
|
||||
tt = TargetFile
|
||||
}
|
||||
}
|
||||
|
||||
return osutil.NormalizedFilename(data.PrintName()), flags, nil
|
||||
return osutil.NormalizedFilename(data.PrintName()), tt, nil
|
||||
}
|
||||
|
||||
func Create(source, target string, flags uint32) error {
|
||||
func Create(source, target string, tt TargetType) error {
|
||||
srcp, err := syscall.UTF16PtrFromString(source)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -146,7 +147,7 @@ func Create(source, target string, flags uint32) error {
|
||||
// If the flags doesn't reveal the target type, try to evaluate it
|
||||
// ourselves, and worst case default to the symlink pointing to a file.
|
||||
mode := 0
|
||||
if flags&protocol.FlagSymlinkMissingTarget != 0 {
|
||||
if tt == TargetUnknown {
|
||||
path := target
|
||||
if !filepath.IsAbs(target) {
|
||||
path = filepath.Join(filepath.Dir(source), target)
|
||||
@@ -156,7 +157,7 @@ func Create(source, target string, flags uint32) error {
|
||||
if err == nil && stat.IsDir() {
|
||||
mode = Win32SymbolicLinkFlagDirectory
|
||||
}
|
||||
} else if flags&protocol.FlagDirectory != 0 {
|
||||
} else if tt == TargetDirectory {
|
||||
mode = Win32SymbolicLinkFlagDirectory
|
||||
}
|
||||
|
||||
@@ -167,24 +168,24 @@ func Create(source, target string, flags uint32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func ChangeType(path string, flags uint32) error {
|
||||
target, cflags, err := Read(path)
|
||||
func ChangeType(path string, tt TargetType) error {
|
||||
target, exTt, err := Read(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// If it's the same type, nothing to do.
|
||||
if cflags&protocol.SymlinkTypeMask == flags&protocol.SymlinkTypeMask {
|
||||
if tt == exTt {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the actual type is unknown, but the new type is file, nothing to do
|
||||
if cflags&protocol.FlagSymlinkMissingTarget != 0 && flags&protocol.FlagDirectory == 0 {
|
||||
if exTt == TargetUnknown && tt != TargetDirectory {
|
||||
return nil
|
||||
}
|
||||
return osutil.InWritableDir(func(path string) error {
|
||||
// It should be a symlink as well hence no need to change permissions on
|
||||
// the file.
|
||||
os.Remove(path)
|
||||
return Create(path, target, flags)
|
||||
return Create(path, target, tt)
|
||||
}, path)
|
||||
}
|
||||
|
||||
15
lib/symlinks/targets.go
Normal file
15
lib/symlinks/targets.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (C) 2015 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package symlinks
|
||||
|
||||
type TargetType int
|
||||
|
||||
const (
|
||||
TargetFile TargetType = iota
|
||||
TargetDirectory
|
||||
TargetUnknown
|
||||
)
|
||||
Reference in New Issue
Block a user