diff --git a/internal/model/puller.go b/internal/model/puller.go index 3124940d2..968db7a76 100644 --- a/internal/model/puller.go +++ b/internal/model/puller.go @@ -373,12 +373,11 @@ func (p *Puller) handleDir(file protocol.FileInfo) { } info, err := os.Lstat(realName) - isLink, _ := symlinks.IsSymlink(realName) switch { // There is already something under that name, but it's a file/link. // Most likely a file/link is getting replaced with a directory. // Remove the file/link and fall through to directory creation. - case isLink || (err == nil && !info.IsDir()): + case err == nil && (!info.IsDir() || info.Mode()&os.ModeSymlink != 0): err = osutil.InWritableDir(os.Remove, realName) if err != nil { l.Infof("Puller (folder %q, dir %q): %v", p.folder, file.Name, err) @@ -795,8 +794,7 @@ func (p *Puller) performFinish(state *sharedPullerState) { // If the target path is a symlink or a directory, we cannot copy // over it, hence remove it before proceeding. stat, err := os.Lstat(state.realName) - isLink, _ := symlinks.IsSymlink(state.realName) - if isLink || (err == nil && stat.IsDir()) { + if err == nil && (stat.IsDir() || stat.Mode()&os.ModeSymlink != 0) { osutil.InWritableDir(os.Remove, state.realName) } // Replace the original content with the new one diff --git a/internal/scanner/walk.go b/internal/scanner/walk.go index f3f7cb5a8..403958613 100644 --- a/internal/scanner/walk.go +++ b/internal/scanner/walk.go @@ -131,12 +131,9 @@ func (w *Walker) walkAndHashFiles(fchan chan protocol.FileInfo) filepath.WalkFun return nil } - // We must perform this check, as symlinks on Windows are always - // .IsRegular or .IsDir unlike on Unix. // Index wise symlinks are always files, regardless of what the target // is, because symlinks carry their target path as their content. - isSymlink, _ := symlinks.IsSymlink(p) - if isSymlink { + if info.Mode()&os.ModeSymlink != 0 { var rval error // If the target is a directory, do NOT descend down there. // This will cause files to get tracked, and removing the symlink @@ -199,7 +196,7 @@ func (w *Walker) walkAndHashFiles(fchan chan protocol.FileInfo) filepath.WalkFun if w.CurrentFiler != nil { cf := w.CurrentFiler.CurrentFile(rn) permUnchanged := w.IgnorePerms || !cf.HasPermissionBits() || PermsEqual(cf.Flags, uint32(info.Mode())) - if !cf.IsDeleted() && cf.IsDirectory() && permUnchanged { + if !cf.IsDeleted() && cf.IsDirectory() && permUnchanged && !cf.IsSymlink() { return nil } } diff --git a/internal/symlinks/symlink_unix.go b/internal/symlinks/symlink_unix.go index 814c74118..4dd73cb12 100644 --- a/internal/symlinks/symlink_unix.go +++ b/internal/symlinks/symlink_unix.go @@ -41,14 +41,6 @@ func Read(path string) (string, uint32, error) { return osutil.NormalizedFilename(path), mode, err } -func IsSymlink(path string) (bool, error) { - lstat, err := os.Lstat(path) - if err != nil { - return false, err - } - return lstat.Mode()&os.ModeSymlink != 0, nil -} - func Create(source, target string, flags uint32) error { return os.Symlink(osutil.NativeFilename(target), source) } diff --git a/internal/symlinks/symlink_windows.go b/internal/symlinks/symlink_windows.go index 93a14b588..0aeb6b837 100644 --- a/internal/symlinks/symlink_windows.go +++ b/internal/symlinks/symlink_windows.go @@ -69,8 +69,8 @@ func init() { return } - isLink, err := IsSymlink(path) - if err != nil || !isLink { + stat, err := os.Lstat(path) + if err != nil || stat.Mode()&os.ModeSymlink == 0 { return } @@ -139,19 +139,6 @@ func Read(path string) (string, uint32, error) { return osutil.NormalizedFilename(data.PrintName()), flags, nil } -func IsSymlink(path string) (bool, error) { - ptr, err := syscall.UTF16PtrFromString(path) - if err != nil { - return false, err - } - - attr, err := syscall.GetFileAttributes(ptr) - if err != nil { - return false, err - } - return attr&FILE_ATTRIBUTE_REPARSE_POINT != 0, nil -} - func Create(source, target string, flags uint32) error { srcp, err := syscall.UTF16PtrFromString(source) if err != nil {