From 604a4e7dbcf31478380b32c246ad0c3150d7ace8 Mon Sep 17 00:00:00 2001 From: Audrius Butkevicius Date: Thu, 4 Dec 2014 23:02:57 +0000 Subject: [PATCH] Scrap IsSymlink for native support on Go 1.4 Obviously needs Go 1.4 to go back in. I am still open to doing fix-up's on rescan interval on Windows, which would still allow getting rid of all the Windows code. Frankly, we could just defer creations of links (like we defer deletions of files) in hopes that the target gets created, and if it doesn't, well tough luck, you'll get a file symlink. To be honest, nobody would even notice this 'issue' as I am sure nobody on Windows uses symlinks. But at the same time, this ugly code is hidden away in some creppy file in it's own module far far away, and the interface that it exports is fine'ish, so I wouldn't mind keeping it as it is. --- internal/model/puller.go | 6 ++---- internal/scanner/walk.go | 7 ++----- internal/symlinks/symlink_unix.go | 8 -------- internal/symlinks/symlink_windows.go | 17 ++--------------- 4 files changed, 6 insertions(+), 32 deletions(-) diff --git a/internal/model/puller.go b/internal/model/puller.go index 3124940d..968db7a7 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 f3f7cb5a..40395861 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 814c7411..4dd73cb1 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 93a14b58..0aeb6b83 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 {