2015-10-27 11:37:03 +01:00
// 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,
2017-02-09 07:52:18 +01:00
// You can obtain one at https://mozilla.org/MPL/2.0/.
2015-10-27 11:37:03 +01:00
package config
import (
2016-11-17 17:12:41 +02:00
"fmt"
2015-10-27 11:37:03 +01:00
"runtime"
2017-08-19 14:36:56 +00:00
"github.com/syncthing/syncthing/lib/fs"
2015-10-27 11:37:03 +01:00
"github.com/syncthing/syncthing/lib/protocol"
)
type FolderConfiguration struct {
ID string `xml:"id,attr" json:"id"`
2016-03-11 09:48:46 +00:00
Label string `xml:"label,attr" json:"label"`
2017-08-19 14:36:56 +00:00
FilesystemType fs . FilesystemType `xml:"filesystemType" json:"filesystemType"`
Path string `xml:"path,attr" json:"path"`
2016-05-04 11:26:36 +00:00
Type FolderType `xml:"type,attr" json:"type"`
2015-10-27 11:37:03 +01:00
Devices [] FolderDeviceConfiguration `xml:"device" json:"devices"`
RescanIntervalS int `xml:"rescanIntervalS,attr" json:"rescanIntervalS"`
IgnorePerms bool `xml:"ignorePerms,attr" json:"ignorePerms"`
AutoNormalize bool `xml:"autoNormalize,attr" json:"autoNormalize"`
2017-04-12 09:01:19 +00:00
MinDiskFree Size `xml:"minDiskFree" json:"minDiskFree"`
2015-10-27 11:37:03 +01:00
Versioning VersioningConfiguration `xml:"versioning" json:"versioning"`
Copiers int `xml:"copiers" json:"copiers"` // This defines how many files are handled concurrently.
Pullers int `xml:"pullers" json:"pullers"` // Defines how many blocks are fetched at the same time, possibly between separate copier routines.
Hashers int `xml:"hashers" json:"hashers"` // Less than one sets the value to the number of cores. These are CPU bound due to hashing.
Order PullOrder `xml:"order" json:"order"`
IgnoreDelete bool `xml:"ignoreDelete" json:"ignoreDelete"`
ScanProgressIntervalS int `xml:"scanProgressIntervalS" json:"scanProgressIntervalS"` // Set to a negative value to disable. Value of 0 will get replaced with value of 2 (default value)
PullerSleepS int `xml:"pullerSleepS" json:"pullerSleepS"`
PullerPauseS int `xml:"pullerPauseS" json:"pullerPauseS"`
MaxConflicts int `xml:"maxConflicts" json:"maxConflicts"`
2015-11-21 16:30:53 +01:00
DisableSparseFiles bool `xml:"disableSparseFiles" json:"disableSparseFiles"`
2016-04-15 10:59:41 +00:00
DisableTempIndexes bool `xml:"disableTempIndexes" json:"disableTempIndexes"`
2016-12-21 18:41:25 +00:00
Paused bool `xml:"paused" json:"paused"`
2017-01-04 21:04:13 +00:00
WeakHashThresholdPct int `xml:"weakHashThresholdPct" json:"weakHashThresholdPct"` // Use weak hash if more than X percent of the file has changed. Set to -1 to always use weak hash.
2015-10-27 11:37:03 +01:00
2017-08-19 14:36:56 +00:00
cachedFilesystem fs . Filesystem
2016-05-04 10:47:33 +00:00
2017-04-12 09:01:19 +00:00
DeprecatedReadOnly bool `xml:"ro,attr,omitempty" json:"-"`
2017-04-27 14:46:19 +09:00
DeprecatedMinDiskFreePct float64 `xml:"minDiskFreePct,omitempty" json:"-"`
2015-10-27 11:37:03 +01:00
}
type FolderDeviceConfiguration struct {
2016-11-07 16:40:48 +00:00
DeviceID protocol . DeviceID `xml:"id,attr" json:"deviceID"`
IntroducedBy protocol . DeviceID `xml:"introducedBy,attr" json:"introducedBy"`
2015-10-27 11:37:03 +01:00
}
2017-08-19 14:36:56 +00:00
func NewFolderConfiguration ( id string , fsType fs . FilesystemType , path string ) FolderConfiguration {
2015-11-07 09:47:31 +01:00
f := FolderConfiguration {
2017-08-19 14:36:56 +00:00
ID : id ,
FilesystemType : fsType ,
Path : path ,
2015-11-07 09:47:31 +01:00
}
f . prepare ()
return f
}
2015-10-27 11:37:03 +01:00
func ( f FolderConfiguration ) Copy () FolderConfiguration {
c := f
c . Devices = make ([] FolderDeviceConfiguration , len ( f . Devices ))
copy ( c . Devices , f . Devices )
2015-10-27 11:53:42 +01:00
c . Versioning = f . Versioning . Copy ()
2015-10-27 11:37:03 +01:00
return c
}
2017-08-19 14:36:56 +00:00
func ( f FolderConfiguration ) Filesystem () fs . Filesystem {
2015-10-27 11:37:03 +01:00
// This is intentionally not a pointer method, because things like
2017-08-19 14:36:56 +00:00
// cfg.Folders["default"].Filesystem() should be valid.
if f . cachedFilesystem == nil && f . Path != "" {
l . Infoln ( "bug: uncached filesystem call (should only happen in tests)" )
return fs . NewFilesystem ( f . FilesystemType , f . Path )
2015-10-27 11:37:03 +01:00
}
2017-08-19 14:36:56 +00:00
return f . cachedFilesystem
2015-10-27 11:37:03 +01:00
}
func ( f * FolderConfiguration ) CreateMarker () error {
if ! f . HasMarker () {
2017-09-02 05:52:38 +00:00
permBits := fs . FileMode ( 0777 )
if runtime . GOOS == "windows" {
// Windows has no umask so we must chose a safer set of bits to
// begin with.
permBits = 0700
}
2017-08-19 14:36:56 +00:00
fs := f . Filesystem ()
2017-09-02 05:52:38 +00:00
err := fs . Mkdir ( ".stfolder" , permBits )
2015-10-27 11:37:03 +01:00
if err != nil {
return err
}
2017-08-19 14:36:56 +00:00
if dir , err := fs . Open ( "." ); err == nil {
if serr := dir . Sync (); err != nil {
l . Infof ( "fsync %q failed: %v" , "." , serr )
}
} else {
l . Infof ( "fsync %q failed: %v" , "." , err )
2016-11-21 18:09:29 +01:00
}
2017-08-19 14:36:56 +00:00
fs . Hide ( ".stfolder" )
2015-10-27 11:37:03 +01:00
}
return nil
}
func ( f * FolderConfiguration ) HasMarker () bool {
2017-08-19 14:36:56 +00:00
_ , err := f . Filesystem (). Stat ( ".stfolder" )
2016-12-18 19:57:41 +01:00
return err == nil
2015-10-27 11:37:03 +01:00
}
2017-04-23 23:50:56 +00:00
func ( f * FolderConfiguration ) CreateRoot () ( err error ) {
// Directory permission bits. Will be filtered down to something
// sane by umask on Unixes.
2017-08-19 14:36:56 +00:00
permBits := fs . FileMode ( 0777 )
2017-04-23 23:50:56 +00:00
if runtime . GOOS == "windows" {
// Windows has no umask so we must chose a safer set of bits to
// begin with.
permBits = 0700
}
2017-08-19 14:36:56 +00:00
filesystem := f . Filesystem ()
if _ , err = filesystem . Stat ( "." ); fs . IsNotExist ( err ) {
if err = filesystem . MkdirAll ( "." , permBits ); err != nil {
l . Warnf ( "Creating directory for %v: %v" , f . Description (), err )
2017-04-23 23:50:56 +00:00
}
}
return err
}
2016-11-17 17:12:41 +02:00
func ( f FolderConfiguration ) Description () string {
2016-12-19 10:12:06 +01:00
if f . Label == "" {
return f . ID
}
2016-11-17 17:12:41 +02:00
return fmt . Sprintf ( "%q (%s)" , f . Label , f . ID )
}
2015-10-27 11:37:03 +01:00
func ( f * FolderConfiguration ) DeviceIDs () [] protocol . DeviceID {
deviceIDs := make ([] protocol . DeviceID , len ( f . Devices ))
for i , n := range f . Devices {
deviceIDs [ i ] = n . DeviceID
}
return deviceIDs
}
2015-11-05 08:01:47 +00:00
func ( f * FolderConfiguration ) prepare () {
2017-08-19 14:36:56 +00:00
if f . Path != "" {
f . cachedFilesystem = fs . NewFilesystem ( f . FilesystemType , f . Path )
2015-11-05 08:01:47 +00:00
}
if f . RescanIntervalS > MaxRescanIntervalS {
f . RescanIntervalS = MaxRescanIntervalS
} else if f . RescanIntervalS < 0 {
f . RescanIntervalS = 0
}
2016-05-09 11:30:19 +00:00
if f . Versioning . Params == nil {
f . Versioning . Params = make ( map [ string ] string )
}
2017-01-04 21:04:13 +00:00
if f . WeakHashThresholdPct == 0 {
f . WeakHashThresholdPct = 25
}
2015-11-05 08:01:47 +00:00
}
2015-10-27 11:37:03 +01:00
type FolderDeviceConfigurationList [] FolderDeviceConfiguration
func ( l FolderDeviceConfigurationList ) Less ( a , b int ) bool {
return l [ a ]. DeviceID . Compare ( l [ b ]. DeviceID ) == - 1
}
func ( l FolderDeviceConfigurationList ) Swap ( a , b int ) {
l [ a ], l [ b ] = l [ b ], l [ a ]
}
func ( l FolderDeviceConfigurationList ) Len () int {
return len ( l )
}