Browse Source

Work around broken Lstat on Android

Jakob Borg 10 years ago
parent
commit
102a2db1f3

+ 1 - 1
cmd/syncthing/main.go

@@ -1019,7 +1019,7 @@ func cleanConfigDirectory() {
 		}
 
 		for _, file := range files {
-			info, err := os.Lstat(file)
+			info, err := osutil.Lstat(file)
 			if err != nil {
 				l.Infoln("Cleaning:", err)
 				continue

+ 1 - 1
internal/model/model.go

@@ -1271,7 +1271,7 @@ nextSub:
 					"size":     f.Size(),
 				})
 				batch = append(batch, nf)
-			} else if _, err := os.Lstat(filepath.Join(folderCfg.Path(), f.Name)); err != nil {
+			} else if _, err := osutil.Lstat(filepath.Join(folderCfg.Path(), f.Name)); err != nil {
 				// File has been deleted.
 
 				// We don't specifically verify that the error is

+ 2 - 2
internal/model/rwfolder.go

@@ -499,7 +499,7 @@ func (p *rwFolder) handleDir(file protocol.FileInfo) {
 		l.Debugf("need dir\n\t%v\n\t%v", file, curFile)
 	}
 
-	info, err := os.Lstat(realName)
+	info, err := osutil.Lstat(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.
@@ -1044,7 +1044,7 @@ func (p *rwFolder) 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)
+	stat, err := osutil.Lstat(state.realName)
 	if err == nil && (stat.IsDir() || stat.Mode()&os.ModeSymlink != 0) {
 		osutil.InWritableDir(os.Remove, state.realName)
 	}

+ 29 - 0
internal/osutil/lstat_broken.go

@@ -0,0 +1,29 @@
+// 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/.
+
+// +build linux android
+
+package osutil
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// Lstat is like os.Lstat, except lobotomized for Android. See
+// https://forum.syncthing.net/t/2395
+func Lstat(name string) (fi os.FileInfo, err error) {
+	for i := 0; i < 10; i++ { // We have to draw the line somewhere
+		fi, err = os.Lstat(name)
+		if err, ok := err.(*os.PathError); ok && err.Err == syscall.EINTR {
+			time.Sleep(time.Duration(i+1) * time.Millisecond)
+			continue
+		}
+		return
+	}
+	return
+}

+ 15 - 0
internal/osutil/lstat_ok.go

@@ -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/.
+
+// +build !linux,!android
+
+package osutil
+
+import "os"
+
+func Lstat(name string) (fi os.FileInfo, err error) {
+	return os.Lstat(name)
+}

+ 3 - 2
internal/scanner/walk.go

@@ -17,6 +17,7 @@ import (
 
 	"github.com/syncthing/protocol"
 	"github.com/syncthing/syncthing/internal/ignore"
+	"github.com/syncthing/syncthing/internal/osutil"
 	"github.com/syncthing/syncthing/internal/symlinks"
 	"golang.org/x/text/unicode/norm"
 )
@@ -193,7 +194,7 @@ func (w *Walker) walkAndHashFiles(fchan chan protocol.FileInfo) filepath.WalkFun
 
 			// We will attempt to normalize it.
 			normalizedPath := filepath.Join(w.Dir, normalizedRn)
-			if _, err := os.Lstat(normalizedPath); os.IsNotExist(err) {
+			if _, err := osutil.Lstat(normalizedPath); os.IsNotExist(err) {
 				// Nothing exists with the normalized filename. Good.
 				if err = os.Rename(p, normalizedPath); err != nil {
 					l.Infof(`Error normalizing UTF8 encoding of file "%s": %v`, rn, err)
@@ -356,7 +357,7 @@ func (w *Walker) walkAndHashFiles(fchan chan protocol.FileInfo) filepath.WalkFun
 }
 
 func checkDir(dir string) error {
-	if info, err := os.Lstat(dir); err != nil {
+	if info, err := osutil.Lstat(dir); err != nil {
 		return err
 	} else if !info.IsDir() {
 		return errors.New(dir + ": not a directory")

+ 1 - 1
internal/symlinks/symlink_windows.go

@@ -60,7 +60,7 @@ func init() {
 		return
 	}
 
-	stat, err := os.Lstat(path)
+	stat, err := osutil.Lstat(path)
 	if err != nil || stat.Mode()&os.ModeSymlink == 0 {
 		return
 	}

+ 4 - 2
internal/versioner/external.go

@@ -12,6 +12,8 @@ import (
 	"os/exec"
 	"path/filepath"
 	"strings"
+
+	"github.com/syncthing/syncthing/internal/osutil"
 )
 
 func init() {
@@ -43,7 +45,7 @@ func NewExternal(folderID, folderPath string, params map[string]string) Versione
 // Move away the named file to a version archive. If this function returns
 // nil, the named file does not exist any more (has been archived).
 func (v External) Archive(filePath string) error {
-	_, err := os.Lstat(filePath)
+	_, err := osutil.Lstat(filePath)
 	if os.IsNotExist(err) {
 		if debug {
 			l.Debugln("not archiving nonexistent file", filePath)
@@ -82,7 +84,7 @@ func (v External) Archive(filePath string) error {
 	}
 
 	// return error if the file was not removed
-	if _, err = os.Lstat(filePath); os.IsNotExist(err) {
+	if _, err = osutil.Lstat(filePath); os.IsNotExist(err) {
 		return nil
 	}
 	return errors.New("Versioner: file was not removed by external script")

+ 1 - 1
internal/versioner/simple.go

@@ -46,7 +46,7 @@ func NewSimple(folderID, folderPath string, params map[string]string) Versioner
 // Move away the named file to a version archive. If this function returns
 // nil, the named file does not exist any more (has been archived).
 func (v Simple) Archive(filePath string) error {
-	fileInfo, err := os.Lstat(filePath)
+	fileInfo, err := osutil.Lstat(filePath)
 	if os.IsNotExist(err) {
 		if debug {
 			l.Debugln("not archiving nonexistent file", filePath)

+ 2 - 2
internal/versioner/staggered.go

@@ -210,7 +210,7 @@ func (v Staggered) expire(versions []string) {
 	var prevAge int64
 	firstFile := true
 	for _, file := range versions {
-		fi, err := os.Lstat(file)
+		fi, err := osutil.Lstat(file)
 		if err != nil {
 			l.Warnln("versioner:", err)
 			continue
@@ -281,7 +281,7 @@ func (v Staggered) Archive(filePath string) error {
 	v.mutex.Lock()
 	defer v.mutex.Unlock()
 
-	_, err := os.Lstat(filePath)
+	_, err := osutil.Lstat(filePath)
 	if os.IsNotExist(err) {
 		if debug {
 			l.Debugln("not archiving nonexistent file", filePath)