lib/symlinks need not depend on protocol
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user