lib/symlinks need not depend on protocol

This commit is contained in:
Jakob Borg
2015-09-04 12:54:01 +02:00
parent 21c3994650
commit 446a938b06
6 changed files with 109 additions and 40 deletions

View File

@@ -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)
}