Compare commits

...

14 Commits

Author SHA1 Message Date
Jakob Borg
3850a08252 lib/model: Remove spurious "replacing service" failure event (ref #9271)
This is no longer a notable condition, as we do this pretty much all the
time.
2023-12-11 07:44:04 +01:00
Simon Frei
a28de73031 lib/model: Remove runner during folder cleanup (fixes #9269) (#9271)
Before introducing the service map and using it for folder runners, the
entries in folderCfgs and folderRunners for the same key/folder were
removed under a single lock. Stopping the folder happens separately
before that with just the read lock. Now with the service map stopping
the folder and removing it from the map is a single operation. And that
still happens with just a read-lock. However even with a full lock it’s
still problematic: After the folder stopped, the runner isn’t present
anymore while the folder-config still is and sais the folder isn't
paused.

The index handler in turn looks at the folder config that is not paused,
thus assumes the runner has to be present -> nil deref on the runner.

A better solution might be to push most of these fmut maps into the
folder - they anyway are needed in there. Then there's just a single
map/source of info that's necessarily consistent. That's quite a bit of
work though, and probably/likely there will be corner cases there too.
2023-12-08 07:13:09 +01:00
Jakob Borg
75310b58a0 build: Update dependencies (#9265) 2023-12-06 10:53:45 +01:00
Jakob Borg
8064957270 build: Revert specifics for Go 1.21.4, build using Go 1.21.5 (#9264)
This reverts commit e477777f49.

In principle, we could have stayed with `~1.21.1`, but `check-latest:
true` apparently checks some cache/manifest/something that is only
periodically refreshed and isn't aware of 1.21.5 yet. So update the
constraints to force an upgrade.

Also the infrastructure images weren't actually using the constraint
since there was no `setup-go` action...
2023-12-06 09:02:12 +01:00
Jakob Borg
c1ec9a8826 lib/fs: Reduce memory usage in xattrs handling (#9251)
This reduces allocations, in number and in size, while getting extended
attributes. This is mostly noticable when there is a large number of new
files to scan and we're running with the default scanProgressInterval --
then a queue of files is built in-memory, and this queue includes
extended attributes as part of file metadata. (Arguable it shouldn't,
but that's a more difficult and involved change.)

With 1M files to scan, each with one extended attribute, current peak
memory usage looks like this:

	Showing nodes accounting for 1425.30MB, 98.19% of 1451.64MB total
	Dropped 1435 nodes (cum <= 7.26MB)
	Showing top 10 nodes out of 54
	      flat  flat%   sum%        cum   cum%
976.56MB 67.27% 67.27% 976.56MB 67.27%
github.com/syncthing/syncthing/lib/fs.getXattr
305.44MB 21.04% 88.31% 305.44MB 21.04%
github.com/syncthing/syncthing/lib/scanner.(*walker).walk.func1
45.78MB 3.15% 91.47% 1045.23MB 72.00%
github.com/syncthing/syncthing/lib/fs.(*BasicFilesystem).GetXattr
22.89MB 1.58% 93.04% 22.89MB 1.58%
github.com/syncthing/syncthing/lib/fs.listXattr
22.89MB 1.58% 94.62% 22.89MB 1.58%
github.com/syncthing/syncthing/lib/protocol.(*PlatformData).SetXattrs
16MB 1.10% 95.72% 16.01MB 1.10%
github.com/syndtr/goleveldb/leveldb/memdb.New

After the change, it's this:

	Showing nodes accounting for 502.32MB, 95.70% of 524.88MB total
	Dropped 1400 nodes (cum <= 2.62MB)
	Showing top 10 nodes out of 91
	      flat  flat%   sum%        cum   cum%
305.43MB 58.19% 58.19% 305.43MB 58.19%
github.com/syncthing/syncthing/lib/scanner.(*walker).walk.func1
45.79MB 8.72% 66.91% 68.68MB 13.09%
github.com/syncthing/syncthing/lib/fs.(*BasicFilesystem).GetXattr
32MB 6.10% 73.01% 32.01MB 6.10%
github.com/syndtr/goleveldb/leveldb/memdb.New
22.89MB 4.36% 77.37% 22.89MB 4.36%
github.com/syncthing/syncthing/lib/fs.listXattr
22.89MB 4.36% 81.73% 22.89MB 4.36%
github.com/syncthing/syncthing/lib/protocol.(*PlatformData).SetXattrs
15.35MB 2.92% 84.66% 15.36MB 2.93%
github.com/syndtr/goleveldb/leveldb/util.(*BufferPool).Get
	   15.28MB  2.91% 87.57%    15.28MB  2.91%  strings.(*Builder).grow

(The usage for xattrs is reduced from 976 MB to 68 MB)
2023-12-04 12:48:17 +01:00
Jakob Borg
1625b44892 lib/model: Improve LastSeen handling (#9256)
LastSeen for a device was only updated when they connected. This now
updates it when they disconnect, so that we remember the last time we
actually saw them. When asking the API for current stats, currently
connected devices get a last seen value of the current time.
2023-12-04 09:24:10 +01:00
Jakob Borg
d51760f410 lib/scanner: Record inode change time for directories and symlinks (#9250) 2023-12-04 07:48:24 +01:00
Jakob Borg
7b1932d64e lib/api: Improve ignore loading error handling (fixes #9253) (#9254) 2023-12-04 07:11:35 +01:00
Syncthing Release Automation
5bfc540c88 gui, man, authors: Update docs, translations, and contributors 2023-12-04 03:45:22 +00:00
Jakob Borg
4cba99fcd4 lib/fs: Better equality comparison in mtimefs 2023-12-03 16:01:46 +01:00
Jakob Borg
2ae15aa454 cmd/stcrashreceiver: Add metrics for diskstore inventory 2023-11-27 08:24:59 +01:00
Jakob Borg
47bcf4f8f4 cmd/stcrashreceiver: Minor cleanup, stricter file permissions 2023-11-27 08:24:59 +01:00
Jakob Borg
a8b9096353 cmd/stcrashreceiver: Add metrics for incoming reports 2023-11-27 08:24:59 +01:00
Jakob Borg
5328380691 cmd/ursrv: Add metrics for incoming reports 2023-11-27 08:24:59 +01:00
37 changed files with 318 additions and 122 deletions

View File

@@ -6,7 +6,7 @@ on:
- infrastructure
env:
GO_VERSION: "~1.21.1"
GO_VERSION: "~1.21.5"
CGO_ENABLED: "0"
BUILD_USER: docker
BUILD_HOST: github.syncthing.net
@@ -28,6 +28,11 @@ jobs:
with:
fetch-depth: 0
- uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Login to Docker Hub
uses: docker/login-action@v3
with:

View File

@@ -12,7 +12,7 @@ env:
# The go version to use for builds. We set check-latest to true when
# installing, so we get the latest patch version that matches the
# expression.
GO_VERSION: "~1.21.1"
GO_VERSION: "~1.21.5"
# Optimize compatibility on the slow archictures.
GO386: softfloat
@@ -48,20 +48,7 @@ jobs:
runner: ["windows-latest", "ubuntu-latest", "macos-latest"]
# The oldest version in this list should match what we have in our go.mod.
# Variables don't seem to be supported here, or we could have done something nice.
go: ["1.20", "1.21"]
# Don't run the Windows tests with Go 1.21.4 or 1.20.11; this can be
# removed when 1.21.5 and 1.20.12 is released.
exclude:
- runner: windows-latest
go: "1.20"
- runner: windows-latest
go: "1.21"
include:
- runner: windows-latest
go: "~1.20.12 || ~1.20.0 <1.20.11"
- runner: windows-latest
go: "~1.21.5 || ~1.21.1 <1.21.4"
go: ["~1.20.12", "~1.21.5"]
runs-on: ${{ matrix.runner }}
steps:
- name: Set git to use LF
@@ -169,9 +156,7 @@ jobs:
- uses: actions/setup-go@v4
with:
# Temporary version constraint to avoid 1.21.4 which has a bug in
# path handling. This can be removed when 1.21.5 is released.
go-version: "~1.21.5 || ~1.21.1 <1.21.4"
go-version: ${{ env.GO_VERSION }}
cache: false
check-latest: true

View File

@@ -12,6 +12,7 @@ import (
"context"
"io"
"log"
"math"
"os"
"path/filepath"
"sort"
@@ -40,7 +41,7 @@ type currentFile struct {
}
func (d *diskStore) Serve(ctx context.Context) {
if err := os.MkdirAll(d.dir, 0750); err != nil {
if err := os.MkdirAll(d.dir, 0o700); err != nil {
log.Println("Creating directory:", err)
return
}
@@ -60,7 +61,7 @@ func (d *diskStore) Serve(ctx context.Context) {
case entry := <-d.inbox:
path := d.fullPath(entry.path)
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
log.Println("Creating directory:", err)
continue
}
@@ -75,7 +76,7 @@ func (d *diskStore) Serve(ctx context.Context) {
log.Println("Failed to compress crash report:", err)
continue
}
if err := os.WriteFile(path, buf.Bytes(), 0644); err != nil {
if err := os.WriteFile(path, buf.Bytes(), 0o600); err != nil {
log.Printf("Failed to write %s: %v", entry.path, err)
_ = os.Remove(path)
continue
@@ -147,6 +148,11 @@ func (d *diskStore) clean() {
if len(d.currentFiles) > 0 {
oldest = time.Since(time.Unix(d.currentFiles[0].mtime, 0)).Truncate(time.Minute)
}
metricDiskstoreFilesTotal.Set(float64(len(d.currentFiles)))
metricDiskstoreBytesTotal.Set(float64(d.currentSize))
metricDiskstoreOldestAgeSeconds.Set(math.Round(oldest.Seconds()))
log.Printf("Clean complete: %d files, %d MB, oldest is %v ago", len(d.currentFiles), d.currentSize>>20, oldest)
}
@@ -178,6 +184,11 @@ func (d *diskStore) inventory() error {
if len(d.currentFiles) > 0 {
oldest = time.Since(time.Unix(d.currentFiles[0].mtime, 0)).Truncate(time.Minute)
}
metricDiskstoreFilesTotal.Set(float64(len(d.currentFiles)))
metricDiskstoreBytesTotal.Set(float64(d.currentSize))
metricDiskstoreOldestAgeSeconds.Set(math.Round(oldest.Seconds()))
log.Printf("Inventory complete: %d files, %d MB, oldest is %v ago", len(d.currentFiles), d.currentSize>>20, oldest)
return err
}

View File

@@ -21,9 +21,9 @@ import (
"net/http"
"os"
"path/filepath"
"time"
"github.com/alecthomas/kong"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/syncthing/syncthing/lib/sha256"
"github.com/syncthing/syncthing/lib/ur"
@@ -33,14 +33,13 @@ import (
const maxRequestSize = 1 << 20 // 1 MiB
type cli struct {
Dir string `help:"Parent directory to store crash and failure reports in" env:"REPORTS_DIR" default:"."`
DSN string `help:"Sentry DSN" env:"SENTRY_DSN"`
Listen string `help:"HTTP listen address" default:":8080" env:"LISTEN_ADDRESS"`
MaxDiskFiles int `help:"Maximum number of reports on disk" default:"100000" env:"MAX_DISK_FILES"`
MaxDiskSizeMB int64 `help:"Maximum disk space to use for reports" default:"1024" env:"MAX_DISK_SIZE_MB"`
CleanInterval time.Duration `help:"Interval between cleaning up old reports" default:"12h" env:"CLEAN_INTERVAL"`
SentryQueue int `help:"Maximum number of reports to queue for sending to Sentry" default:"64" env:"SENTRY_QUEUE"`
DiskQueue int `help:"Maximum number of reports to queue for writing to disk" default:"64" env:"DISK_QUEUE"`
Dir string `help:"Parent directory to store crash and failure reports in" env:"REPORTS_DIR" default:"."`
DSN string `help:"Sentry DSN" env:"SENTRY_DSN"`
Listen string `help:"HTTP listen address" default:":8080" env:"LISTEN_ADDRESS"`
MaxDiskFiles int `help:"Maximum number of reports on disk" default:"100000" env:"MAX_DISK_FILES"`
MaxDiskSizeMB int64 `help:"Maximum disk space to use for reports" default:"1024" env:"MAX_DISK_SIZE_MB"`
SentryQueue int `help:"Maximum number of reports to queue for sending to Sentry" default:"64" env:"SENTRY_QUEUE"`
DiskQueue int `help:"Maximum number of reports to queue for writing to disk" default:"64" env:"DISK_QUEUE"`
}
func main() {
@@ -72,6 +71,7 @@ func main() {
mux.HandleFunc("/ping", func(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("OK"))
})
mux.Handle("/metrics", promhttp.Handler())
if params.DSN != "" {
mux.HandleFunc("/newcrash/failure", handleFailureFn(params.DSN, filepath.Join(params.Dir, "failure_reports")))
@@ -85,6 +85,11 @@ func main() {
func handleFailureFn(dsn, failureDir string) func(w http.ResponseWriter, req *http.Request) {
return func(w http.ResponseWriter, req *http.Request) {
result := "failure"
defer func() {
metricFailureReportsTotal.WithLabelValues(result).Inc()
}()
lr := io.LimitReader(req.Body, maxRequestSize)
bs, err := io.ReadAll(lr)
req.Body.Close()
@@ -135,6 +140,7 @@ func handleFailureFn(dsn, failureDir string) func(w http.ResponseWriter, req *ht
log.Println("Failed to send failure report:", err)
} else {
log.Println("Sent failure report:", r.Description)
result = "success"
}
}
}

View File

@@ -0,0 +1,40 @@
// Copyright (C) 2023 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 main
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
metricCrashReportsTotal = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "syncthing",
Subsystem: "crashreceiver",
Name: "crash_reports_total",
}, []string{"result"})
metricFailureReportsTotal = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "syncthing",
Subsystem: "crashreceiver",
Name: "failure_reports_total",
}, []string{"result"})
metricDiskstoreFilesTotal = promauto.NewGauge(prometheus.GaugeOpts{
Namespace: "syncthing",
Subsystem: "crashreceiver",
Name: "diskstore_files_total",
})
metricDiskstoreBytesTotal = promauto.NewGauge(prometheus.GaugeOpts{
Namespace: "syncthing",
Subsystem: "crashreceiver",
Name: "diskstore_bytes_total",
})
metricDiskstoreOldestAgeSeconds = promauto.NewGauge(prometheus.GaugeOpts{
Namespace: "syncthing",
Subsystem: "crashreceiver",
Name: "diskstore_oldest_age_seconds",
})
)

View File

@@ -71,6 +71,11 @@ func (r *crashReceiver) serveHead(reportID string, w http.ResponseWriter, _ *htt
// servePut accepts and stores the given report.
func (r *crashReceiver) servePut(reportID string, w http.ResponseWriter, req *http.Request) {
result := "receive_failure"
defer func() {
metricCrashReportsTotal.WithLabelValues(result).Inc()
}()
// Read at most maxRequestSize of report data.
log.Println("Receiving report", reportID)
lr := io.LimitReader(req.Body, maxRequestSize)
@@ -81,13 +86,17 @@ func (r *crashReceiver) servePut(reportID string, w http.ResponseWriter, req *ht
return
}
result = "success"
// Store the report
if !r.store.Put(reportID, bs) {
log.Println("Failed to store report (queue full):", reportID)
result = "queue_failure"
}
// Send the report to Sentry
if !r.sentry.Send(reportID, userIDFor(req), bs) {
log.Println("Failed to send report to sentry (queue full):", reportID)
result = "sentry_failure"
}
}

View File

@@ -0,0 +1,26 @@
// Copyright (C) 2023 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 serve
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var metricReportsTotal = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "syncthing",
Subsystem: "ursrv",
Name: "reports_total",
}, []string{"version"})
func init() {
metricReportsTotal.WithLabelValues("fail")
metricReportsTotal.WithLabelValues("duplicate")
metricReportsTotal.WithLabelValues("v1")
metricReportsTotal.WithLabelValues("v2")
metricReportsTotal.WithLabelValues("v3")
}

View File

@@ -11,6 +11,7 @@ import (
"database/sql"
"embed"
"encoding/json"
"fmt"
"html/template"
"io"
"log"
@@ -26,6 +27,7 @@ import (
_ "github.com/lib/pq" // PostgreSQL driver
"github.com/oschwald/geoip2-golang"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/text/cases"
"golang.org/x/text/language"
@@ -196,6 +198,7 @@ func (cli *CLI) Run() error {
http.HandleFunc("/performance.json", srv.performanceHandler)
http.HandleFunc("/blockstats.json", srv.blockStatsHandler)
http.HandleFunc("/locations.json", srv.locationsHandler)
http.Handle("/metrics", promhttp.Handler())
http.Handle("/static/", http.FileServer(http.FS(statics)))
go srv.cacheRefresher()
@@ -289,6 +292,12 @@ func (s *server) locationsHandler(w http.ResponseWriter, _ *http.Request) {
}
func (s *server) newDataHandler(w http.ResponseWriter, r *http.Request) {
version := "fail"
defer func() {
// Version is "fail", "duplicate", "v2", "v3", ...
metricReportsTotal.WithLabelValues(version).Inc()
}()
defer r.Body.Close()
addr := r.Header.Get("X-Forwarded-For")
@@ -334,6 +343,7 @@ func (s *server) newDataHandler(w http.ResponseWriter, r *http.Request) {
if err.Error() == `pq: duplicate key value violates unique constraint "uniqueidjsonindex"` {
// We already have a report today for the same unique ID; drop
// this one without complaining.
version = "duplicate"
return
}
log.Println("insert:", err)
@@ -343,6 +353,8 @@ func (s *server) newDataHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Database Error", http.StatusInternalServerError)
return
}
version = fmt.Sprintf("v%d", rep.URVersion)
}
func (s *server) summaryHandler(w http.ResponseWriter, r *http.Request) {

20
go.mod
View File

@@ -41,20 +41,20 @@ require (
github.com/quic-go/quic-go v0.40.0
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
github.com/sasha-s/go-deadlock v0.3.1
github.com/shirou/gopsutil/v3 v3.23.10
github.com/shirou/gopsutil/v3 v3.23.11
github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
github.com/thejerf/suture/v4 v4.0.2
github.com/urfave/cli v1.22.14
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
golang.org/x/crypto v0.15.0
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/crypto v0.16.0
golang.org/x/exp v0.0.0-20231127185646-65229373498e
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.18.0
golang.org/x/sys v0.14.0
golang.org/x/net v0.19.0
golang.org/x/sys v0.15.0
golang.org/x/text v0.14.0
golang.org/x/time v0.4.0
golang.org/x/tools v0.15.0
golang.org/x/time v0.5.0
golang.org/x/tools v0.16.0
google.golang.org/protobuf v1.31.0
)
@@ -63,12 +63,12 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
github.com/google/pprof v0.0.0-20231205033806-a5a03c77bf08 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/onsi/ginkgo/v2 v2.13.1 // indirect
github.com/onsi/ginkgo/v2 v2.13.2 // indirect
github.com/oschwald/maxminddb-golang v1.12.0 // indirect
github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect
github.com/petermattis/goid v0.0.0-20231126143041-f558c26febf5 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect

41
go.sum
View File

@@ -79,8 +79,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20231205033806-a5a03c77bf08 h1:PxlBVtIFHR/mtWk2i0gTEdCz+jBnqiuHNSki0epDbVs=
github.com/google/pprof v0.0.0-20231205033806-a5a03c77bf08/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -128,8 +128,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU=
github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
@@ -140,8 +140,8 @@ github.com/oschwald/geoip2-golang v1.9.0/go.mod h1:BHK6TvDyATVQhKNbQBdrj9eAvuwOM
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc h1:8bQZVK1X6BJR/6nYUPxQEP+ReTsceJTKizeuwjWOPUA=
github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/petermattis/goid v0.0.0-20231126143041-f558c26febf5 h1:+qIP3OMrT7SN5kLnTcVEISPOMB/97RyAKTg1UWA738E=
github.com/petermattis/goid v0.0.0-20231126143041-f558c26febf5/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -171,8 +171,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
github.com/shirou/gopsutil/v3 v3.23.10 h1:/N42opWlYzegYaVkWejXWJpbzKv2JDy3mrgGzKsh9hM=
github.com/shirou/gopsutil/v3 v3.23.10/go.mod h1:JIE26kpucQi+innVlAUnIEOSBhBUkirr5b44yr55+WE=
github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ=
github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -210,10 +210,10 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No=
golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -233,8 +233,8 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -270,9 +270,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -287,8 +286,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@@ -296,8 +295,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -545,6 +545,7 @@
"light": "Светла"
}
},
"unknown device": "непознато устройство",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} споделя папката „{{folder}}“.",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} споделя папката „{{folderlabel}}“ ({{folder}}).",
"{%reintroducer%} might reintroduce this device.": "Поръчителят {{reintroducer}} може отново да предложи това устройство."

View File

@@ -545,6 +545,7 @@
"light": "Light"
}
},
"unknown device": "unknown device",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} wants to share folder \"{{folder}}\".",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} wants to share folder \"{{folderlabel}}\" ({{folder}}).",
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}} might reintroduce this device."

View File

@@ -26,9 +26,11 @@
"Allow Anonymous Usage Reporting?": "Разрешить анонимный отчет об использовании?",
"Allowed Networks": "Разрешённые сети",
"Alphabetic": "По алфавиту",
"Altered by ignoring deletes.": "Изменено, игнорируя удаления.",
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "Для версионирования используется внешняя программа. Ей нужно удалить файл из общей папки. Если путь к приложению содержит пробелы, его нужно взять в кавычки.",
"Anonymous Usage Reporting": "Анонимный отчет об использовании",
"Anonymous usage report format has changed. Would you like to move to the new format?": "Формат анонимных отчётов изменился. Хотите переключиться на новый формат?",
"Applied to LAN": "Примененоо к LAN",
"Apply": "Применить",
"Are you sure you want to override all remote changes?": "Уверены, что хотите перезаписать все удалённые изменения?",
"Are you sure you want to permanently delete all these files?": "Уверены, что хотите навсегда удалить эти файлы?",
@@ -37,6 +39,7 @@
"Are you sure you want to restore {%count%} files?": "Уверены, что хотите восстановить {{count}} файлов?",
"Are you sure you want to revert all local changes?": "Уверены, что хотите отменить все локальные изменения?",
"Are you sure you want to upgrade?": "Уверены, что хотите обновить?",
"Authentication Required": "Требуется Аутентификация",
"Authors": "Авторы",
"Auto Accept": "Автопринятие",
"Automatic Crash Reporting": "Автоматическая отправка отчётов о сбоях",
@@ -63,6 +66,7 @@
"Configured": "Сконфигурировано",
"Connected (Unused)": "Подключено (не используется)",
"Connection Error": "Ошибка подключения",
"Connection Management": "Управление соединениями",
"Connection Type": "Тип соединения",
"Connections": "Подключения",
"Connections via relays might be rate limited by the relay": "Соединения через промежуточные узлы могут быть ограничены по количеству запросов единицу времени",
@@ -172,10 +176,12 @@
"Forever": "Вечно",
"Full Rescan Interval (s)": "Интервал полного сканирования (в секундах)",
"GUI": "Интерфейс",
"GUI / API HTTPS Certificate": "HTTPS-сертификат GUI/API",
"GUI Authentication Password": "Пароль для доступа к панели управления",
"GUI Authentication User": "Имя пользователя для доступа к панели управления",
"GUI Authentication: Set User and Password": "GUI аутентификация: Установите имя пользователя и пароль",
"GUI Listen Address": "Адрес GUI",
"GUI Override Directory": "Каталог переопределения графического интерфейса",
"GUI Theme": "Тема оформления",
"General": "Общие",
"Generate": "Сгенерировать",
@@ -183,6 +189,7 @@
"Global Discovery Servers": "Серверы глобального обнаружения",
"Global State": "Глобальное состояние",
"Help": "Помощь",
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "Подсказка: обнаруживаются только запрещающие правила, тогда как по умолчанию они отклоняются. Рассмотрите возможность добавления «разрешить любое» в качестве последнего правила.",
"Home page": "Сайт",
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Ваши настройки указывают что вы не хотите, чтобы эта функция была включена. Мы отключили отправку отчетов о сбоях.",
"Identification": "Идентификация",
@@ -198,9 +205,11 @@
"Included Software": "Включенное программное обеспечение",
"Incoming Rate Limit (KiB/s)": "Ограничение входящей скорости (КиБ/с)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Неправильные настройки могут повредить содержимое папок и сделать Syncthing неработоспособным.",
"Incorrect user name or password.": "Неверное имя пользователя или пароль.",
"Internally used paths:": "Внутренние используемые пути:",
"Introduced By": "Рекомендовано",
"Introducer": "Рекомендатель",
"Introduction": "Вступление",
"Inversion of the given condition (i.e. do not exclude)": "Инвертировать текущее условие (например, исключить)",
"Keep Versions": "Количество хранимых версий",
"LDAP": "LDAP",
@@ -226,11 +235,18 @@
"Locally Changed Items": "Объекты, изменённые на этом компьютере",
"Log": "Журнал",
"Log File": "Файл журнала",
"Log In": "Вход",
"Log Out": "Выход",
"Log in to see paths information.": "Войдите, чтобы увидеть информацию о путях.",
"Log in to see version information.": "Войдите, чтобы просмотреть информацию о версии.",
"Log tailing paused. Scroll to the bottom to continue.": "Вывод журнала приостановлен. Прокрутите вниз, чтобы продолжить.",
"Login failed, see Syncthing logs for details.": "Не удалось войти в систему. Посмотреть подробности можно в журнале Syncthing",
"Logs": "Журналы",
"Major Upgrade": "Обновление основной версии",
"Mass actions": "Массовые действия",
"Maximum Age": "Максимальный срок",
"Maximum single entry size": "Максимальный размер одной записи",
"Maximum total size": "Общий максимальный размер",
"Metadata Only": "Только метаданные",
"Minimum Free Disk Space": "Минимальное свободное место на диске",
"Mod. Device": "Изм. устройство",
@@ -247,9 +263,11 @@
"No": "Нет",
"No File Versioning": "Без управления версиями файлов",
"No files will be deleted as a result of this operation.": "В результате этой операции никакие файлы не будут удалены",
"No rules set": "Правила не заданы",
"No upgrades": "Нет обновлений",
"Not shared": "Не зашаренный",
"Notice": "Внимание",
"Number of Connections": "Количество подключений",
"OK": "ОК",
"Off": "Отключить",
"Oldest First": "Сначала старые",
@@ -260,6 +278,8 @@
"Outgoing Rate Limit (KiB/s)": "Ограничение исходящей скорости (КиБ/с)",
"Override": "Перезаписать",
"Override Changes": "Перезаписать изменения",
"Ownership": "Владелец",
"Password": "Пароль",
"Path": "Путь",
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Путь к папке на локальном компьютере. Если её не существует, то она будет создана. Тильда (~) может использоваться как сокращение для",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Путь, в котором нужно хранить версии (оставьте пустым для папки по умолчанию .stversions внутри общей папки).",
@@ -282,6 +302,8 @@
"Preview": "Предварительный просмотр",
"Preview Usage Report": "Посмотреть отчёт об использовании",
"QR code": "QR-код",
"QUIC LAN": "QUIC LAN",
"QUIC WAN": "QUIC WAN",
"Quick guide to supported patterns": "Краткое руководство по поддерживаемым шаблонам",
"Random": "Случайно",
"Receive Encrypted": "Принять шифрованный",
@@ -313,6 +335,7 @@
"Revert": "Обратить",
"Revert Local Changes": "Отменить изменения на этом компьютере",
"Save": "Сохранить",
"Saving changes": "Изменения сохраняются",
"Scan Time Remaining": "Оставшееся время сканирования",
"Scanning": "Сканирование",
"See external versioning help for supported templated command line parameters.": "Поддерживаемые шаблонные параметры командной строки см. в документации сторонней программы контроля версий",
@@ -326,6 +349,7 @@
"Send Extended Attributes": "Отправлять расширенные атрибуты",
"Send Only": "Только отправить",
"Send Ownership": "Отправлять информацию о владельце",
"Set Ignores on Added Folder": "Установить игнорирования для добавленной папки",
"Settings": "Настройки",
"Share": "Предоставить доступ",
"Share Folder": "Предоставить доступ к папке",
@@ -362,9 +386,11 @@
"Statistics": "Статистика",
"Stopped": "Остановлено",
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Хранит и синхронизирует только зашифрованные данные. Папки на всех подключённых устройствах должны быть настроены под один и тот же пароль или иметь тип «{{receiveEncrypted}}».",
"Subject:": "Субьект:",
"Support": "Поддержка",
"Support Bundle": "Данные для поддержки",
"Sync Extended Attributes": "Синхронизировать расширенные атрибуты",
"Sync Ownership": "Синхронизация владений",
"Sync Protocol Listen Addresses": "Адрес протокола синхронизации",
"Sync Status": "Состояние синхронизации",
"Syncing": "Синхронизация",
@@ -376,10 +402,13 @@
"Syncthing is listening on the following network addresses for connection attempts from other devices:": "Syncthing ожидает подключения от других устройств на следующих сетевых адресах:",
"Syncthing is not listening for connection attempts from other devices on any address. Only outgoing connections from this device may work.": "Syncthing не ожидает попыток подключения ни на каких адресах. Только исходящие подключения могут работать на этом устройстве.",
"Syncthing is restarting.": "Перезапуск Syncthing.",
"Syncthing is saving changes.": "Синхронизация это сохранение изменений.",
"Syncthing is upgrading.": "Обновление Syncthing.",
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing теперь поддерживает автоматическую отправку отчетов о сбоях разработчикам. Эта функция включена по умолчанию.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Кажется, Syncthing не запущен или есть проблемы с подключением к Интернету. Переподключаюсь...",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing столкнулся с проблемой при обработке Вашего запроса. Пожалуйста, обновите страницу или перезапустите Syncthing если проблема повторится.",
"TCP LAN": "TCP LAN",
"TCP WAN": "TCP WAN",
"Take me back": "Вернуться к редактированию",
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Эти изменения не вступят в силу, пока адрес панели управления переопределён в настройках запуска.",
"The Syncthing Authors": "Авторы Syncthing",
@@ -406,12 +435,15 @@
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Интервал в секундах для запуска очистки в каталоге версий. Ноль, чтобы отключить периодическую очистку.",
"The maximum age must be a number and cannot be blank.": "Максимальный срок должен быть числом и не может быть пустым.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Максимальный срок хранения версии (в днях, 0 значит вечное хранение).",
"The number of connections must be a non-negative number.": "Количество соединений должно быть неотрицательным.",
"The number of days must be a number and cannot be blank.": "Количество дней должно быть числом и не может быть пустым.",
"The number of days to keep files in the trash can. Zero means forever.": "Количество дней хранения файлов в корзине. Ноль значит навсегда.",
"The number of old versions to keep, per file.": "Количество хранимых версий файла.",
"The number of versions must be a number and cannot be blank.": "Количество версий должно быть числом и не может быть пустым.",
"The path cannot be blank.": "Путь не может быть пустым.",
"The rate limit is applied to the accumulated traffic of all connections to this device.": "Ограничение скорости применяется к накопленному трафику всех подключений к этому устройству.",
"The rate limit must be a non-negative number (0: no limit)": "Скорость должна быть неотрицательным числом (0: нет ограничения)",
"The remote device has not accepted sharing this folder.": "Удаленное устройство не разрешило общий доступ к этой папке.",
"The remote device has paused this folder.": "Удаленное устройство приостановило эту папку.",
"The rescan interval must be a non-negative number of seconds.": "Интервал пересканирования должен быть неотрицательным количеством секунд.",
"There are no devices to share this folder with.": "Нет устройств, для которых будет доступна эта папка.",
@@ -454,7 +486,11 @@
"Usage reporting is always enabled for candidate releases.": "Отправка отчётов об использовании всегда включена для кандидатов в релизы.",
"Use HTTPS for GUI": "Использовать HTTPS для панели управления",
"Use notifications from the filesystem to detect changed items.": "Использовать уведомления от файловой системы для обнаружения изменённых объектов.",
"User": "Пользователь",
"User Home": "Папка пользователя",
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Имя пользователя/пароль не был установлен для GUI-аутентификации. Настройте его.",
"Using a QUIC connection over LAN": "Использование QUIC-соединения по локальной сети",
"Using a QUIC connection over WAN": "Использование QUIC-соединения по всеобщей сети",
"Using a direct TCP connection over LAN": "Использование прямого TCP-соединения через LAN",
"Using a direct TCP connection over WAN": "Использование прямого TCP-соединения через WAN",
"Version": "Версия",
@@ -475,6 +511,7 @@
"Watching for changes discovers most changes without periodic scanning.": "Отслеживание обнаруживает изменения без периодического сканирования.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "Когда добавляете устройство, помните о том, что это же устройство должно быть добавлено и другой стороной.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "Когда добавляете новую папку, помните, что ID папок используются для того, чтобы связывать папки между всеми устройствами. Они чувствительны к регистру и должны совпадать на всех используемых устройствах.",
"When set to more than one on both devices, Syncthing will attempt to establish multiple concurrent connections. If the values differ, the highest will be used. Set to zero to let Syncthing decide.": "Когда установлено значение больше еденицы, Syncthing попытается установить несколько одновременных подключений. Если значения различаются, будет использоваться наибольшее. Установите значение 0, чтобы позволить Syncthing решать самостоятельно.",
"Yes": "Да",
"Yesterday": "Вчера",
"You can also copy and paste the text into a new message manually.": "Вы также можете скопировать и вставить текст в новое сообщение вручную.",
@@ -486,8 +523,11 @@
"You have unsaved changes. Do you really want to discard them?": "Есть несохранённые изменения. Вы действительно хотите отменить их?",
"You must keep at least one version.": "Вы должны хранить как минимум одну версию.",
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "Не добавляйте и не изменяйте ничего локально в папке «{{receiveEncrypted}}».",
"Your SMS app should open to let you choose the recipient and send it from your own number.": "Должно открыться приложение SMS, где вы сможете выбрать получателя и отправителя со своего номера.",
"Your email app should open to let you choose the recipient and send it from your own address.": "Ваше почтовое приложение должно открыться, чтобы вы могли выбрать получателя и отправителя со своего адреса.",
"days": "дней",
"deleted": "удалено",
"deny": "отклонить",
"directories": "папок",
"file": "файл",
"files": "файлов",
@@ -495,6 +535,7 @@
"full documentation": "полная документация",
"items": "элементы",
"modified": "изменено",
"permit": "разрешить",
"seconds": "сек.",
"theme": {
"name": {
@@ -504,6 +545,7 @@
"light": "Светлая"
}
},
"unknown device": "неизвестное устройство",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} хочет поделиться папкой «{{folder}}».",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} хочет поделиться папкой «{{folderlabel}}» ({{folder}}).",
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}} может повторно рекомендовать это устройство."

View File

@@ -37,7 +37,7 @@
"Are you sure you want to revert all local changes?": "Ви впевнені, що бажаєте відкинути всі локальні зміни?",
"Are you sure you want to upgrade?": "Впевнені, що хочете оновитися?",
"Authors": "Автори",
"Auto Accept": "Затверджувати автоматично пропоновані віддаленим пристроєм каталоги",
"Auto Accept": "Автоприймання",
"Automatic Crash Reporting": "Автоматичне звітування про збої",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Автоматиче оновлення зараз дозволяє обирати між стабільними випусками та реліз-кандидатами.",
"Automatic upgrades": "Автоматичні оновлення",

View File

@@ -57,13 +57,16 @@
"Configured": "已設定",
"Connected (Unused)": "已連線(未使用)",
"Connection Error": "連線錯誤",
"Connection Management": "連線管理",
"Connection Type": "連線類型",
"Connections": "連線",
"Connections via relays might be rate limited by the relay": "通過中繼的連線可能會受到中繼的速率限制",
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Syncthing 現在能持續地監視變動了。此機制將偵測到磁碟上的變動並僅對修改過的項目發起掃描。優點是檔案的變動將更快地傳播,並且減少完整掃描的需求。",
"Copied from elsewhere": "從別處複製",
"Copied from original": "從原處複製",
"Copied!": "已複製!",
"Copy": "複製",
"Copy failed! Try to select and copy manually.": "複製失敗!嘗試手動選擇並複製。",
"Currently Shared With Devices": "目前與裝置共享",
"Danger!": "危險!",
"Debugging Facilities": "除錯工具",
@@ -382,6 +385,7 @@
"The number of old versions to keep, per file.": "每個檔案要保留的舊版本數量。",
"The number of versions must be a number and cannot be blank.": "每個檔案要保留的舊版本數量必須是數字且不能為空白。",
"The path cannot be blank.": "路徑不能空白。",
"The rate limit is applied to the accumulated traffic of all connections to this device.": "速率限制會套用到這台裝置所有連線的流量總和。",
"The rate limit must be a non-negative number (0: no limit)": "限制速率必須為非負的數字 (0: 不設限制)",
"The remote device has not accepted sharing this folder.": "遠端裝置尚未接受分享這個資料夾。",
"The remote device has paused this folder.": "遠端裝置已暫停同步此資料夾。",
@@ -442,6 +446,7 @@
"Watching for changes discovers most changes without periodic scanning.": "監視變動會發現大多數變更,而無需定期掃描。",
"When adding a new device, keep in mind that this device must be added on the other side too.": "當新增一個裝置時,務必記住,當前的這個裝置也同樣必須被添加至另一邊。",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "當新增一個資料夾時,請記住,資料夾識別碼是用來將裝置之間的資料夾綁定在一起的。它們有區分大小寫,且必須在所有裝置之間完全相同。",
"When set to more than one on both devices, Syncthing will attempt to establish multiple concurrent connections. If the values differ, the highest will be used. Set to zero to let Syncthing decide.": "當兩台裝置都設定為大於 1 時Syncthing 會嘗試建立多個並行的連線。如果兩台裝置數值不同,最高的數值會被使用。設定為 0 以便讓 Syncthing 自行決定。",
"Yes": "是",
"You can also select one of these nearby devices:": "您亦可從這些附近裝置中擇一:",
"You can change your choice at any time in the Settings dialog.": "您可以在設定對話框中隨時更改您的選擇。",

View File

@@ -47,7 +47,6 @@ import (
"github.com/syncthing/syncthing/lib/discover"
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/ignore"
"github.com/syncthing/syncthing/lib/locations"
"github.com/syncthing/syncthing/lib/logger"
"github.com/syncthing/syncthing/lib/model"
@@ -1349,11 +1348,6 @@ func (s *service) getDBIgnores(w http.ResponseWriter, r *http.Request) {
folder := qs.Get("folder")
lines, patterns, err := s.model.LoadIgnores(folder)
if err != nil && !ignore.IsParseError(err) {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
sendJSON(w, map[string]interface{}{
"ignore": lines,
"expanded": patterns,

View File

@@ -13,6 +13,7 @@ import (
"bytes"
"errors"
"fmt"
"sync"
"syscall"
"github.com/syncthing/syncthing/lib/protocol"
@@ -31,14 +32,13 @@ func (f *BasicFilesystem) GetXattr(path string, xattrFilter XattrFilter) ([]prot
}
res := make([]protocol.Xattr, 0, len(attrs))
var val, buf []byte
var totSize int
for _, attr := range attrs {
if !xattrFilter.Permit(attr) {
l.Debugf("get xattr %s: skipping attribute %q denied by filter", path, attr)
continue
}
val, buf, err = getXattr(path, attr, buf)
val, err := getXattr(path, attr)
var errNo syscall.Errno
if errors.As(err, &errNo) && errNo == 0x5d {
// ENOATTR, returned on BSD when asking for an attribute that
@@ -64,27 +64,52 @@ func (f *BasicFilesystem) GetXattr(path string, xattrFilter XattrFilter) ([]prot
return res, nil
}
func getXattr(path, name string, buf []byte) (val []byte, rest []byte, err error) {
if len(buf) == 0 {
buf = make([]byte, 1024)
}
var xattrBufPool = sync.Pool{
New: func() any { return make([]byte, 1024) },
}
func getXattr(path, name string) ([]byte, error) {
buf := xattrBufPool.Get().([]byte)
defer func() {
// Put the buffer back in the pool, or not if we're not supposed to
// (we returned it to the caller).
if buf != nil {
xattrBufPool.Put(buf)
}
}()
size, err := unix.Lgetxattr(path, name, buf)
if errors.Is(err, unix.ERANGE) {
// Buffer was too small. Figure out how large it needs to be, and
// allocate.
size, err = unix.Lgetxattr(path, name, nil)
if err != nil {
return nil, nil, fmt.Errorf("Lgetxattr %s %q: %w", path, name, err)
return nil, fmt.Errorf("Lgetxattr %s %q: %w", path, name, err)
}
if size > len(buf) {
xattrBufPool.Put(buf)
buf = make([]byte, size)
}
size, err = unix.Lgetxattr(path, name, buf)
}
if err != nil {
return nil, buf, fmt.Errorf("Lgetxattr %s %q: %w", path, name, err)
return nil, fmt.Errorf("Lgetxattr %s %q: %w", path, name, err)
}
return buf[:size], buf[size:], nil
if size >= len(buf)/4*3 {
// The buffer is adequately sized (at least three quarters of it is
// used), return it as-is.
val := buf[:size]
buf = nil // Don't put it back in the pool.
return val, nil
}
// The buffer is larger than required, copy the data to a new buffer of
// the correct size. This avoids having lots of 1024-sized allocations
// sticking around when 24 bytes or whatever would be enough.
val := make([]byte, size)
copy(val, buf)
return val, nil
}
func (f *BasicFilesystem) SetXattr(path string, xattrs []protocol.Xattr, xattrFilter XattrFilter) error {

View File

@@ -88,7 +88,7 @@ func (f *mtimeFS) Stat(name string) (FileInfo, error) {
if err != nil {
return nil, err
}
if mtimeMapping.Real == info.ModTime() {
if mtimeMapping.Real.Equal(info.ModTime()) {
info = mtimeFileInfo{
FileInfo: info,
mtime: mtimeMapping.Virtual,
@@ -108,7 +108,7 @@ func (f *mtimeFS) Lstat(name string) (FileInfo, error) {
if err != nil {
return nil, err
}
if mtimeMapping.Real == info.ModTime() {
if mtimeMapping.Real.Equal(info.ModTime()) {
info = mtimeFileInfo{
FileInfo: info,
mtime: mtimeMapping.Virtual,
@@ -215,7 +215,7 @@ func (f mtimeFile) Stat() (FileInfo, error) {
if err != nil {
return nil, err
}
if mtimeMapping.Real == info.ModTime() {
if mtimeMapping.Real.Equal(info.ModTime()) {
info = mtimeFileInfo{
FileInfo: info,
mtime: mtimeMapping.Virtual,

View File

@@ -465,7 +465,7 @@ func (m *model) warnAboutOverwritingProtectedFiles(cfg config.FolderConfiguratio
func (m *model) removeFolder(cfg config.FolderConfiguration) {
m.fmut.RLock()
wait := m.folderRunners.RemoveAndWaitChan(cfg.ID, 0)
wait := m.folderRunners.StopAndWaitChan(cfg.ID, 0)
m.fmut.RUnlock()
<-wait
@@ -507,6 +507,7 @@ func (m *model) removeFolder(cfg config.FolderConfiguration) {
// Need to hold lock on m.fmut when calling this.
func (m *model) cleanupFolderLocked(cfg config.FolderConfiguration) {
// clear up our config maps
m.folderRunners.Remove(cfg.ID)
delete(m.folderCfgs, cfg.ID)
delete(m.folderFiles, cfg.ID)
delete(m.folderIgnores, cfg.ID)
@@ -536,7 +537,7 @@ func (m *model) restartFolder(from, to config.FolderConfiguration, cacheIgnoredF
defer restartMut.Unlock()
m.fmut.RLock()
wait := m.folderRunners.RemoveAndWaitChan(from.ID, 0)
wait := m.folderRunners.StopAndWaitChan(from.ID, 0)
m.fmut.RUnlock()
<-wait
@@ -817,6 +818,11 @@ func (m *model) DeviceStatistics() (map[protocol.DeviceID]stats.DeviceStatistics
if err != nil {
return nil, err
}
if len(m.deviceConnIDs[id]) > 0 {
// If a device is currently connected, we can see them right
// now.
stats.LastSeen = time.Now().Truncate(time.Second)
}
res[id] = stats
}
return res, nil
@@ -2483,6 +2489,7 @@ func (m *model) deviceWasSeen(deviceID protocol.DeviceID) {
func (m *model) deviceDidCloseFRLocked(deviceID protocol.DeviceID, duration time.Duration) {
if sr, ok := m.deviceStatRefs[deviceID]; ok {
_ = sr.LastConnectionDuration(duration)
_ = sr.WasSeen()
}
}

View File

@@ -46,7 +46,6 @@ func (s *serviceMap[K, S]) Add(k K, v S) {
if tok, ok := s.tokens[k]; ok {
// There is already a service at this key, remove it first.
s.supervisor.Remove(tok)
s.eventLogger.Log(events.Failure, fmt.Sprintf("%s replaced service at key %v", s, k))
}
s.services[k] = v
s.tokens[k] = s.supervisor.Add(v)
@@ -59,6 +58,34 @@ func (s *serviceMap[K, S]) Get(k K) (v S, ok bool) {
return
}
// Stop removes the service at the given key from the supervisor, stopping it.
// The service itself is still retained, i.e. a call to Get with the same key
// will still return a result.
func (s *serviceMap[K, S]) Stop(k K) {
if tok, ok := s.tokens[k]; ok {
s.supervisor.Remove(tok)
}
return
}
// StopAndWaitChan removes the service at the given key from the supervisor,
// stopping it. The service itself is still retained, i.e. a call to Get with
// the same key will still return a result.
// The returned channel will produce precisely one error value: either the
// return value from RemoveAndWait (possibly nil), or errSvcNotFound if the
// service was not found.
func (s *serviceMap[K, S]) StopAndWaitChan(k K, timeout time.Duration) <-chan error {
ret := make(chan error, 1)
if tok, ok := s.tokens[k]; ok {
go func() {
ret <- s.supervisor.RemoveAndWait(tok, timeout)
}()
} else {
ret <- errSvcNotFound
}
return ret
}
// Remove removes the service at the given key, stopping it on the supervisor.
// If there is no service at the given key, nothing happens. The return value
// indicates whether a service was removed.
@@ -66,6 +93,8 @@ func (s *serviceMap[K, S]) Remove(k K) (found bool) {
if tok, ok := s.tokens[k]; ok {
found = true
s.supervisor.Remove(tok)
} else {
_, found = s.services[k]
}
delete(s.services, k)
delete(s.tokens, k)
@@ -84,16 +113,8 @@ func (s *serviceMap[K, S]) RemoveAndWait(k K, timeout time.Duration) error {
// value: either the return value from RemoveAndWait (possibly nil), or
// errSvcNotFound if the service was not found.
func (s *serviceMap[K, S]) RemoveAndWaitChan(k K, timeout time.Duration) <-chan error {
ret := make(chan error, 1)
if tok, ok := s.tokens[k]; ok {
go func() {
ret <- s.supervisor.RemoveAndWait(tok, timeout)
}()
} else {
ret <- errSvcNotFound
}
ret := s.StopAndWaitChan(k, timeout)
delete(s.services, k)
delete(s.tokens, k)
return ret
}

View File

@@ -688,6 +688,13 @@ func CreateFileInfo(fi fs.FileInfo, name string, filesystem fs.Filesystem, scanO
return protocol.FileInfo{}, fmt.Errorf("reading platform data: %w", err)
}
}
if ct := fi.InodeChangeTime(); !ct.IsZero() {
f.InodeChangeNs = ct.UnixNano()
} else {
f.InodeChangeNs = 0
}
if fi.IsSymlink() {
f.Type = protocol.FileInfoTypeSymlink
target, err := filesystem.ReadSymlink(name)
@@ -698,19 +705,18 @@ func CreateFileInfo(fi fs.FileInfo, name string, filesystem fs.Filesystem, scanO
f.NoPermissions = true // Symlinks don't have permissions of their own
return f, nil
}
f.Permissions = uint32(fi.Mode() & fs.ModePerm)
f.ModifiedS = fi.ModTime().Unix()
f.ModifiedNs = fi.ModTime().Nanosecond()
if fi.IsDir() {
f.Type = protocol.FileInfoTypeDirectory
return f, nil
}
f.Size = fi.Size()
f.Type = protocol.FileInfoTypeFile
if ct := fi.InodeChangeTime(); !ct.IsZero() {
f.InodeChangeNs = ct.UnixNano()
} else {
f.InodeChangeNs = 0
}
return f, nil
}

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "STDISCOSRV" "1" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "STDISCOSRV" "1" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
stdiscosrv \- Syncthing Discovery Server
.SH SYNOPSIS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "STRELAYSRV" "1" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "STRELAYSRV" "1" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
strelaysrv \- Syncthing Relay Server
.SH SYNOPSIS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-BEP" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-BEP" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-bep \- Block Exchange Protocol v1
.SH INTRODUCTION AND DEFINITIONS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-CONFIG" "5" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-CONFIG" "5" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-config \- Syncthing Configuration
.SH SYNOPSIS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-DEVICE-IDS" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-DEVICE-IDS" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-device-ids \- Understanding Device IDs
.sp

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-EVENT-API" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-EVENT-API" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-event-api \- Event API
.SH DESCRIPTION

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-FAQ" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-FAQ" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-faq \- Frequently Asked Questions
.INDENT 0.0

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-GLOBALDISCO" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-GLOBALDISCO" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-globaldisco \- Global Discovery Protocol v3
.SH ANNOUNCEMENTS

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-LOCALDISCO" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-LOCALDISCO" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-localdisco \- Local Discovery Protocol v4
.SH MODE OF OPERATION

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-NETWORKING" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-NETWORKING" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-networking \- Firewall Setup
.SH ROUTER SETUP

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-RELAY" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-RELAY" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-relay \- Relay Protocol v1
.SH WHAT IS A RELAY?

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-REST-API" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-REST-API" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-rest-api \- REST API
.sp

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-SECURITY" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-SECURITY" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-security \- Security Principles
.sp

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-STIGNORE" "5" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-STIGNORE" "5" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-stignore \- Prevent files from being synchronized to other nodes
.SH SYNOPSIS
@@ -44,12 +44,12 @@ syncthing-stignore \- Prevent files from being synchronized to other nodes
.SH DESCRIPTION
.sp
If some files should not be synchronized to (or from) other devices, a file called
\fB\&.stignore\fP can be created containing file patterns to ignore. The
\fB\&.stignore\fP file must be placed in the root of the synced folder. The
\fB\&.stignore\fP file itself will never be synced to other devices, although it can
\fB#include\fP files that \fIare\fP synchronized between devices. All patterns are
relative to the synced folder root.
The contents of the \fB\&.stignore\fP file must be UTF\-8 encoded.
\fB\&.stignore\fP can be created containing file patterns to ignore. The \fB\&.stignore\fP
file must be placed in the root of the synced folder (files in other locations are
not applied). The \fB\&.stignore\fP file itself will never be synced to other devices,
although it can \fB#include\fP files that \fIare\fP synchronized between devices. All
patterns are relative to the synced folder root. The contents of the \fB\&.stignore\fP
file must be UTF\-8 encoded.
.sp
\fBNOTE:\fP
.INDENT 0.0
@@ -115,8 +115,9 @@ patterns from a file in a subdirectory, the patterns themselves are
still relative to the synced folder \fIroot\fP\&. Example:
\fB#include more\-patterns.txt\fP\&.
.sp
Any \fB#include\fP directives inside a file loaded by \fB#include\fP require paths specified relative
to the directory containing the loaded file, rather than the synchronised root directory.
Any \fB#include\fP directives inside a file loaded by \fB#include\fP require paths
specified relative to the directory containing the loaded file, rather than the
synchronised root directory.
.IP \(bu 2
A pattern beginning with a \fB!\fP prefix negates the pattern: matching files
are \fIincluded\fP (that is, \fInot\fP ignored). This can be used to override

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING-VERSIONING" "7" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING-VERSIONING" "7" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing-versioning \- Keep automatic backups of deleted files by other nodes
.sp

View File

@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "SYNCTHING" "1" "Nov 22, 2023" "v1.26.0" "Syncthing"
.TH "SYNCTHING" "1" "Dec 01, 2023" "v1.26.0" "Syncthing"
.SH NAME
syncthing \- Syncthing
.SH SYNOPSIS