Browse Source

all: Adjust windows perms in fs package (#5200)

Simon Frei 7 years ago
parent
commit
272fb3b444
4 changed files with 36 additions and 51 deletions
  1. 29 0
      lib/fs/fsfileinfo_windows.go
  2. 0 3
      lib/model/folder_sendrecv.go
  3. 0 19
      lib/osutil/osutil.go
  4. 7 29
      lib/scanner/walk.go

+ 29 - 0
lib/fs/fsfileinfo_windows.go

@@ -8,8 +8,28 @@ package fs
 
 import (
 	"os"
+	"path/filepath"
+	"strings"
 )
 
+var execExts map[string]bool
+
+func init() {
+	// PATHEXT contains a list of executable file extensions, on Windows
+	pathext := filepath.SplitList(os.Getenv("PATHEXT"))
+	// We want the extensions in execExts to be lower case
+	execExts = make(map[string]bool, len(pathext))
+	for _, ext := range pathext {
+		execExts[strings.ToLower(ext)] = true
+	}
+}
+
+// isWindowsExecutable returns true if the given path has an extension that is
+// in the list of executable extensions.
+func isWindowsExecutable(path string) bool {
+	return execExts[strings.ToLower(filepath.Ext(path))]
+}
+
 func (e fsFileInfo) Mode() FileMode {
 	m := e.FileInfo.Mode()
 	if m&os.ModeSymlink != 0 && e.Size() > 0 {
@@ -17,5 +37,14 @@ func (e fsFileInfo) Mode() FileMode {
 		// NTFS deduped files. Remove the symlink bit.
 		m &^= os.ModeSymlink
 	}
+	// Set executable bits on files with executable extenions (.exe, .bat, etc).
+	if isWindowsExecutable(e.Name()) {
+		m |= 0111
+	}
+	// There is no user/group/others in Windows' read-only attribute, and
+	// all "w" bits are set if the file is not read-only.  Do not send these
+	// group/others-writable bits to other devices in order to avoid
+	// unexpected world-writable files on other platforms.
+	m &^= 0022
 	return FileMode(m)
 }

+ 0 - 3
lib/model/folder_sendrecv.go

@@ -1453,9 +1453,6 @@ func (f *sendReceiveFolder) performFinish(ignores *ignore.Matcher, file, curFile
 		// handle that.
 
 		curMode := uint32(stat.Mode())
-		if runtime.GOOS == "windows" && osutil.IsWindowsExecutable(file.Name) {
-			curMode |= 0111
-		}
 
 		// Check that the file on disk is what we expect it to be according
 		// to the database. If there's a mismatch here, there might be local

+ 0 - 19
lib/osutil/osutil.go

@@ -10,7 +10,6 @@ package osutil
 import (
 	"errors"
 	"io"
-	"os"
 	"path/filepath"
 	"runtime"
 	"strings"
@@ -136,24 +135,6 @@ func copyFileContents(filesystem fs.Filesystem, src, dst string) (err error) {
 	return
 }
 
-var execExts map[string]bool
-
-func init() {
-	// PATHEXT contains a list of executable file extensions, on Windows
-	pathext := filepath.SplitList(os.Getenv("PATHEXT"))
-	// We want the extensions in execExts to be lower case
-	execExts = make(map[string]bool, len(pathext))
-	for _, ext := range pathext {
-		execExts[strings.ToLower(ext)] = true
-	}
-}
-
-// IsWindowsExecutable returns true if the given path has an extension that is
-// in the list of executable extensions.
-func IsWindowsExecutable(path string) bool {
-	return execExts[strings.ToLower(filepath.Ext(path))]
-}
-
 func IsDeleted(ffs fs.Filesystem, name string) bool {
 	if _, err := ffs.Lstat(name); fs.IsNotExist(err) {
 		return true

+ 7 - 29
lib/scanner/walk.go

@@ -19,26 +19,10 @@ import (
 	"github.com/syncthing/syncthing/lib/events"
 	"github.com/syncthing/syncthing/lib/fs"
 	"github.com/syncthing/syncthing/lib/ignore"
-	"github.com/syncthing/syncthing/lib/osutil"
 	"github.com/syncthing/syncthing/lib/protocol"
 	"golang.org/x/text/unicode/norm"
 )
 
-var maskModePerm fs.FileMode
-
-func init() {
-	if runtime.GOOS == "windows" {
-		// There is no user/group/others in Windows' read-only
-		// attribute, and all "w" bits are set in fs.FileMode
-		// if the file is not read-only.  Do not send these
-		// group/others-writable bits to other devices in order to
-		// avoid unexpected world-writable files on other platforms.
-		maskModePerm = fs.ModePerm & 0755
-	} else {
-		maskModePerm = fs.ModePerm
-	}
-}
-
 type Config struct {
 	// Folder for which the walker has been created
 	Folder string
@@ -326,16 +310,10 @@ func (w *walker) walkRegular(ctx context.Context, relPath string, info fs.FileIn
 	curFile, hasCurFile := w.CurrentFiler.CurrentFile(relPath)
 
 	newMode := uint32(info.Mode())
-	if runtime.GOOS == "windows" {
-		if osutil.IsWindowsExecutable(relPath) {
-			// Set executable bits on files with executable extenions (.exe,
-			// .bat, etc).
-			newMode |= 0111
-		} else if hasCurFile {
-			// If we have an existing index entry, copy the executable bits
-			// from there.
-			newMode |= (curFile.Permissions & 0111)
-		}
+	if runtime.GOOS == "windows" && hasCurFile {
+		// If we have an existing index entry, copy the executable bits
+		// from there.
+		newMode |= (curFile.Permissions & 0111)
 	}
 
 	blockSize := protocol.MinBlockSize
@@ -362,7 +340,7 @@ func (w *walker) walkRegular(ctx context.Context, relPath string, info fs.FileIn
 		Name:          relPath,
 		Type:          protocol.FileInfoTypeFile,
 		Version:       curFile.Version.Update(w.ShortID),
-		Permissions:   newMode & uint32(maskModePerm),
+		Permissions:   newMode & uint32(fs.ModePerm),
 		NoPermissions: w.IgnorePerms,
 		ModifiedS:     info.ModTime().Unix(),
 		ModifiedNs:    int32(info.ModTime().Nanosecond()),
@@ -405,7 +383,7 @@ func (w *walker) walkDir(ctx context.Context, relPath string, info fs.FileInfo,
 		Name:          relPath,
 		Type:          protocol.FileInfoTypeDirectory,
 		Version:       cf.Version.Update(w.ShortID),
-		Permissions:   uint32(info.Mode() & maskModePerm),
+		Permissions:   uint32(info.Mode() & fs.ModePerm),
 		NoPermissions: w.IgnorePerms,
 		ModifiedS:     info.ModTime().Unix(),
 		ModifiedNs:    int32(info.ModTime().Nanosecond()),
@@ -615,7 +593,7 @@ func CreateFileInfo(fi fs.FileInfo, name string, filesystem fs.Filesystem) (prot
 	f := protocol.FileInfo{
 		Name:        name,
 		Type:        protocol.FileInfoTypeFile,
-		Permissions: uint32(fi.Mode()),
+		Permissions: uint32(fi.Mode() & fs.ModePerm),
 		ModifiedS:   fi.ModTime().Unix(),
 		ModifiedNs:  int32(fi.ModTime().Nanosecond()),
 		Size:        fi.Size(),