2017-12-29 21:23:06 +00:00
|
|
|
// Copyright (C) 2017 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 https://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
|
|
package fs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
2018-09-16 14:09:56 +00:00
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2022-09-14 07:50:55 +00:00
|
|
|
"time"
|
2017-12-29 21:23:06 +00:00
|
|
|
)
|
|
|
|
|
2018-09-16 14:09:56 +00:00
|
|
|
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))]
|
|
|
|
}
|
|
|
|
|
2019-02-24 17:02:02 +00:00
|
|
|
func (e basicFileInfo) Mode() FileMode {
|
2017-12-29 21:23:06 +00:00
|
|
|
m := e.FileInfo.Mode()
|
|
|
|
if m&os.ModeSymlink != 0 && e.Size() > 0 {
|
|
|
|
// "Symlinks" with nonzero size are in fact "hard" links, such as
|
|
|
|
// NTFS deduped files. Remove the symlink bit.
|
|
|
|
m &^= os.ModeSymlink
|
|
|
|
}
|
2022-08-23 13:44:11 +00:00
|
|
|
// Set executable bits on files with executable extensions (.exe, .bat, etc).
|
2018-09-16 14:09:56 +00:00
|
|
|
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
|
2017-12-29 21:23:06 +00:00
|
|
|
return FileMode(m)
|
|
|
|
}
|
2019-02-24 17:02:02 +00:00
|
|
|
|
|
|
|
func (e basicFileInfo) Owner() int {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e basicFileInfo) Group() int {
|
|
|
|
return -1
|
|
|
|
}
|
2020-05-13 19:46:24 +00:00
|
|
|
|
2022-09-14 07:50:55 +00:00
|
|
|
func (basicFileInfo) InodeChangeTime() time.Time {
|
|
|
|
return time.Time{}
|
|
|
|
}
|
|
|
|
|
2020-05-13 19:46:24 +00:00
|
|
|
// osFileInfo converts e to os.FileInfo that is suitable
|
|
|
|
// to be passed to os.SameFile.
|
|
|
|
func (e *basicFileInfo) osFileInfo() os.FileInfo {
|
|
|
|
fi := e.FileInfo
|
|
|
|
if fi, ok := fi.(*dirJunctFileInfo); ok {
|
|
|
|
return fi.FileInfo
|
|
|
|
}
|
|
|
|
return fi
|
|
|
|
}
|