diff --git a/cmd/stcompdirs/main.go b/cmd/stcompdirs/main.go index 74ae6c2d1..00d9914d7 100644 --- a/cmd/stcompdirs/main.go +++ b/cmd/stcompdirs/main.go @@ -15,8 +15,6 @@ import ( "log" "os" "path/filepath" - - "github.com/syncthing/syncthing/lib/symlinks" ) func main() { @@ -104,7 +102,7 @@ func startWalker(dir string, res chan<- fileInfo, abort <-chan struct{}) chan er mode: os.ModeSymlink, } - tgt, _, err := symlinks.Read(path) + tgt, err := os.Readlink(path) if err != nil { return err } diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 4b225946d..78ebdaac7 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -43,7 +43,6 @@ import ( "github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/rand" "github.com/syncthing/syncthing/lib/sha256" - "github.com/syncthing/syncthing/lib/symlinks" "github.com/syncthing/syncthing/lib/tlsutil" "github.com/syncthing/syncthing/lib/upgrade" "github.com/syncthing/syncthing/lib/weakhash" @@ -679,10 +678,6 @@ func syncthingMain(runtimeOptions RuntimeOptions) { opts := cfg.Options() - if !opts.SymlinksEnabled { - symlinks.Supported = false - } - if opts.WeakHashSelectionMethod == config.WeakHashAuto { if perfWithoutWeakHash*0.8 > perfWithWeakHash { l.Infof("Weak hash disabled, as it has an unacceptable performance impact.") @@ -751,6 +746,10 @@ func syncthingMain(runtimeOptions RuntimeOptions) { // have been incorrectly ignore filtered. ldb.DropDeltaIndexIDs() } + if cfg.RawCopy().OriginalVersion < 19 { + // Converts old symlink types to new in the entire database. + ldb.ConvertSymlinkTypes() + } m := model.NewModel(cfg, myID, myDeviceName(cfg), "syncthing", Version, ldb, protectedFiles) diff --git a/lib/config/config.go b/lib/config/config.go index fc56db763..f575587d3 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -27,7 +27,7 @@ import ( const ( OldestHandledVersion = 10 - CurrentVersion = 18 + CurrentVersion = 19 MaxRescanIntervalS = 365 * 24 * 60 * 60 ) @@ -261,6 +261,9 @@ func (cfg *Configuration) clean() error { if cfg.Version == 17 { convertV17V18(cfg) } + if cfg.Version == 18 { + convertV18V19(cfg) + } // Build a list of available devices existingDevices := make(map[protocol.DeviceID]bool) @@ -314,6 +317,11 @@ func (cfg *Configuration) clean() error { return nil } +func convertV18V19(cfg *Configuration) { + // Triggers a database tweak + cfg.Version = 19 +} + func convertV17V18(cfg *Configuration) { // Do channel selection for existing users. Those who have auto upgrades // and usage reporting on default to the candidate channel. Others get diff --git a/lib/config/config_test.go b/lib/config/config_test.go index e7a60ded0..a104a06bf 100644 --- a/lib/config/config_test.go +++ b/lib/config/config_test.go @@ -54,7 +54,6 @@ func TestDefaultValues(t *testing.T) { KeepTemporariesH: 24, CacheIgnoredFiles: false, ProgressUpdateIntervalS: 5, - SymlinksEnabled: true, LimitBandwidthInLan: false, MinHomeDiskFreePct: 1, URURL: "https://data.syncthing.net/newdata", @@ -191,7 +190,6 @@ func TestOverriddenValues(t *testing.T) { KeepTemporariesH: 48, CacheIgnoredFiles: true, ProgressUpdateIntervalS: 10, - SymlinksEnabled: false, LimitBandwidthInLan: true, MinHomeDiskFreePct: 5.2, URURL: "https://localhost/newdata", diff --git a/lib/config/optionsconfiguration.go b/lib/config/optionsconfiguration.go index 2663570a1..51da0cfa2 100644 --- a/lib/config/optionsconfiguration.go +++ b/lib/config/optionsconfiguration.go @@ -122,7 +122,6 @@ type OptionsConfiguration struct { KeepTemporariesH int `xml:"keepTemporariesH" json:"keepTemporariesH" default:"24"` // 0 for off CacheIgnoredFiles bool `xml:"cacheIgnoredFiles" json:"cacheIgnoredFiles" default:"false"` ProgressUpdateIntervalS int `xml:"progressUpdateIntervalS" json:"progressUpdateIntervalS" default:"5"` - SymlinksEnabled bool `xml:"symlinksEnabled" json:"symlinksEnabled" default:"true"` LimitBandwidthInLan bool `xml:"limitBandwidthInLan" json:"limitBandwidthInLan" default:"false"` MinHomeDiskFreePct float64 `xml:"minHomeDiskFreePct" json:"minHomeDiskFreePct" default:"1"` ReleasesURL string `xml:"releasesURL" json:"releasesURL" default:"https://upgrades.syncthing.net/meta.json"` diff --git a/lib/config/testdata/v19.xml b/lib/config/testdata/v19.xml new file mode 100644 index 000000000..29d17601c --- /dev/null +++ b/lib/config/testdata/v19.xml @@ -0,0 +1,15 @@ + + + + + 1 + -1 + true + + +
tcp://a
+
+ +
tcp://b
+
+
diff --git a/lib/db/leveldb_dbinstance.go b/lib/db/leveldb_dbinstance.go index ffc3d5d30..84e92f0c0 100644 --- a/lib/db/leveldb_dbinstance.go +++ b/lib/db/leveldb_dbinstance.go @@ -618,6 +618,41 @@ func (db *Instance) checkGlobals(folder []byte, globalSize *sizeTracker) { l.Debugf("db check completed for %q", folder) } +// ConvertSymlinkTypes should be run once only on an old database. It +// changes SYMLINK_FILE and SYMLINK_DIRECTORY types to the current SYMLINK +// type (previously SYMLINK_UNKNOWN). It does this for all devices, both +// local and remote, and does not reset delta indexes. It shouldn't really +// matter what the symlink type is, but this cleans it up for a possible +// future when SYMLINK_FILE and SYMLINK_DIRECTORY are no longer understood. +func (db *Instance) ConvertSymlinkTypes() { + t := db.newReadWriteTransaction() + defer t.close() + + dbi := t.NewIterator(util.BytesPrefix([]byte{KeyTypeDevice}), nil) + defer dbi.Release() + + conv := 0 + for dbi.Next() { + var f protocol.FileInfo + if err := f.Unmarshal(dbi.Value()); err != nil { + // probably can't happen + continue + } + if f.Type == protocol.FileInfoTypeDeprecatedSymlinkDirectory || f.Type == protocol.FileInfoTypeDeprecatedSymlinkFile { + f.Type = protocol.FileInfoTypeSymlink + bs, err := f.Marshal() + if err != nil { + panic("can't happen: " + err.Error()) + } + t.Put(dbi.Key(), bs) + t.checkFlush() + conv++ + } + } + + l.Infof("Updated symlink type for %d index entries", conv) +} + // deviceKey returns a byte slice encoding the following information: // keyTypeDevice (1 byte) // folder (4 bytes) diff --git a/lib/db/structs.go b/lib/db/structs.go index 7d8c54681..6ecc7afdf 100644 --- a/lib/db/structs.go +++ b/lib/db/structs.go @@ -35,7 +35,7 @@ func (f FileInfoTruncated) IsDirectory() bool { func (f FileInfoTruncated) IsSymlink() bool { switch f.Type { - case protocol.FileInfoTypeSymlinkDirectory, protocol.FileInfoTypeSymlinkFile, protocol.FileInfoTypeSymlinkUnknown: + case protocol.FileInfoTypeSymlink, protocol.FileInfoTypeDeprecatedSymlinkDirectory, protocol.FileInfoTypeDeprecatedSymlinkFile: return true default: return false diff --git a/lib/fs/basicfs_symlink_unix.go b/lib/fs/basicfs_symlink_unix.go index ee21c7cec..44ecf6bb8 100644 --- a/lib/fs/basicfs_symlink_unix.go +++ b/lib/fs/basicfs_symlink_unix.go @@ -20,24 +20,10 @@ func (BasicFilesystem) SymlinksSupported() bool { return symlinksSupported } -func (BasicFilesystem) CreateSymlink(name, target string, _ LinkTargetType) error { +func (BasicFilesystem) CreateSymlink(name, target string) error { return os.Symlink(target, name) } -func (BasicFilesystem) ChangeSymlinkType(_ string, _ LinkTargetType) error { - return nil -} - -func (BasicFilesystem) ReadSymlink(path string) (string, LinkTargetType, error) { - tt := LinkTargetUnknown - if stat, err := os.Stat(path); err == nil { - if stat.IsDir() { - tt = LinkTargetDirectory - } else { - tt = LinkTargetFile - } - } - - path, err := os.Readlink(path) - return path, tt, err +func (BasicFilesystem) ReadSymlink(path string) (string, error) { + return os.Readlink(path) } diff --git a/lib/fs/basicfs_symlink_windows.go b/lib/fs/basicfs_symlink_windows.go index e4c3a854a..a1299048c 100644 --- a/lib/fs/basicfs_symlink_windows.go +++ b/lib/fs/basicfs_symlink_windows.go @@ -8,188 +8,20 @@ package fs -import ( - "os" - "path/filepath" +import "errors" - "github.com/syncthing/syncthing/lib/osutil" +var errNotSupported = errors.New("symlinks not supported") - "syscall" - "unicode/utf16" - "unsafe" -) - -const ( - win32FsctlGetReparsePoint = 0x900a8 - win32FileFlagOpenReparsePoint = 0x00200000 - win32SymbolicLinkFlagDirectory = 0x1 -) - -var ( - modkernel32 = syscall.NewLazyDLL("kernel32.dll") - procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") - procCreateSymbolicLink = modkernel32.NewProc("CreateSymbolicLinkW") - symlinksSupported = false -) - -func init() { - defer func() { - if err := recover(); err != nil { - // Ensure that the supported flag is disabled when we hit an - // error, even though it should already be. Also, silently swallow - // the error since it's fine for a system not to support symlinks. - symlinksSupported = false - } - }() - - // Needs administrator privileges. - // Let's check that everything works. - // This could be done more officially: - // http://stackoverflow.com/questions/2094663/determine-if-windows-process-has-privilege-to-create-symbolic-link - // But I don't want to define 10 more structs just to look this up. - base := os.TempDir() - path := filepath.Join(base, "symlinktest") - defer os.Remove(path) - - err := DefaultFilesystem.CreateSymlink(path, base, LinkTargetDirectory) - if err != nil { - return - } - - stat, err := osutil.Lstat(path) - if err != nil || stat.Mode()&os.ModeSymlink == 0 { - return - } - - target, tt, err := DefaultFilesystem.ReadSymlink(path) - if err != nil || osutil.NativeFilename(target) != base || tt != LinkTargetDirectory { - return - } - symlinksSupported = true -} - -func DisableSymlinks() { - symlinksSupported = false -} +func DisableSymlinks() {} func (BasicFilesystem) SymlinksSupported() bool { - return symlinksSupported + return false } -func (BasicFilesystem) ReadSymlink(path string) (string, LinkTargetType, error) { - ptr, err := syscall.UTF16PtrFromString(path) - if err != nil { - return "", LinkTargetUnknown, err - } - handle, err := syscall.CreateFile(ptr, 0, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS|win32FileFlagOpenReparsePoint, 0) - if err != nil || handle == syscall.InvalidHandle { - return "", LinkTargetUnknown, err - } - defer syscall.Close(handle) - var ret uint16 - var data reparseData - - r1, _, err := syscall.Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), win32FsctlGetReparsePoint, 0, 0, uintptr(unsafe.Pointer(&data)), unsafe.Sizeof(data), uintptr(unsafe.Pointer(&ret)), 0, 0) - if r1 == 0 { - return "", LinkTargetUnknown, err - } - - tt := LinkTargetUnknown - if attr, err := syscall.GetFileAttributes(ptr); err == nil { - if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - tt = LinkTargetDirectory - } else { - tt = LinkTargetFile - } - } - - return osutil.NormalizedFilename(data.printName()), tt, nil +func (BasicFilesystem) ReadSymlink(path string) (string, error) { + return "", errNotSupported } -func (BasicFilesystem) CreateSymlink(path, target string, tt LinkTargetType) error { - srcp, err := syscall.UTF16PtrFromString(path) - if err != nil { - return err - } - - trgp, err := syscall.UTF16PtrFromString(osutil.NativeFilename(target)) - if err != nil { - return err - } - - // Sadly for Windows we need to specify the type of the symlink, - // whether it's a directory symlink or a file symlink. - // If the flags doesn't reveal the target type, try to evaluate it - // ourselves, and worst case default to the symlink pointing to a file. - mode := 0 - if tt == LinkTargetUnknown { - path := target - if !filepath.IsAbs(target) { - path = filepath.Join(filepath.Dir(path), target) - } - - stat, err := os.Stat(path) - if err == nil && stat.IsDir() { - mode = win32SymbolicLinkFlagDirectory - } - } else if tt == LinkTargetDirectory { - mode = win32SymbolicLinkFlagDirectory - } - - r0, _, err := syscall.Syscall(procCreateSymbolicLink.Addr(), 3, uintptr(unsafe.Pointer(srcp)), uintptr(unsafe.Pointer(trgp)), uintptr(mode)) - if r0 == 1 { - return nil - } - return err -} - -func (fs BasicFilesystem) ChangeSymlinkType(path string, tt LinkTargetType) error { - target, existingTargetType, err := fs.ReadSymlink(path) - if err != nil { - return err - } - // If it's the same type, nothing to do. - if tt == existingTargetType { - return nil - } - - // If the actual type is unknown, but the new type is file, nothing to do - if existingTargetType == LinkTargetUnknown && tt != LinkTargetDirectory { - return nil - } - return osutil.InWritableDir(func(path string) error { - // It should be a symlink as well hence no need to change permissions on - // the file. - os.Remove(path) - return fs.CreateSymlink(path, target, tt) - }, path) -} - -type reparseData struct { - reparseTag uint32 - reparseDataLength uint16 - reserved uint16 - substitueNameOffset uint16 - substitueNameLength uint16 - printNameOffset uint16 - printNameLength uint16 - flags uint32 - // substituteName - 264 widechars max = 528 bytes - // printName - 260 widechars max = 520 bytes - // = 1048 bytes total - buffer [1048 / 2]uint16 -} - -func (r *reparseData) printName() string { - // offset and length are in bytes but we're indexing a []uint16 - offset := r.printNameOffset / 2 - length := r.printNameLength / 2 - return string(utf16.Decode(r.buffer[offset : offset+length])) -} - -func (r *reparseData) substituteName() string { - // offset and length are in bytes but we're indexing a []uint16 - offset := r.substitueNameOffset / 2 - length := r.substitueNameLength / 2 - return string(utf16.Decode(r.buffer[offset : offset+length])) +func (BasicFilesystem) CreateSymlink(path, target string) error { + return errNotSupported } diff --git a/lib/fs/filesystem.go b/lib/fs/filesystem.go index cd96e8804..1c94add4f 100644 --- a/lib/fs/filesystem.go +++ b/lib/fs/filesystem.go @@ -12,26 +12,17 @@ import ( "time" ) -type LinkTargetType int - -const ( - LinkTargetFile LinkTargetType = iota - LinkTargetDirectory - LinkTargetUnknown -) - // The Filesystem interface abstracts access to the file system. type Filesystem interface { - ChangeSymlinkType(name string, tt LinkTargetType) error Chmod(name string, mode FileMode) error Chtimes(name string, atime time.Time, mtime time.Time) error Create(name string) (File, error) - CreateSymlink(name, target string, tt LinkTargetType) error + CreateSymlink(name, target string) error DirNames(name string) ([]string, error) Lstat(name string) (FileInfo, error) Mkdir(name string, perm FileMode) error Open(name string) (File, error) - ReadSymlink(name string) (string, LinkTargetType, error) + ReadSymlink(name string) (string, error) Remove(name string) error Rename(oldname, newname string) error Stat(name string) (FileInfo, error) diff --git a/lib/model/model.go b/lib/model/model.go index 5070e63f1..8f0f8e359 100644 --- a/lib/model/model.go +++ b/lib/model/model.go @@ -20,7 +20,6 @@ import ( "runtime" "sort" "strings" - stdsync "sync" "time" "github.com/syncthing/syncthing/lib/config" @@ -33,7 +32,6 @@ import ( "github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/scanner" "github.com/syncthing/syncthing/lib/stats" - "github.com/syncthing/syncthing/lib/symlinks" "github.com/syncthing/syncthing/lib/sync" "github.com/syncthing/syncthing/lib/upgrade" "github.com/syncthing/syncthing/lib/versioner" @@ -105,7 +103,6 @@ type Model struct { type folderFactory func(*Model, config.FolderConfiguration, versioner.Versioner, *fs.MtimeFS) service var ( - symlinkWarning = stdsync.Once{} folderFactories = make(map[config.FolderType]folderFactory, 0) ) @@ -116,7 +113,6 @@ var ( errFolderMarkerMissing = errors.New("folder marker missing") errHomeDiskNoSpace = errors.New("home disk has insufficient free space") errFolderNoSpace = errors.New("folder has insufficient free space") - errUnsupportedSymlink = errors.New("symlink not supported") errInvalidFilename = errors.New("filename is invalid") errDeviceUnknown = errors.New("unknown device") errDevicePaused = errors.New("device is paused") @@ -1879,9 +1875,8 @@ func (m *Model) internalScanFolderSubdirs(folder string, subDirs []string) error } switch { - case !f.IsInvalid() && (ignores.Match(f.Name).IsIgnored() || symlinkInvalid(folder, f)): - // File was valid at last pass but has been ignored or is an - // unsupported symlink. Set invalid bit. + case !f.IsInvalid() && ignores.Match(f.Name).IsIgnored(): + // File was valid at last pass but has been ignored. Set invalid bit. l.Debugln("setting invalid bit on ignored", f) nf := protocol.FileInfo{ Name: f.Name, @@ -2490,26 +2485,6 @@ func mapDeviceConfigs(devices []config.DeviceConfiguration) map[protocol.DeviceI return m } -func symlinkInvalid(folder string, fi db.FileIntf) bool { - if !symlinks.Supported && fi.IsSymlink() && !fi.IsInvalid() && !fi.IsDeleted() { - symlinkWarning.Do(func() { - l.Warnln("Symlinks are disabled, unsupported or require Administrator privileges. This might cause your folder to appear out of sync.") - }) - - // Need to type switch for the concrete type to be able to access fields... - var name string - switch fi := fi.(type) { - case protocol.FileInfo: - name = fi.Name - case db.FileInfoTruncated: - name = fi.Name - } - l.Infoln("Unsupported symlink", name, "in folder", folder) - return true - } - return false -} - // Skips `skip` elements and retrieves up to `get` elements from a given slice. // Returns the resulting slice, plus how much elements are left to skip or // copy to satisfy the values which were provided, given the slice is not diff --git a/lib/model/progressemitter_test.go b/lib/model/progressemitter_test.go index 00ba1d154..2f5d76502 100644 --- a/lib/model/progressemitter_test.go +++ b/lib/model/progressemitter_test.go @@ -359,7 +359,7 @@ func TestSendDownloadProgressMessages(t *testing.T) { file: protocol.FileInfo{ Name: "state6", Version: v1, - Type: protocol.FileInfoTypeSymlinkUnknown, + Type: protocol.FileInfoTypeSymlink, }, mut: sync.NewRWMutex(), available: []int32{1, 2, 3}, diff --git a/lib/model/requests_test.go b/lib/model/requests_test.go index 30b0efc6a..b39a67c53 100644 --- a/lib/model/requests_test.go +++ b/lib/model/requests_test.go @@ -89,7 +89,7 @@ func TestSymlinkTraversalRead(t *testing.T) { // Send an update for the symlink, wait for it to sync and be reported back. contents := []byte("..") - fc.addFile("symlink", 0644, protocol.FileInfoTypeSymlinkDirectory, contents) + fc.addFile("symlink", 0644, protocol.FileInfoTypeSymlink, contents) fc.sendIndexUpdate() <-done @@ -142,7 +142,7 @@ func TestSymlinkTraversalWrite(t *testing.T) { // Send an update for the symlink, wait for it to sync and be reported back. contents := []byte("..") - fc.addFile("symlink", 0644, protocol.FileInfoTypeSymlinkDirectory, contents) + fc.addFile("symlink", 0644, protocol.FileInfoTypeSymlink, contents) fc.sendIndexUpdate() <-done @@ -152,7 +152,7 @@ func TestSymlinkTraversalWrite(t *testing.T) { contents = []byte("testdata testdata\n") fc.addFile("symlink/testfile", 0644, protocol.FileInfoTypeFile, contents) fc.addFile("symlink/testdir", 0644, protocol.FileInfoTypeDirectory, contents) - fc.addFile("symlink/testsyml", 0644, protocol.FileInfoTypeSymlinkFile, contents) + fc.addFile("symlink/testsyml", 0644, protocol.FileInfoTypeSymlink, contents) fc.sendIndexUpdate() select { @@ -191,7 +191,7 @@ func TestRequestCreateTmpSymlink(t *testing.T) { fc.mut.Unlock() // Send an update for the test file, wait for it to sync and be reported back. - fc.addFile(".syncthing.testlink.tmp", 0644, protocol.FileInfoTypeSymlinkDirectory, []byte("..")) + fc.addFile(".syncthing.testlink.tmp", 0644, protocol.FileInfoTypeSymlink, []byte("..")) fc.sendIndexUpdate() select { diff --git a/lib/model/rwfolder.go b/lib/model/rwfolder.go index fb8d249d0..1eb469f99 100644 --- a/lib/model/rwfolder.go +++ b/lib/model/rwfolder.go @@ -25,7 +25,6 @@ import ( "github.com/syncthing/syncthing/lib/osutil" "github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/scanner" - "github.com/syncthing/syncthing/lib/symlinks" "github.com/syncthing/syncthing/lib/sync" "github.com/syncthing/syncthing/lib/versioner" "github.com/syncthing/syncthing/lib/weakhash" @@ -741,15 +740,10 @@ func (f *sendReceiveFolder) handleSymlink(file protocol.FileInfo) { } } - tt := symlinks.TargetFile - if file.IsDirectory() { - tt = symlinks.TargetDirectory - } - // We declare a function that acts on only the path name, so // we can pass it to InWritableDir. createLink := func(path string) error { - return symlinks.Create(path, file.SymlinkTarget, tt) + return os.Symlink(file.SymlinkTarget, path) } if err = osutil.InWritableDir(createLink, realName); err == nil { @@ -1765,9 +1759,6 @@ func fileValid(file db.FileIntf) error { // We don't care about file validity if we're not supposed to have it return nil - case !symlinks.Supported && file.IsSymlink(): - return errUnsupportedSymlink - case runtime.GOOS == "windows" && windowsInvalidFilename(file.FileName()): return errInvalidFilename } diff --git a/lib/osutil/traversessymlink_test.go b/lib/osutil/traversessymlink_test.go index 6a58663ce..9c4b7cb40 100644 --- a/lib/osutil/traversessymlink_test.go +++ b/lib/osutil/traversessymlink_test.go @@ -4,6 +4,8 @@ // 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 !windows + package osutil_test import ( @@ -11,19 +13,13 @@ import ( "testing" "github.com/syncthing/syncthing/lib/osutil" - "github.com/syncthing/syncthing/lib/symlinks" ) func TestTraversesSymlink(t *testing.T) { - if !symlinks.Supported { - t.Skip("pointless test") - return - } - os.RemoveAll("testdata") defer os.RemoveAll("testdata") os.MkdirAll("testdata/a/b/c", 0755) - symlinks.Create("testdata/a/l", "b", symlinks.TargetDirectory) + os.Symlink("b", "testdata/a/l") // a/l -> b, so a/l/c should resolve by normal stat info, err := osutil.Lstat("testdata/a/l/c") diff --git a/lib/protocol/bep.pb.go b/lib/protocol/bep.pb.go index fd973b3a1..23c613a78 100644 --- a/lib/protocol/bep.pb.go +++ b/lib/protocol/bep.pb.go @@ -134,11 +134,11 @@ func (Compression) EnumDescriptor() ([]byte, []int) { return fileDescriptorBep, type FileInfoType int32 const ( - FileInfoTypeFile FileInfoType = 0 - FileInfoTypeDirectory FileInfoType = 1 - FileInfoTypeSymlinkFile FileInfoType = 2 - FileInfoTypeSymlinkDirectory FileInfoType = 3 - FileInfoTypeSymlinkUnknown FileInfoType = 4 + FileInfoTypeFile FileInfoType = 0 + FileInfoTypeDirectory FileInfoType = 1 + FileInfoTypeDeprecatedSymlinkFile FileInfoType = 2 + FileInfoTypeDeprecatedSymlinkDirectory FileInfoType = 3 + FileInfoTypeSymlink FileInfoType = 4 ) var FileInfoType_name = map[int32]string{ @@ -146,14 +146,14 @@ var FileInfoType_name = map[int32]string{ 1: "DIRECTORY", 2: "SYMLINK_FILE", 3: "SYMLINK_DIRECTORY", - 4: "SYMLINK_UNKNOWN", + 4: "SYMLINK", } var FileInfoType_value = map[string]int32{ "FILE": 0, "DIRECTORY": 1, "SYMLINK_FILE": 2, "SYMLINK_DIRECTORY": 3, - "SYMLINK_UNKNOWN": 4, + "SYMLINK": 4, } func (x FileInfoType) String() string { @@ -4165,114 +4165,114 @@ var ( func init() { proto.RegisterFile("bep.proto", fileDescriptorBep) } var fileDescriptorBep = []byte{ - // 1732 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcd, 0x73, 0xdb, 0xc6, - 0x15, 0xe7, 0x07, 0xf8, 0xf5, 0x48, 0xc9, 0xd0, 0xda, 0x56, 0x50, 0x58, 0xa1, 0x10, 0x26, 0x6e, - 0x14, 0x4d, 0xe3, 0xb8, 0x71, 0xda, 0xcc, 0x74, 0xda, 0xce, 0xf0, 0x03, 0x92, 0x39, 0xa1, 0x41, - 0x76, 0x49, 0xd9, 0x75, 0x0e, 0xc5, 0x80, 0xc4, 0x92, 0xc2, 0x08, 0xc4, 0xb2, 0x00, 0x28, 0x9b, - 0xfd, 0x13, 0xf8, 0x17, 0xf4, 0xc2, 0x99, 0xcc, 0xf4, 0xd4, 0x7b, 0xff, 0x08, 0x1f, 0x33, 0x3d, - 0xf4, 0xd0, 0x83, 0xa7, 0x51, 0x2f, 0x3d, 0xf6, 0xd2, 0x53, 0x2f, 0x9d, 0xdd, 0x05, 0x48, 0x50, - 0x92, 0x3b, 0x39, 0xe4, 0x84, 0x7d, 0xef, 0xfd, 0xf6, 0xed, 0xbe, 0x8f, 0xdf, 0x5b, 0x40, 0x69, - 0x48, 0x66, 0x8f, 0x66, 0x3e, 0x0d, 0x29, 0x2a, 0xf2, 0xcf, 0x88, 0xba, 0xea, 0xa7, 0x13, 0x27, - 0x3c, 0x9f, 0x0f, 0x1f, 0x8d, 0xe8, 0xf4, 0xb3, 0x09, 0x9d, 0xd0, 0xcf, 0xb8, 0x65, 0x38, 0x1f, - 0x73, 0x89, 0x0b, 0x7c, 0x25, 0x36, 0xd6, 0x66, 0x90, 0x7b, 0x4a, 0x5c, 0x97, 0xa2, 0x43, 0x28, - 0xdb, 0xe4, 0xd2, 0x19, 0x11, 0xd3, 0xb3, 0xa6, 0x44, 0x49, 0x6b, 0xe9, 0xa3, 0x12, 0x06, 0xa1, - 0x32, 0xac, 0x29, 0x61, 0x80, 0x91, 0xeb, 0x10, 0x2f, 0x14, 0x80, 0x8c, 0x00, 0x08, 0x15, 0x07, - 0x3c, 0x84, 0xdd, 0x08, 0x70, 0x49, 0xfc, 0xc0, 0xa1, 0x9e, 0x92, 0xe5, 0x98, 0x1d, 0xa1, 0x7d, - 0x2e, 0x94, 0xb5, 0x00, 0xf2, 0x4f, 0x89, 0x65, 0x13, 0x1f, 0x7d, 0x02, 0x52, 0xb8, 0x98, 0x89, - 0xb3, 0x76, 0x3f, 0xbf, 0xff, 0x28, 0x8e, 0xe1, 0xd1, 0x33, 0x12, 0x04, 0xd6, 0x84, 0x0c, 0x16, - 0x33, 0x82, 0x39, 0x04, 0xfd, 0x1a, 0xca, 0x23, 0x3a, 0x9d, 0xf9, 0x24, 0xe0, 0x8e, 0x33, 0x7c, - 0xc7, 0xc1, 0x8d, 0x1d, 0xcd, 0x0d, 0x06, 0x27, 0x37, 0xd4, 0xea, 0xb0, 0xd3, 0x74, 0xe7, 0x41, - 0x48, 0xfc, 0x26, 0xf5, 0xc6, 0xce, 0x04, 0x3d, 0x86, 0xc2, 0x98, 0xba, 0x36, 0xf1, 0x03, 0x25, - 0xad, 0x65, 0x8f, 0xca, 0x9f, 0xcb, 0x1b, 0x67, 0x27, 0xdc, 0xd0, 0x90, 0xde, 0xbc, 0x3d, 0x4c, - 0xe1, 0x18, 0x56, 0xfb, 0x53, 0x06, 0xf2, 0xc2, 0x82, 0xf6, 0x21, 0xe3, 0xd8, 0x22, 0x45, 0x8d, - 0xfc, 0xd5, 0xdb, 0xc3, 0x4c, 0xbb, 0x85, 0x33, 0x8e, 0x8d, 0xee, 0x41, 0xce, 0xb5, 0x86, 0xc4, - 0x8d, 0x92, 0x23, 0x04, 0xf4, 0x00, 0x4a, 0x3e, 0xb1, 0x6c, 0x93, 0x7a, 0xee, 0x82, 0xa7, 0xa4, - 0x88, 0x8b, 0x4c, 0xd1, 0xf5, 0xdc, 0x05, 0xfa, 0x14, 0x90, 0x33, 0xf1, 0xa8, 0x4f, 0xcc, 0x19, - 0xf1, 0xa7, 0x0e, 0xbf, 0x6d, 0xa0, 0x48, 0x1c, 0xb5, 0x27, 0x2c, 0xbd, 0x8d, 0x01, 0x7d, 0x08, - 0x3b, 0x11, 0xdc, 0x26, 0x2e, 0x09, 0x89, 0x92, 0xe3, 0xc8, 0x8a, 0x50, 0xb6, 0xb8, 0x0e, 0x3d, - 0x86, 0x7b, 0xb6, 0x13, 0x58, 0x43, 0x97, 0x98, 0x21, 0x99, 0xce, 0x4c, 0xc7, 0xb3, 0xc9, 0x6b, - 0x12, 0x28, 0x79, 0x8e, 0x45, 0x91, 0x6d, 0x40, 0xa6, 0xb3, 0xb6, 0xb0, 0xa0, 0x7d, 0xc8, 0xcf, - 0xac, 0x79, 0x40, 0x6c, 0xa5, 0xc0, 0x31, 0x91, 0xc4, 0xb2, 0x24, 0x3a, 0x20, 0x50, 0xe4, 0xeb, - 0x59, 0x6a, 0x71, 0x43, 0x9c, 0xa5, 0x08, 0x56, 0xfb, 0x77, 0x06, 0xf2, 0xc2, 0x82, 0x7e, 0xbc, - 0xce, 0x52, 0xa5, 0xb1, 0xcf, 0x50, 0x7f, 0x7f, 0x7b, 0x58, 0x14, 0xb6, 0x76, 0x2b, 0x91, 0x35, - 0x04, 0x52, 0xa2, 0xa3, 0xf8, 0x1a, 0x1d, 0x40, 0xc9, 0xb2, 0x6d, 0x56, 0x3d, 0x12, 0x28, 0x59, - 0x2d, 0x7b, 0x54, 0xc2, 0x1b, 0x05, 0xfa, 0x72, 0xbb, 0x1b, 0xa4, 0xeb, 0xfd, 0xf3, 0xae, 0x36, - 0x60, 0xa5, 0x18, 0x11, 0x3f, 0xea, 0xe0, 0x1c, 0x3f, 0xaf, 0xc8, 0x14, 0xbc, 0x7f, 0x3f, 0x80, - 0xca, 0xd4, 0x7a, 0x6d, 0x06, 0xe4, 0xf7, 0x73, 0xe2, 0x8d, 0x08, 0x4f, 0x57, 0x16, 0x97, 0xa7, - 0xd6, 0xeb, 0x7e, 0xa4, 0x42, 0x55, 0x00, 0xc7, 0x0b, 0x7d, 0x6a, 0xcf, 0x47, 0xc4, 0x8f, 0x72, - 0x95, 0xd0, 0xa0, 0x9f, 0x41, 0x91, 0x27, 0xdb, 0x74, 0x6c, 0xa5, 0xa8, 0xa5, 0x8f, 0xa4, 0x86, - 0x1a, 0x05, 0x5e, 0xe0, 0xa9, 0xe6, 0x71, 0xc7, 0x4b, 0x5c, 0xe0, 0xd8, 0xb6, 0x8d, 0x7e, 0x09, - 0x6a, 0x70, 0xe1, 0xb0, 0x42, 0x09, 0x4f, 0xa1, 0x43, 0x3d, 0xd3, 0x27, 0x53, 0x7a, 0x69, 0xb9, - 0x81, 0x52, 0xe2, 0xc7, 0x28, 0x0c, 0xd1, 0x4e, 0x00, 0x70, 0x64, 0xaf, 0x75, 0x21, 0xc7, 0x3d, - 0xb2, 0x2a, 0x8a, 0x66, 0x8d, 0xd8, 0x1b, 0x49, 0xe8, 0x11, 0xe4, 0xc6, 0x8e, 0x4b, 0x02, 0x25, - 0xc3, 0x6b, 0x88, 0x12, 0x9d, 0xee, 0xb8, 0xa4, 0xed, 0x8d, 0x69, 0x54, 0x45, 0x01, 0xab, 0x9d, - 0x41, 0x99, 0x3b, 0x3c, 0x9b, 0xd9, 0x56, 0x48, 0x7e, 0x30, 0xb7, 0xff, 0xcd, 0x42, 0x31, 0xb6, - 0xac, 0x8b, 0x9e, 0x4e, 0x14, 0xfd, 0x38, 0x9a, 0x07, 0x82, 0xdd, 0xfb, 0x37, 0xfd, 0x25, 0x06, - 0x02, 0x02, 0x29, 0x70, 0xfe, 0x40, 0x38, 0x9f, 0xb2, 0x98, 0xaf, 0x91, 0x06, 0xe5, 0xeb, 0x24, - 0xda, 0xc1, 0x49, 0x15, 0x7a, 0x1f, 0x60, 0x4a, 0x6d, 0x67, 0xec, 0x10, 0xdb, 0x0c, 0x78, 0x03, - 0x64, 0x71, 0x29, 0xd6, 0xf4, 0x91, 0xc2, 0xda, 0x9d, 0x51, 0xc8, 0x8e, 0xb8, 0x12, 0x8b, 0xcc, - 0xe2, 0x78, 0x97, 0x96, 0xeb, 0xc4, 0x0c, 0x89, 0x45, 0x36, 0xf5, 0x3c, 0xba, 0x45, 0xde, 0x22, - 0x07, 0xec, 0x78, 0x34, 0x49, 0xdc, 0xc7, 0x50, 0x88, 0xa7, 0x22, 0xab, 0xe7, 0x16, 0x93, 0x9e, - 0x93, 0x51, 0x48, 0xd7, 0xf3, 0x26, 0x82, 0x21, 0x15, 0x8a, 0xeb, 0x56, 0x04, 0x7e, 0xd3, 0xb5, - 0xcc, 0x66, 0xf1, 0x3a, 0x0e, 0x2f, 0x50, 0xca, 0x5a, 0xfa, 0x28, 0x87, 0xd7, 0xa1, 0x19, 0xec, - 0xb8, 0x0d, 0x60, 0xb8, 0x50, 0x2a, 0xbc, 0x17, 0xef, 0xc4, 0xbd, 0xd8, 0x3f, 0xa7, 0x7e, 0xd8, - 0x6e, 0x6d, 0x76, 0x34, 0x16, 0xe8, 0xa7, 0x90, 0x6f, 0xb8, 0x74, 0x74, 0x11, 0x33, 0xfd, 0xee, - 0xe6, 0x7e, 0x5c, 0x9f, 0xa8, 0x67, 0x04, 0x64, 0xa1, 0x07, 0x8b, 0xa9, 0xeb, 0x78, 0x17, 0x66, - 0x68, 0xf9, 0x13, 0x12, 0x2a, 0x7b, 0x62, 0xe0, 0x47, 0xda, 0x01, 0x57, 0xfe, 0x42, 0xfa, 0xe3, - 0x37, 0x87, 0xa9, 0x9a, 0x07, 0xa5, 0xb5, 0x1f, 0xd6, 0x52, 0x74, 0x3c, 0x0e, 0x48, 0xc8, 0xeb, - 0x9f, 0xc5, 0x91, 0xb4, 0xae, 0x6a, 0x86, 0x07, 0x24, 0xaa, 0x8a, 0x40, 0x3a, 0xb7, 0x82, 0x73, - 0x5e, 0xe9, 0x0a, 0xe6, 0x6b, 0xc6, 0xe3, 0x57, 0xc4, 0xba, 0x30, 0xb9, 0x41, 0xd4, 0xb9, 0xc8, - 0x14, 0x4f, 0xad, 0xe0, 0x3c, 0x3a, 0xef, 0x57, 0x90, 0x17, 0x79, 0x45, 0x4f, 0xa0, 0x38, 0xa2, - 0x73, 0x2f, 0xdc, 0xcc, 0xfa, 0xbd, 0xe4, 0xa8, 0xe0, 0x96, 0x28, 0xb2, 0x35, 0xb0, 0x76, 0x02, - 0x85, 0xc8, 0x84, 0x1e, 0xae, 0xe7, 0x98, 0xd4, 0xb8, 0x7f, 0x2d, 0x85, 0xdb, 0xc3, 0xff, 0xd2, - 0x72, 0xe7, 0xe2, 0xf2, 0x12, 0x16, 0x42, 0xed, 0x2f, 0x69, 0x28, 0x60, 0x56, 0xb6, 0x20, 0x4c, - 0x3c, 0x1b, 0xb9, 0xad, 0x67, 0x63, 0x43, 0xb0, 0xcc, 0x16, 0xc1, 0x62, 0x8e, 0x64, 0x13, 0x1c, - 0xd9, 0x64, 0x4e, 0xba, 0x35, 0x73, 0xb9, 0x5b, 0x32, 0x97, 0x4f, 0x64, 0xee, 0x21, 0xec, 0x8e, - 0x7d, 0x3a, 0xe5, 0x0f, 0x03, 0xf5, 0x2d, 0x7f, 0x11, 0xf5, 0xf3, 0x0e, 0xd3, 0x0e, 0x62, 0x65, - 0xcd, 0x84, 0x22, 0x26, 0xc1, 0x8c, 0x7a, 0x01, 0x79, 0xe7, 0xb5, 0x11, 0x48, 0xb6, 0x15, 0x5a, - 0xfc, 0xd2, 0x15, 0xcc, 0xd7, 0xe8, 0x63, 0x90, 0x46, 0xd4, 0x16, 0x57, 0xde, 0x4d, 0xf6, 0x90, - 0xee, 0xfb, 0xd4, 0x6f, 0x52, 0x9b, 0x60, 0x0e, 0xa8, 0xcd, 0x40, 0x6e, 0xd1, 0x57, 0x9e, 0x4b, - 0x2d, 0xbb, 0xe7, 0xd3, 0x09, 0x1b, 0xd0, 0xef, 0x1c, 0x34, 0x2d, 0x28, 0xcc, 0xf9, 0x28, 0x8a, - 0x47, 0xcd, 0x47, 0xdb, 0xa3, 0xe1, 0xba, 0x23, 0x31, 0xb7, 0x62, 0x3e, 0x45, 0x5b, 0x6b, 0x7f, - 0x4b, 0x83, 0xfa, 0x6e, 0x34, 0x6a, 0x43, 0x59, 0x20, 0xcd, 0xc4, 0x3f, 0xc9, 0xd1, 0xf7, 0x39, - 0x88, 0x4f, 0x25, 0x98, 0xaf, 0xd7, 0xb7, 0x3e, 0x68, 0x09, 0xfe, 0x67, 0xbf, 0x1f, 0xff, 0x3f, - 0x86, 0x9d, 0x21, 0x23, 0xcc, 0xfa, 0xf9, 0x96, 0xb4, 0xec, 0x51, 0xae, 0x91, 0x91, 0x53, 0xb8, - 0x32, 0x14, 0x4c, 0xe2, 0xfa, 0x5a, 0x1e, 0xa4, 0x9e, 0xe3, 0x4d, 0x6a, 0x87, 0x90, 0x6b, 0xba, - 0x94, 0x17, 0x2c, 0xef, 0x13, 0x2b, 0xa0, 0x5e, 0x9c, 0x47, 0x21, 0x1d, 0xff, 0x35, 0x03, 0xe5, - 0xc4, 0xaf, 0x15, 0x7a, 0x0c, 0xbb, 0xcd, 0xce, 0x59, 0x7f, 0xa0, 0x63, 0xb3, 0xd9, 0x35, 0x4e, - 0xda, 0xa7, 0x72, 0x4a, 0x3d, 0x58, 0xae, 0x34, 0x65, 0xba, 0x01, 0x6d, 0xff, 0x35, 0x1d, 0x42, - 0xae, 0x6d, 0xb4, 0xf4, 0xdf, 0xca, 0x69, 0xf5, 0xde, 0x72, 0xa5, 0xc9, 0x09, 0xa0, 0x78, 0x82, - 0x7e, 0x02, 0x15, 0x0e, 0x30, 0xcf, 0x7a, 0xad, 0xfa, 0x40, 0x97, 0x33, 0xaa, 0xba, 0x5c, 0x69, - 0xfb, 0xd7, 0x71, 0x51, 0xce, 0x3f, 0x84, 0x02, 0xd6, 0x7f, 0x73, 0xa6, 0xf7, 0x07, 0x72, 0x56, - 0xdd, 0x5f, 0xae, 0x34, 0x94, 0x00, 0xc6, 0xac, 0x79, 0x08, 0x45, 0xac, 0xf7, 0x7b, 0x5d, 0xa3, - 0xaf, 0xcb, 0x92, 0xfa, 0xde, 0x72, 0xa5, 0xdd, 0xdd, 0x42, 0x45, 0x5d, 0xfa, 0x73, 0xd8, 0x6b, - 0x75, 0x5f, 0x18, 0x9d, 0x6e, 0xbd, 0x65, 0xf6, 0x70, 0xf7, 0x14, 0xeb, 0xfd, 0xbe, 0x9c, 0x53, - 0x0f, 0x97, 0x2b, 0xed, 0x41, 0x02, 0x7f, 0xa3, 0xe9, 0xde, 0x07, 0xa9, 0xd7, 0x36, 0x4e, 0xe5, - 0xbc, 0x7a, 0x77, 0xb9, 0xd2, 0xee, 0x24, 0xa0, 0x2c, 0xa9, 0x2c, 0xe2, 0x66, 0xa7, 0xdb, 0xd7, - 0xe5, 0xc2, 0x8d, 0x88, 0x79, 0xb2, 0x8f, 0x7f, 0x07, 0xe8, 0xe6, 0xcf, 0x27, 0xfa, 0x08, 0x24, - 0xa3, 0x6b, 0xe8, 0x72, 0x4a, 0xc4, 0x7f, 0x13, 0x61, 0x50, 0x8f, 0xa0, 0x1a, 0x64, 0x3b, 0x5f, - 0x7f, 0x21, 0xa7, 0xd5, 0x1f, 0x2d, 0x57, 0xda, 0xfd, 0x9b, 0xa0, 0xce, 0xd7, 0x5f, 0x1c, 0x53, - 0x28, 0x27, 0x1d, 0xd7, 0xa0, 0xf8, 0x4c, 0x1f, 0xd4, 0x5b, 0xf5, 0x41, 0x5d, 0x4e, 0x89, 0x2b, - 0xc5, 0xe6, 0x67, 0x24, 0xb4, 0x38, 0x09, 0x0f, 0x20, 0x67, 0xe8, 0xcf, 0x75, 0x2c, 0xa7, 0xd5, - 0xbd, 0xe5, 0x4a, 0xdb, 0x89, 0x01, 0x06, 0xb9, 0x24, 0x3e, 0xaa, 0x42, 0xbe, 0xde, 0x79, 0x51, - 0x7f, 0xd9, 0x97, 0x33, 0x2a, 0x5a, 0xae, 0xb4, 0xdd, 0xd8, 0x5c, 0x77, 0x5f, 0x59, 0x8b, 0xe0, - 0xf8, 0x3f, 0x69, 0xa8, 0x24, 0x1f, 0x5c, 0x54, 0x05, 0xe9, 0xa4, 0xdd, 0xd1, 0xe3, 0xe3, 0x92, - 0x36, 0xb6, 0x46, 0x47, 0x50, 0x6a, 0xb5, 0xb1, 0xde, 0x1c, 0x74, 0xf1, 0xcb, 0x38, 0x96, 0x24, - 0xa8, 0xe5, 0xf8, 0xbc, 0xc1, 0xd9, 0xcf, 0x6e, 0xa5, 0xff, 0xf2, 0x59, 0xa7, 0x6d, 0x7c, 0x65, - 0x72, 0x8f, 0x19, 0xf5, 0xc1, 0x72, 0xa5, 0xbd, 0x97, 0x04, 0xf7, 0xc5, 0xd3, 0xc1, 0x1d, 0x7f, - 0x09, 0x7b, 0x31, 0x7c, 0x73, 0x40, 0x56, 0xd5, 0x96, 0x2b, 0xed, 0xe0, 0x96, 0x3d, 0x9b, 0x73, - 0x9e, 0xc0, 0x9d, 0x78, 0xe3, 0x99, 0xf1, 0x95, 0xd1, 0x7d, 0x61, 0xc8, 0x92, 0x5a, 0x5d, 0xae, - 0x34, 0xf5, 0x96, 0x6d, 0x67, 0xde, 0x85, 0x47, 0x5f, 0x79, 0xc7, 0x7f, 0x4e, 0x43, 0x69, 0x3d, - 0xa5, 0x58, 0x9e, 0x8d, 0xae, 0xa9, 0x63, 0xdc, 0xc5, 0x71, 0xe0, 0x6b, 0xa3, 0x41, 0xf9, 0x12, - 0x7d, 0x00, 0x85, 0x53, 0xdd, 0xd0, 0x71, 0xbb, 0x19, 0xf3, 0x61, 0x0d, 0x39, 0x25, 0x1e, 0xf1, - 0x9d, 0x11, 0xfa, 0x04, 0x2a, 0x46, 0xd7, 0xec, 0x9f, 0x35, 0x9f, 0xc6, 0x11, 0xf3, 0x06, 0x4e, - 0xb8, 0xea, 0xcf, 0x47, 0xe7, 0x3c, 0xda, 0x63, 0x46, 0x9d, 0xe7, 0xf5, 0x4e, 0xbb, 0x25, 0xa0, - 0x59, 0x55, 0x59, 0xae, 0xb4, 0x7b, 0x6b, 0x68, 0x5b, 0xfc, 0x70, 0x30, 0xec, 0xb1, 0x0d, 0xd5, - 0xff, 0x3f, 0x8f, 0x90, 0x06, 0xf9, 0x7a, 0xaf, 0xa7, 0x1b, 0xad, 0xf8, 0xf6, 0x1b, 0x5b, 0x7d, - 0x36, 0x23, 0x9e, 0xcd, 0x10, 0x27, 0x5d, 0x7c, 0xaa, 0x0f, 0xe2, 0xcb, 0x6f, 0x10, 0x27, 0x94, - 0x3d, 0xdc, 0x8d, 0x83, 0x37, 0xdf, 0x55, 0x53, 0xdf, 0x7e, 0x57, 0x4d, 0xbd, 0xb9, 0xaa, 0xa6, - 0xbf, 0xbd, 0xaa, 0xa6, 0xff, 0x71, 0x55, 0x4d, 0xfd, 0xeb, 0xaa, 0x9a, 0xfe, 0xe6, 0x9f, 0xd5, - 0xf4, 0x30, 0xcf, 0xe7, 0xd7, 0x93, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xeb, 0xb3, 0x61, 0xe0, - 0x86, 0x0e, 0x00, 0x00, + // 1729 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x8f, 0xdb, 0xc6, + 0x15, 0x17, 0x25, 0xea, 0xdf, 0x93, 0x76, 0xc3, 0x1d, 0xdb, 0x5b, 0x96, 0xd9, 0x68, 0x69, 0xc5, + 0x8e, 0x37, 0x8b, 0x64, 0xe3, 0x26, 0x69, 0x8b, 0x16, 0x6d, 0x01, 0xfd, 0xe1, 0xae, 0x85, 0xca, + 0x94, 0x3a, 0xd2, 0x3a, 0x75, 0x0e, 0x25, 0x28, 0x71, 0xa4, 0x25, 0x4c, 0x71, 0x54, 0x92, 0x5a, + 0x5b, 0xfd, 0x08, 0xfa, 0x04, 0xbd, 0x08, 0x08, 0xd0, 0x53, 0xef, 0xfd, 0x10, 0x3e, 0x06, 0x3d, + 0xf4, 0xd0, 0x83, 0xd1, 0x6c, 0x2f, 0x3d, 0xf6, 0x5e, 0xa0, 0x28, 0x38, 0x43, 0x52, 0xd4, 0xae, + 0x37, 0xf0, 0xa1, 0x27, 0xce, 0xbc, 0xf7, 0x9b, 0x3f, 0xef, 0xf7, 0xde, 0xef, 0x0d, 0xa1, 0x3c, + 0x22, 0xf3, 0x93, 0xb9, 0x47, 0x03, 0x8a, 0x4a, 0xec, 0x33, 0xa6, 0x8e, 0xf2, 0xe9, 0xd4, 0x0e, + 0x2e, 0x16, 0xa3, 0x93, 0x31, 0x9d, 0x7d, 0x36, 0xa5, 0x53, 0xfa, 0x19, 0xf3, 0x8c, 0x16, 0x13, + 0x36, 0x63, 0x13, 0x36, 0xe2, 0x0b, 0xeb, 0x73, 0xc8, 0x3f, 0x21, 0x8e, 0x43, 0xd1, 0x21, 0x54, + 0x2c, 0x72, 0x69, 0x8f, 0x89, 0xe1, 0x9a, 0x33, 0x22, 0x0b, 0xaa, 0x70, 0x54, 0xc6, 0xc0, 0x4d, + 0xba, 0x39, 0x23, 0x21, 0x60, 0xec, 0xd8, 0xc4, 0x0d, 0x38, 0x20, 0xcb, 0x01, 0xdc, 0xc4, 0x00, + 0x0f, 0x61, 0x37, 0x02, 0x5c, 0x12, 0xcf, 0xb7, 0xa9, 0x2b, 0xe7, 0x18, 0x66, 0x87, 0x5b, 0x9f, + 0x71, 0x63, 0xdd, 0x87, 0xc2, 0x13, 0x62, 0x5a, 0xc4, 0x43, 0x1f, 0x83, 0x18, 0x2c, 0xe7, 0xfc, + 0xac, 0xdd, 0xcf, 0xef, 0x9d, 0xc4, 0x31, 0x9c, 0x3c, 0x25, 0xbe, 0x6f, 0x4e, 0xc9, 0x70, 0x39, + 0x27, 0x98, 0x41, 0xd0, 0xaf, 0xa0, 0x32, 0xa6, 0xb3, 0xb9, 0x47, 0x7c, 0xb6, 0x71, 0x96, 0xad, + 0x38, 0xb8, 0xb1, 0xa2, 0xb5, 0xc1, 0xe0, 0xf4, 0x82, 0x7a, 0x03, 0x76, 0x5a, 0xce, 0xc2, 0x0f, + 0x88, 0xd7, 0xa2, 0xee, 0xc4, 0x9e, 0xa2, 0xc7, 0x50, 0x9c, 0x50, 0xc7, 0x22, 0x9e, 0x2f, 0x0b, + 0x6a, 0xee, 0xa8, 0xf2, 0xb9, 0xb4, 0xd9, 0xec, 0x94, 0x39, 0x9a, 0xe2, 0xeb, 0x37, 0x87, 0x19, + 0x1c, 0xc3, 0xea, 0x7f, 0xca, 0x42, 0x81, 0x7b, 0xd0, 0x3e, 0x64, 0x6d, 0x8b, 0x53, 0xd4, 0x2c, + 0x5c, 0xbd, 0x39, 0xcc, 0x76, 0xda, 0x38, 0x6b, 0x5b, 0xe8, 0x2e, 0xe4, 0x1d, 0x73, 0x44, 0x9c, + 0x88, 0x1c, 0x3e, 0x41, 0xef, 0x43, 0xd9, 0x23, 0xa6, 0x65, 0x50, 0xd7, 0x59, 0x32, 0x4a, 0x4a, + 0xb8, 0x14, 0x1a, 0x7a, 0xae, 0xb3, 0x44, 0x9f, 0x02, 0xb2, 0xa7, 0x2e, 0xf5, 0x88, 0x31, 0x27, + 0xde, 0xcc, 0x66, 0xb7, 0xf5, 0x65, 0x91, 0xa1, 0xf6, 0xb8, 0xa7, 0xbf, 0x71, 0xa0, 0x0f, 0x61, + 0x27, 0x82, 0x5b, 0xc4, 0x21, 0x01, 0x91, 0xf3, 0x0c, 0x59, 0xe5, 0xc6, 0x36, 0xb3, 0xa1, 0xc7, + 0x70, 0xd7, 0xb2, 0x7d, 0x73, 0xe4, 0x10, 0x23, 0x20, 0xb3, 0xb9, 0x61, 0xbb, 0x16, 0x79, 0x45, + 0x7c, 0xb9, 0xc0, 0xb0, 0x28, 0xf2, 0x0d, 0xc9, 0x6c, 0xde, 0xe1, 0x1e, 0xb4, 0x0f, 0x85, 0xb9, + 0xb9, 0xf0, 0x89, 0x25, 0x17, 0x19, 0x26, 0x9a, 0x85, 0x2c, 0xf1, 0x0a, 0xf0, 0x65, 0xe9, 0x3a, + 0x4b, 0x6d, 0xe6, 0x88, 0x59, 0x8a, 0x60, 0xf5, 0x7f, 0x67, 0xa1, 0xc0, 0x3d, 0xe8, 0xa3, 0x84, + 0xa5, 0x6a, 0x73, 0x3f, 0x44, 0xfd, 0xfd, 0xcd, 0x61, 0x89, 0xfb, 0x3a, 0xed, 0x14, 0x6b, 0x08, + 0xc4, 0x54, 0x45, 0xb1, 0x31, 0x3a, 0x80, 0xb2, 0x69, 0x59, 0x61, 0xf6, 0x88, 0x2f, 0xe7, 0xd4, + 0xdc, 0x51, 0x19, 0x6f, 0x0c, 0xe8, 0xa7, 0xdb, 0xd5, 0x20, 0x5e, 0xaf, 0x9f, 0xdb, 0xca, 0x20, + 0x4c, 0xc5, 0x98, 0x78, 0x51, 0x05, 0xe7, 0xd9, 0x79, 0xa5, 0xd0, 0xc0, 0xea, 0xf7, 0x3e, 0x54, + 0x67, 0xe6, 0x2b, 0xc3, 0x27, 0xbf, 0x5f, 0x10, 0x77, 0x4c, 0x18, 0x5d, 0x39, 0x5c, 0x99, 0x99, + 0xaf, 0x06, 0x91, 0x09, 0xd5, 0x00, 0x6c, 0x37, 0xf0, 0xa8, 0xb5, 0x18, 0x13, 0x2f, 0xe2, 0x2a, + 0x65, 0x41, 0x3f, 0x86, 0x12, 0x23, 0xdb, 0xb0, 0x2d, 0xb9, 0xa4, 0x0a, 0x47, 0x62, 0x53, 0x89, + 0x02, 0x2f, 0x32, 0xaa, 0x59, 0xdc, 0xf1, 0x10, 0x17, 0x19, 0xb6, 0x63, 0xa1, 0x5f, 0x80, 0xe2, + 0xbf, 0xb0, 0xc3, 0x44, 0xf1, 0x9d, 0x02, 0x9b, 0xba, 0x86, 0x47, 0x66, 0xf4, 0xd2, 0x74, 0x7c, + 0xb9, 0xcc, 0x8e, 0x91, 0x43, 0x44, 0x27, 0x05, 0xc0, 0x91, 0xbf, 0xde, 0x83, 0x3c, 0xdb, 0x31, + 0xcc, 0x22, 0x2f, 0xd6, 0x48, 0xbd, 0xd1, 0x0c, 0x9d, 0x40, 0x7e, 0x62, 0x3b, 0xc4, 0x97, 0xb3, + 0x2c, 0x87, 0x28, 0x55, 0xe9, 0xb6, 0x43, 0x3a, 0xee, 0x84, 0x46, 0x59, 0xe4, 0xb0, 0xfa, 0x39, + 0x54, 0xd8, 0x86, 0xe7, 0x73, 0xcb, 0x0c, 0xc8, 0xff, 0x6d, 0xdb, 0xff, 0xe4, 0xa0, 0x14, 0x7b, + 0x92, 0xa4, 0x0b, 0xa9, 0xa4, 0x1f, 0x47, 0xfd, 0x80, 0xab, 0x7b, 0xff, 0xe6, 0x7e, 0xa9, 0x86, + 0x80, 0x40, 0xf4, 0xed, 0x3f, 0x10, 0xa6, 0xa7, 0x1c, 0x66, 0x63, 0xa4, 0x42, 0xe5, 0xba, 0x88, + 0x76, 0x70, 0xda, 0x84, 0x3e, 0x00, 0x98, 0x51, 0xcb, 0x9e, 0xd8, 0xc4, 0x32, 0x7c, 0x56, 0x00, + 0x39, 0x5c, 0x8e, 0x2d, 0x03, 0x24, 0x87, 0xe5, 0x1e, 0x4a, 0xc8, 0x8a, 0xb4, 0x12, 0x4f, 0x43, + 0x8f, 0xed, 0x5e, 0x9a, 0x8e, 0x1d, 0x2b, 0x24, 0x9e, 0x86, 0x5d, 0xcf, 0xa5, 0x5b, 0xe2, 0x2d, + 0x31, 0xc0, 0x8e, 0x4b, 0xd3, 0xc2, 0x7d, 0x0c, 0xc5, 0xb8, 0x2b, 0x86, 0xf9, 0xdc, 0x52, 0xd2, + 0x33, 0x32, 0x0e, 0x68, 0xd2, 0x6f, 0x22, 0x18, 0x52, 0xa0, 0x94, 0x94, 0x22, 0xb0, 0x9b, 0x26, + 0xf3, 0xb0, 0x17, 0x27, 0x71, 0xb8, 0xbe, 0x5c, 0x51, 0x85, 0xa3, 0x3c, 0x4e, 0x42, 0xd3, 0xc3, + 0xe3, 0x36, 0x80, 0xd1, 0x52, 0xae, 0xb2, 0x5a, 0x7c, 0x2f, 0xae, 0xc5, 0xc1, 0x05, 0xf5, 0x82, + 0x4e, 0x7b, 0xb3, 0xa2, 0xb9, 0x44, 0x3f, 0x82, 0x42, 0xd3, 0xa1, 0xe3, 0x17, 0xb1, 0xd2, 0xef, + 0x6c, 0xee, 0xc7, 0xec, 0xa9, 0x7c, 0x46, 0xc0, 0x30, 0x74, 0x7f, 0x39, 0x73, 0x6c, 0xf7, 0x85, + 0x11, 0x98, 0xde, 0x94, 0x04, 0xf2, 0x1e, 0x6f, 0xf8, 0x91, 0x75, 0xc8, 0x8c, 0x3f, 0x17, 0xff, + 0xf8, 0xcd, 0x61, 0xa6, 0xee, 0x42, 0x39, 0xd9, 0x27, 0x2c, 0x29, 0x3a, 0x99, 0xf8, 0x24, 0x60, + 0xf9, 0xcf, 0xe1, 0x68, 0x96, 0x64, 0x35, 0xcb, 0x02, 0xe2, 0x59, 0x45, 0x20, 0x5e, 0x98, 0xfe, + 0x05, 0xcb, 0x74, 0x15, 0xb3, 0x71, 0xa8, 0xe3, 0x97, 0xc4, 0x7c, 0x61, 0x30, 0x07, 0xcf, 0x73, + 0x29, 0x34, 0x3c, 0x31, 0xfd, 0x8b, 0xe8, 0xbc, 0x5f, 0x42, 0x81, 0xf3, 0x8a, 0xbe, 0x80, 0xd2, + 0x98, 0x2e, 0xdc, 0x60, 0xd3, 0xeb, 0xf7, 0xd2, 0xad, 0x82, 0x79, 0xa2, 0xc8, 0x12, 0x60, 0xfd, + 0x14, 0x8a, 0x91, 0x0b, 0x3d, 0x4c, 0xfa, 0x98, 0xd8, 0xbc, 0x77, 0x8d, 0xc2, 0xed, 0xe6, 0x7f, + 0x69, 0x3a, 0x0b, 0x7e, 0x79, 0x11, 0xf3, 0x49, 0xfd, 0x2f, 0x02, 0x14, 0x71, 0x98, 0x36, 0x3f, + 0x48, 0x3d, 0x1b, 0xf9, 0xad, 0x67, 0x63, 0x23, 0xb0, 0xec, 0x96, 0xc0, 0x62, 0x8d, 0xe4, 0x52, + 0x1a, 0xd9, 0x30, 0x27, 0xbe, 0x95, 0xb9, 0xfc, 0x5b, 0x98, 0x2b, 0xa4, 0x98, 0x7b, 0x08, 0xbb, + 0x13, 0x8f, 0xce, 0xd8, 0xc3, 0x40, 0x3d, 0xd3, 0x5b, 0x46, 0xf5, 0xbc, 0x13, 0x5a, 0x87, 0xb1, + 0xb1, 0x6e, 0x40, 0x09, 0x13, 0x7f, 0x4e, 0x5d, 0x9f, 0xdc, 0x7a, 0x6d, 0x04, 0xa2, 0x65, 0x06, + 0x26, 0xbb, 0x74, 0x15, 0xb3, 0x31, 0x7a, 0x04, 0xe2, 0x98, 0x5a, 0xfc, 0xca, 0xbb, 0xe9, 0x1a, + 0xd2, 0x3c, 0x8f, 0x7a, 0x2d, 0x6a, 0x11, 0xcc, 0x00, 0xf5, 0x39, 0x48, 0x6d, 0xfa, 0xd2, 0x75, + 0xa8, 0x69, 0xf5, 0x3d, 0x3a, 0x0d, 0x1b, 0xf4, 0xad, 0x8d, 0xa6, 0x0d, 0xc5, 0x05, 0x6b, 0x45, + 0x71, 0xab, 0x79, 0xb0, 0xdd, 0x1a, 0xae, 0x6f, 0xc4, 0xfb, 0x56, 0xac, 0xa7, 0x68, 0x69, 0xfd, + 0x6f, 0x02, 0x28, 0xb7, 0xa3, 0x51, 0x07, 0x2a, 0x1c, 0x69, 0xa4, 0xfe, 0x49, 0x8e, 0xde, 0xe5, + 0x20, 0xd6, 0x95, 0x60, 0x91, 0x8c, 0xdf, 0xfa, 0xa0, 0xa5, 0xf4, 0x9f, 0x7b, 0x37, 0xfd, 0x3f, + 0x82, 0x9d, 0x51, 0x28, 0x98, 0xe4, 0xf9, 0x16, 0xd5, 0xdc, 0x51, 0xbe, 0x99, 0x95, 0x32, 0xb8, + 0x3a, 0xe2, 0x4a, 0x62, 0xf6, 0x7a, 0x01, 0xc4, 0xbe, 0xed, 0x4e, 0xeb, 0x87, 0x90, 0x6f, 0x39, + 0x94, 0x25, 0xac, 0xe0, 0x11, 0xd3, 0xa7, 0x6e, 0xcc, 0x23, 0x9f, 0x1d, 0xff, 0x35, 0x0b, 0x95, + 0xd4, 0xaf, 0x15, 0x7a, 0x0c, 0xbb, 0xad, 0xee, 0xf9, 0x60, 0xa8, 0x61, 0xa3, 0xd5, 0xd3, 0x4f, + 0x3b, 0x67, 0x52, 0x46, 0x39, 0x58, 0xad, 0x55, 0x79, 0xb6, 0x01, 0x6d, 0xff, 0x35, 0x1d, 0x42, + 0xbe, 0xa3, 0xb7, 0xb5, 0xdf, 0x4a, 0x82, 0x72, 0x77, 0xb5, 0x56, 0xa5, 0x14, 0x90, 0x3f, 0x41, + 0x9f, 0x40, 0x95, 0x01, 0x8c, 0xf3, 0x7e, 0xbb, 0x31, 0xd4, 0xa4, 0xac, 0xa2, 0xac, 0xd6, 0xea, + 0xfe, 0x75, 0x5c, 0xc4, 0xf9, 0x87, 0x50, 0xc4, 0xda, 0x6f, 0xce, 0xb5, 0xc1, 0x50, 0xca, 0x29, + 0xfb, 0xab, 0xb5, 0x8a, 0x52, 0xc0, 0x58, 0x35, 0x0f, 0xa1, 0x84, 0xb5, 0x41, 0xbf, 0xa7, 0x0f, + 0x34, 0x49, 0x54, 0x7e, 0xb0, 0x5a, 0xab, 0x77, 0xb6, 0x50, 0x51, 0x95, 0xfe, 0x04, 0xf6, 0xda, + 0xbd, 0xaf, 0xf4, 0x6e, 0xaf, 0xd1, 0x36, 0xfa, 0xb8, 0x77, 0x86, 0xb5, 0xc1, 0x40, 0xca, 0x2b, + 0x87, 0xab, 0xb5, 0xfa, 0x7e, 0x0a, 0x7f, 0xa3, 0xe8, 0x3e, 0x00, 0xb1, 0xdf, 0xd1, 0xcf, 0xa4, + 0x82, 0x72, 0x67, 0xb5, 0x56, 0xdf, 0x4b, 0x41, 0x43, 0x52, 0xc3, 0x88, 0x5b, 0xdd, 0xde, 0x40, + 0x93, 0x8a, 0x37, 0x22, 0x66, 0x64, 0x1f, 0xff, 0x0e, 0xd0, 0xcd, 0x9f, 0x4f, 0xf4, 0x00, 0x44, + 0xbd, 0xa7, 0x6b, 0x52, 0x86, 0xc7, 0x7f, 0x13, 0xa1, 0x53, 0x97, 0xa0, 0x3a, 0xe4, 0xba, 0x5f, + 0x7f, 0x29, 0x09, 0xca, 0x0f, 0x57, 0x6b, 0xf5, 0xde, 0x4d, 0x50, 0xf7, 0xeb, 0x2f, 0x8f, 0x29, + 0x54, 0xd2, 0x1b, 0xd7, 0xa1, 0xf4, 0x54, 0x1b, 0x36, 0xda, 0x8d, 0x61, 0x43, 0xca, 0xf0, 0x2b, + 0xc5, 0xee, 0xa7, 0x24, 0x30, 0x99, 0x08, 0x0f, 0x20, 0xaf, 0x6b, 0xcf, 0x34, 0x2c, 0x09, 0xca, + 0xde, 0x6a, 0xad, 0xee, 0xc4, 0x00, 0x9d, 0x5c, 0x12, 0x0f, 0xd5, 0xa0, 0xd0, 0xe8, 0x7e, 0xd5, + 0x78, 0x3e, 0x90, 0xb2, 0x0a, 0x5a, 0xad, 0xd5, 0xdd, 0xd8, 0xdd, 0x70, 0x5e, 0x9a, 0x4b, 0xff, + 0xf8, 0xbf, 0x02, 0x54, 0xd3, 0x0f, 0x2e, 0xaa, 0x81, 0x78, 0xda, 0xe9, 0x6a, 0xf1, 0x71, 0x69, + 0x5f, 0x38, 0x46, 0x47, 0x50, 0x6e, 0x77, 0xb0, 0xd6, 0x1a, 0xf6, 0xf0, 0xf3, 0x38, 0x96, 0x34, + 0xa8, 0x6d, 0x7b, 0xac, 0xc0, 0x97, 0xe8, 0x67, 0x50, 0x1d, 0x3c, 0x7f, 0xda, 0xed, 0xe8, 0xbf, + 0x36, 0xd8, 0x8e, 0x59, 0xe5, 0xd1, 0x6a, 0xad, 0xde, 0xdf, 0x02, 0x93, 0xb9, 0x47, 0xc6, 0x66, + 0x40, 0xac, 0x01, 0x7f, 0x44, 0x42, 0x67, 0x49, 0x40, 0x2d, 0xd8, 0x8b, 0x97, 0x6e, 0x0e, 0xcb, + 0x29, 0x9f, 0xac, 0xd6, 0xea, 0x47, 0xdf, 0xbb, 0x3e, 0x39, 0xbd, 0x24, 0xa0, 0x07, 0x50, 0x8c, + 0x36, 0x89, 0x2b, 0x29, 0xbd, 0x34, 0x5a, 0x70, 0xfc, 0x67, 0x01, 0xca, 0x49, 0xbb, 0x0a, 0x09, + 0xd7, 0x7b, 0x86, 0x86, 0x71, 0x0f, 0xc7, 0x0c, 0x24, 0x4e, 0x9d, 0xb2, 0x21, 0xba, 0x0f, 0xc5, + 0x33, 0x4d, 0xd7, 0x70, 0xa7, 0x15, 0x0b, 0x23, 0x81, 0x9c, 0x11, 0x97, 0x78, 0xf6, 0x18, 0x7d, + 0x0c, 0x55, 0xbd, 0x67, 0x0c, 0xce, 0x5b, 0x4f, 0xe2, 0xd0, 0xd9, 0xf9, 0xa9, 0xad, 0x06, 0x8b, + 0xf1, 0x05, 0xe3, 0xf3, 0x38, 0xd4, 0xd0, 0xb3, 0x46, 0xb7, 0xd3, 0xe6, 0xd0, 0x9c, 0x22, 0xaf, + 0xd6, 0xea, 0xdd, 0x04, 0xda, 0xe1, 0x7f, 0x1e, 0x21, 0xf6, 0xd8, 0x82, 0xda, 0xf7, 0x37, 0x26, + 0xa4, 0x42, 0xa1, 0xd1, 0xef, 0x6b, 0x7a, 0x3b, 0xbe, 0xfd, 0xc6, 0xd7, 0x98, 0xcf, 0x89, 0x6b, + 0x85, 0x88, 0xd3, 0x1e, 0x3e, 0xd3, 0x86, 0xf1, 0xe5, 0x37, 0x88, 0x53, 0x1a, 0xbe, 0xe0, 0xcd, + 0x83, 0xd7, 0xdf, 0xd5, 0x32, 0xdf, 0x7e, 0x57, 0xcb, 0xbc, 0xbe, 0xaa, 0x09, 0xdf, 0x5e, 0xd5, + 0x84, 0x7f, 0x5c, 0xd5, 0x32, 0xff, 0xba, 0xaa, 0x09, 0xdf, 0xfc, 0xb3, 0x26, 0x8c, 0x0a, 0xac, + 0x91, 0x7d, 0xf1, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xad, 0x8a, 0xef, 0x7f, 0x8f, 0x0e, 0x00, + 0x00, } diff --git a/lib/protocol/bep.proto b/lib/protocol/bep.proto index 5645163e8..fc6c9d9c7 100644 --- a/lib/protocol/bep.proto +++ b/lib/protocol/bep.proto @@ -113,9 +113,9 @@ message FileInfo { enum FileInfoType { FILE = 0 [(gogoproto.enumvalue_customname) = "FileInfoTypeFile"]; DIRECTORY = 1 [(gogoproto.enumvalue_customname) = "FileInfoTypeDirectory"]; - SYMLINK_FILE = 2 [(gogoproto.enumvalue_customname) = "FileInfoTypeSymlinkFile"]; - SYMLINK_DIRECTORY = 3 [(gogoproto.enumvalue_customname) = "FileInfoTypeSymlinkDirectory"]; - SYMLINK_UNKNOWN = 4 [(gogoproto.enumvalue_customname) = "FileInfoTypeSymlinkUnknown"]; + SYMLINK_FILE = 2 [(gogoproto.enumvalue_customname) = "FileInfoTypeDeprecatedSymlinkFile", deprecated = true]; + SYMLINK_DIRECTORY = 3 [(gogoproto.enumvalue_customname) = "FileInfoTypeDeprecatedSymlinkDirectory", deprecated = true]; + SYMLINK = 4 [(gogoproto.enumvalue_customname) = "FileInfoTypeSymlink"]; } message BlockInfo { diff --git a/lib/protocol/bep_extensions.go b/lib/protocol/bep_extensions.go index 5408c6e03..de543f7de 100644 --- a/lib/protocol/bep_extensions.go +++ b/lib/protocol/bep_extensions.go @@ -37,7 +37,7 @@ func (f FileInfo) String() string { case FileInfoTypeFile: return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Length:%d, Deleted:%v, Invalid:%v, NoPermissions:%v, Blocks:%v}", f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Size, f.Deleted, f.Invalid, f.NoPermissions, f.Blocks) - case FileInfoTypeSymlinkDirectory, FileInfoTypeSymlinkFile, FileInfoTypeSymlinkUnknown: + case FileInfoTypeSymlink, FileInfoTypeDeprecatedSymlinkDirectory, FileInfoTypeDeprecatedSymlinkFile: return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, Deleted:%v, Invalid:%v, NoPermissions:%v, SymlinkTarget:%q}", f.Name, f.Type, f.Sequence, f.Version, f.Deleted, f.Invalid, f.NoPermissions, f.SymlinkTarget) default: @@ -59,7 +59,7 @@ func (f FileInfo) IsDirectory() bool { func (f FileInfo) IsSymlink() bool { switch f.Type { - case FileInfoTypeSymlinkDirectory, FileInfoTypeSymlinkFile, FileInfoTypeSymlinkUnknown: + case FileInfoTypeSymlink, FileInfoTypeDeprecatedSymlinkDirectory, FileInfoTypeDeprecatedSymlinkFile: return true default: return false diff --git a/lib/scanner/walk.go b/lib/scanner/walk.go index d3ceb9b9f..45967100b 100644 --- a/lib/scanner/walk.go +++ b/lib/scanner/walk.go @@ -20,7 +20,6 @@ import ( "github.com/syncthing/syncthing/lib/ignore" "github.com/syncthing/syncthing/lib/osutil" "github.com/syncthing/syncthing/lib/protocol" - "github.com/syncthing/syncthing/lib/symlinks" "golang.org/x/text/unicode/norm" ) @@ -374,19 +373,12 @@ func (w *walker) walkDir(relPath string, info os.FileInfo, dchan chan protocol.F // walkSymlink returns nil or an error, if the error is of the nature that // it should stop the entire walk. func (w *walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileInfo) error { - // If the target is a directory, do NOT descend down there. This will - // cause files to get tracked, and removing the symlink will as a result - // remove files in their real location. - if !symlinks.Supported { - return nil - } - // We always rehash symlinks as they have no modtime or // permissions. We check if they point to the old target by // checking that their existing blocks match with the blocks in // the index. - target, targetType, err := symlinks.Read(absPath) + target, err := os.Readlink(absPath) if err != nil { l.Debugln("readlink error:", absPath, err) return nil @@ -400,13 +392,13 @@ func (w *walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileIn // - the symlink type (file/dir) was the same // - the target was the same cf, ok := w.CurrentFiler.CurrentFile(relPath) - if ok && !cf.IsDeleted() && cf.IsSymlink() && !cf.IsInvalid() && SymlinkTypeEqual(targetType, cf) && cf.SymlinkTarget == target { + if ok && !cf.IsDeleted() && cf.IsSymlink() && !cf.IsInvalid() && cf.SymlinkTarget == target { return nil } f := protocol.FileInfo{ Name: relPath, - Type: SymlinkType(targetType), + Type: protocol.FileInfoTypeSymlink, Version: cf.Version.Update(w.ShortID), NoPermissions: true, // Symlinks don't have permissions of their own SymlinkTarget: target, @@ -489,38 +481,6 @@ func PermsEqual(a, b uint32) bool { } } -func SymlinkTypeEqual(disk symlinks.TargetType, f protocol.FileInfo) bool { - // If the target is missing, Unix never knows what type of symlink it is - // and Windows always knows even if there is no target. Which means that - // without this special check a Unix node would be fighting with a Windows - // node about whether or not the target is known. Basically, if you don't - // know and someone else knows, just accept it. The fact that you don't - // know means you are on Unix, and on Unix you don't really care what the - // target type is. The moment you do know, and if something doesn't match, - // that will propagate through the cluster. - switch disk { - case symlinks.TargetUnknown: - return true - case symlinks.TargetDirectory: - return f.Type == protocol.FileInfoTypeSymlinkDirectory - case symlinks.TargetFile: - return f.Type == protocol.FileInfoTypeSymlinkFile - } - panic("unknown symlink TargetType") -} - -func SymlinkType(t symlinks.TargetType) protocol.FileInfoType { - switch t { - case symlinks.TargetFile: - return protocol.FileInfoTypeSymlinkFile - case symlinks.TargetDirectory: - return protocol.FileInfoTypeSymlinkDirectory - case symlinks.TargetUnknown: - return protocol.FileInfoTypeSymlinkUnknown - } - panic("unknown symlink TargetType") -} - // A byteCounter gets bytes added to it via Update() and then provides the // Total() and one minute moving average Rate() in bytes per second. type byteCounter struct { diff --git a/lib/scanner/walk_test.go b/lib/scanner/walk_test.go index 48f27981a..48599fe25 100644 --- a/lib/scanner/walk_test.go +++ b/lib/scanner/walk_test.go @@ -23,7 +23,6 @@ import ( "github.com/syncthing/syncthing/lib/ignore" "github.com/syncthing/syncthing/lib/osutil" "github.com/syncthing/syncthing/lib/protocol" - "github.com/syncthing/syncthing/lib/symlinks" "golang.org/x/text/unicode/norm" ) @@ -282,7 +281,7 @@ func TestIssue1507(t *testing.T) { } func TestWalkSymlink(t *testing.T) { - if !symlinks.Supported { + if runtime.GOOS == "windows" { t.Skip("skipping unsupported symlink test") return } @@ -293,7 +292,7 @@ func TestWalkSymlink(t *testing.T) { defer os.RemoveAll("_symlinks") os.Mkdir("_symlinks", 0755) - symlinks.Create("_symlinks/link", "destination", symlinks.TargetUnknown) + os.Symlink("destination", "_symlinks/link") // Scan it @@ -383,34 +382,6 @@ func (l testfileList) String() string { return b.String() } -func TestSymlinkTypeEqual(t *testing.T) { - testcases := []struct { - onDiskType symlinks.TargetType - fiType protocol.FileInfoType - equal bool - }{ - // File is only equal to file - {symlinks.TargetFile, protocol.FileInfoTypeSymlinkFile, true}, - {symlinks.TargetFile, protocol.FileInfoTypeSymlinkDirectory, false}, - {symlinks.TargetFile, protocol.FileInfoTypeSymlinkUnknown, false}, - // Directory is only equal to directory - {symlinks.TargetDirectory, protocol.FileInfoTypeSymlinkFile, false}, - {symlinks.TargetDirectory, protocol.FileInfoTypeSymlinkDirectory, true}, - {symlinks.TargetDirectory, protocol.FileInfoTypeSymlinkUnknown, false}, - // Unknown is equal to anything - {symlinks.TargetUnknown, protocol.FileInfoTypeSymlinkFile, true}, - {symlinks.TargetUnknown, protocol.FileInfoTypeSymlinkDirectory, true}, - {symlinks.TargetUnknown, protocol.FileInfoTypeSymlinkUnknown, true}, - } - - for _, tc := range testcases { - res := SymlinkTypeEqual(tc.onDiskType, protocol.FileInfo{Type: tc.fiType}) - if res != tc.equal { - t.Errorf("Incorrect result %v for %v, %v", res, tc.onDiskType, tc.fiType) - } - } -} - var initOnce sync.Once const ( diff --git a/lib/symlinks/empty_test.go b/lib/symlinks/empty_test.go deleted file mode 100644 index 1ce3acc8f..000000000 --- a/lib/symlinks/empty_test.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (C) 2016 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/. - -// The existence of this file means we get 0% test coverage rather than no -// test coverage at all. Remove when implementing an actual test. - -package symlinks diff --git a/lib/symlinks/symlink_unix.go b/lib/symlinks/symlink_unix.go deleted file mode 100644 index fa7cab3df..000000000 --- a/lib/symlinks/symlink_unix.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2014 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 !windows - -package symlinks - -import ( - "os" - - "github.com/syncthing/syncthing/lib/osutil" -) - -var ( - Supported = true -) - -func Read(path string) (string, TargetType, error) { - tt := TargetUnknown - if stat, err := os.Stat(path); err == nil { - if stat.IsDir() { - tt = TargetDirectory - } else { - tt = TargetFile - } - } - path, err := os.Readlink(path) - - return osutil.NormalizedFilename(path), tt, err -} - -func Create(source, target string, tt TargetType) error { - return os.Symlink(osutil.NativeFilename(target), source) -} diff --git a/lib/symlinks/symlink_windows.go b/lib/symlinks/symlink_windows.go deleted file mode 100644 index ce0b019be..000000000 --- a/lib/symlinks/symlink_windows.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (C) 2014 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 windows - -package symlinks - -import ( - "os" - "path/filepath" - - "github.com/syncthing/syncthing/lib/osutil" - - "syscall" - "unicode/utf16" - "unsafe" -) - -const ( - Win32FsctlGetReparsePoint = 0x900a8 - Win32FileFlagOpenReparsePoint = 0x00200000 - Win32FileAttributeReparsePoint = 0x400 - Win32IOReparseTagSymlink = 0xA000000C - Win32SymbolicLinkFlagDirectory = 0x1 -) - -var ( - modkernel32 = syscall.NewLazyDLL("kernel32.dll") - procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") - procCreateSymbolicLink = modkernel32.NewProc("CreateSymbolicLinkW") - - Supported = false -) - -func init() { - defer func() { - if err := recover(); err != nil { - // Ensure that the supported flag is disabled when we hit an - // error, even though it should already be. Also, silently swallow - // the error since it's fine for a system not to support symlinks. - Supported = false - } - }() - - // Needs administrator privileges. - // Let's check that everything works. - // This could be done more officially: - // http://stackoverflow.com/questions/2094663/determine-if-windows-process-has-privilege-to-create-symbolic-link - // But I don't want to define 10 more structs just to look this up. - base := os.TempDir() - path := filepath.Join(base, "symlinktest") - defer os.Remove(path) - - err := Create(path, base, TargetDirectory) - if err != nil { - return - } - - stat, err := osutil.Lstat(path) - if err != nil || stat.Mode()&os.ModeSymlink == 0 { - return - } - - target, tt, err := Read(path) - if err != nil || osutil.NativeFilename(target) != base || tt != TargetDirectory { - return - } - Supported = true -} - -type reparseData struct { - reparseTag uint32 - reparseDataLength uint16 - reserved uint16 - substitueNameOffset uint16 - substitueNameLength uint16 - printNameOffset uint16 - printNameLength uint16 - flags uint32 - // substituteName - 264 widechars max = 528 bytes - // printName - 260 widechars max = 520 bytes - // = 1048 bytes total - buffer [1048]uint16 -} - -func (r *reparseData) PrintName() string { - // No clue why the offset and length is doubled... - offset := r.printNameOffset / 2 - length := r.printNameLength / 2 - return string(utf16.Decode(r.buffer[offset : offset+length])) -} - -func (r *reparseData) SubstituteName() string { - // No clue why the offset and length is doubled... - offset := r.substitueNameOffset / 2 - length := r.substitueNameLength / 2 - return string(utf16.Decode(r.buffer[offset : offset+length])) -} - -func Read(path string) (string, TargetType, error) { - ptr, err := syscall.UTF16PtrFromString(path) - if err != nil { - return "", TargetUnknown, err - } - handle, err := syscall.CreateFile(ptr, 0, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS|Win32FileFlagOpenReparsePoint, 0) - if err != nil || handle == syscall.InvalidHandle { - return "", TargetUnknown, err - } - defer syscall.Close(handle) - var ret uint16 - var data reparseData - - r1, _, err := syscall.Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), Win32FsctlGetReparsePoint, 0, 0, uintptr(unsafe.Pointer(&data)), unsafe.Sizeof(data), uintptr(unsafe.Pointer(&ret)), 0, 0) - if r1 == 0 { - return "", TargetUnknown, err - } - - tt := TargetUnknown - if attr, err := syscall.GetFileAttributes(ptr); err == nil { - if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - tt = TargetDirectory - } else { - tt = TargetFile - } - } - - return osutil.NormalizedFilename(data.PrintName()), tt, nil -} - -func Create(source, target string, tt TargetType) error { - srcp, err := syscall.UTF16PtrFromString(source) - if err != nil { - return err - } - - trgp, err := syscall.UTF16PtrFromString(osutil.NativeFilename(target)) - if err != nil { - return err - } - - // Sadly for Windows we need to specify the type of the symlink, - // whether it's a directory symlink or a file symlink. - // If the flags doesn't reveal the target type, try to evaluate it - // ourselves, and worst case default to the symlink pointing to a file. - mode := 0 - if tt == TargetUnknown { - path := target - if !filepath.IsAbs(target) { - path = filepath.Join(filepath.Dir(source), target) - } - - stat, err := os.Stat(path) - if err == nil && stat.IsDir() { - mode = Win32SymbolicLinkFlagDirectory - } - } else if tt == TargetDirectory { - mode = Win32SymbolicLinkFlagDirectory - } - - r0, _, err := syscall.Syscall(procCreateSymbolicLink.Addr(), 3, uintptr(unsafe.Pointer(srcp)), uintptr(unsafe.Pointer(trgp)), uintptr(mode)) - if r0 == 1 { - return nil - } - return err -} diff --git a/lib/symlinks/targets.go b/lib/symlinks/targets.go deleted file mode 100644 index 9f54062cd..000000000 --- a/lib/symlinks/targets.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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/. - -package symlinks - -type TargetType int - -const ( - TargetFile TargetType = iota - TargetDirectory - TargetUnknown -) diff --git a/test/ignore_test.go b/test/ignore_test.go index 8fc8edfdb..969c3066a 100644 --- a/test/ignore_test.go +++ b/test/ignore_test.go @@ -13,8 +13,6 @@ import ( "os" "path/filepath" "testing" - - "github.com/syncthing/syncthing/lib/symlinks" ) func TestIgnores(t *testing.T) { @@ -55,7 +53,7 @@ func TestIgnores(t *testing.T) { syms = []string{"s1", "s2", "s3", "s4", "s11", "s12", "s13", "s14"} for _, sym := range syms { p := filepath.Join("s1", sym) - symlinks.Create(p, p, 0) + os.Symlink(p, p) } all = append(all, syms...) } diff --git a/test/symlink_test.go b/test/symlink_test.go index d6baf3967..44adb5d09 100644 --- a/test/symlink_test.go +++ b/test/symlink_test.go @@ -16,7 +16,6 @@ import ( "github.com/syncthing/syncthing/lib/config" "github.com/syncthing/syncthing/lib/protocol" "github.com/syncthing/syncthing/lib/rc" - "github.com/syncthing/syncthing/lib/symlinks" ) func TestSymlinks(t *testing.T) { @@ -107,7 +106,7 @@ func testSymlinks(t *testing.T) { t.Fatal(err) } fd.Close() - err = symlinks.Create("s1/fileLink", "file", 0) + err = os.Symlink("file", "s1/fileLink") if err != nil { log.Fatal(err) } @@ -118,35 +117,35 @@ func testSymlinks(t *testing.T) { if err != nil { t.Fatal(err) } - err = symlinks.Create("s1/dirLink", "dir", 0) + err = os.Symlink("dir", "s1/dirLink") if err != nil { log.Fatal(err) } // A link to something in the repo that does not exist - err = symlinks.Create("s1/noneLink", "does/not/exist", 0) + err = os.Symlink("does/not/exist", "s1/noneLink") if err != nil { log.Fatal(err) } // A link we will replace with a file later - err = symlinks.Create("s1/repFileLink", "does/not/exist", 0) + err = os.Symlink("does/not/exist", "s1/repFileLink") if err != nil { log.Fatal(err) } // A link we will replace with a directory later - err = symlinks.Create("s1/repDirLink", "does/not/exist", 0) + err = os.Symlink("does/not/exist", "s1/repDirLink") if err != nil { log.Fatal(err) } // A link we will remove later - err = symlinks.Create("s1/removeLink", "does/not/exist", 0) + err = os.Symlink("does/not/exist", "s1/removeLink") if err != nil { log.Fatal(err) } @@ -183,7 +182,7 @@ func testSymlinks(t *testing.T) { if err != nil { log.Fatal(err) } - err = symlinks.Create("s1/dirLink", "file", 0) + err = os.Symlink("file", "s1/dirLink") if err != nil { log.Fatal(err) } @@ -219,7 +218,7 @@ func testSymlinks(t *testing.T) { if err != nil { log.Fatal(err) } - err = symlinks.Create("s1/fileToReplace", "somewhere/non/existent", 0) + err = os.Symlink("somewhere/non/existent", "s1/fileToReplace") if err != nil { log.Fatal(err) } @@ -230,7 +229,7 @@ func testSymlinks(t *testing.T) { if err != nil { log.Fatal(err) } - err = symlinks.Create("s1/dirToReplace", "somewhere/non/existent", 0) + err = os.Symlink("somewhere/non/existent", "s1/dirToReplace") if err != nil { log.Fatal(err) } diff --git a/test/util.go b/test/util.go index b2ed3ab9c..b5dcd0a07 100644 --- a/test/util.go +++ b/test/util.go @@ -28,7 +28,6 @@ import ( "github.com/syncthing/syncthing/lib/osutil" "github.com/syncthing/syncthing/lib/rc" - "github.com/syncthing/syncthing/lib/symlinks" ) func init() { @@ -436,7 +435,7 @@ func startWalker(dir string, res chan<- fileInfo, abort <-chan struct{}) chan er mode: os.ModeSymlink, } - tgt, _, err := symlinks.Read(path) + tgt, err := os.Readlink(path) if err != nil { return err }