mirror of
https://github.com/syncthing/syncthing.git
synced 2025-12-24 06:28:10 -05:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f0acacbd2 | ||
|
|
932b4ce9bd | ||
|
|
b3e3ca7294 | ||
|
|
41b4c5cd5e | ||
|
|
eb4eb7524d | ||
|
|
a64c5396e9 | ||
|
|
5595113074 | ||
|
|
ea19ec64bf | ||
|
|
9de6c5ed69 | ||
|
|
d037681fd1 | ||
|
|
1b0eaa093a | ||
|
|
3382ccc3f1 | ||
|
|
9ee208b441 | ||
|
|
dd90e8ec7a | ||
|
|
aa6ae0f3b0 | ||
|
|
e8b256793a | ||
|
|
8233279a65 | ||
|
|
8e5d5802cc | ||
|
|
25ae01b0d7 | ||
|
|
66583927f8 | ||
|
|
f0328abeaa | ||
|
|
4b8d07d91c | ||
|
|
c33daca3b4 | ||
|
|
a533f453f8 |
4
.github/workflows/build-infra-dockers.yaml
vendored
4
.github/workflows/build-infra-dockers.yaml
vendored
@@ -30,11 +30,11 @@ jobs:
|
||||
- stupgrades
|
||||
- ursrv
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
check-latest: true
|
||||
|
||||
68
.github/workflows/build-syncthing.yaml
vendored
68
.github/workflows/build-syncthing.yaml
vendored
@@ -51,12 +51,12 @@ jobs:
|
||||
release-generation: ${{ steps.get-version.outputs.release-generation }}
|
||||
go-version: ${{ steps.get-go.outputs.go-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
@@ -116,9 +116,9 @@ jobs:
|
||||
git config --global core.autocrlf false
|
||||
git config --global core.eol lf
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
cache: true
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
- golangci
|
||||
- meta
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
#
|
||||
# Windows
|
||||
@@ -183,9 +183,9 @@ jobs:
|
||||
VERSION: ${{ needs.facts.outputs.version }}
|
||||
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -292,9 +292,9 @@ jobs:
|
||||
VERSION: ${{ needs.facts.outputs.version }}
|
||||
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -347,7 +347,7 @@ jobs:
|
||||
VERSION: ${{ needs.facts.outputs.version }}
|
||||
GO_VERSION: ${{ needs.facts.outputs.go-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Build syncthing in OmniOS VM
|
||||
uses: vmactions/omnios-vm@v1
|
||||
@@ -389,9 +389,9 @@ jobs:
|
||||
VERSION: ${{ needs.facts.outputs.version }}
|
||||
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -517,9 +517,9 @@ jobs:
|
||||
VERSION: ${{ needs.facts.outputs.version }}
|
||||
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -584,9 +584,9 @@ jobs:
|
||||
VERSION: ${{ needs.facts.outputs.version }}
|
||||
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -633,9 +633,9 @@ jobs:
|
||||
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
repository: syncthing/release-tools
|
||||
path: tools
|
||||
@@ -643,7 +643,7 @@ jobs:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -714,9 +714,9 @@ jobs:
|
||||
VERSION: ${{ needs.facts.outputs.version }}
|
||||
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -770,7 +770,7 @@ jobs:
|
||||
- facts
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
repository: syncthing/release-tools
|
||||
path: tools
|
||||
@@ -781,7 +781,7 @@ jobs:
|
||||
name: packages-signed
|
||||
path: packages
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -825,7 +825,7 @@ jobs:
|
||||
RELEASE_KIND: ${{ needs.facts.outputs.release-kind }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
|
||||
@@ -842,7 +842,7 @@ jobs:
|
||||
name: debian-packages
|
||||
path: packages
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -1004,9 +1004,9 @@ jobs:
|
||||
dockerfile: Dockerfile.stdiscosrv
|
||||
image: discosrv
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -1099,7 +1099,7 @@ jobs:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Sync images
|
||||
uses: docker://docker.io/regclient/regsync:latest
|
||||
with:
|
||||
@@ -1117,9 +1117,9 @@ jobs:
|
||||
needs:
|
||||
- facts
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ needs.facts.outputs.go-version }}
|
||||
cache: false
|
||||
@@ -1139,8 +1139,8 @@ jobs:
|
||||
name: Run golangci-lint
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: 'stable'
|
||||
|
||||
@@ -1160,8 +1160,8 @@ jobs:
|
||||
name: Run meta checks
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: 'stable'
|
||||
|
||||
|
||||
4
.github/workflows/release-syncthing.yaml
vendored
4
.github/workflows/release-syncthing.yaml
vendored
@@ -15,13 +15,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
environment: release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.ref }} # https://github.com/actions/checkout/issues/882
|
||||
token: ${{ secrets.ACTIONS_GITHUB_TOKEN }}
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: stable
|
||||
|
||||
|
||||
3
.github/workflows/trigger-nightly.yaml
vendored
3
.github/workflows/trigger-nightly.yaml
vendored
@@ -8,11 +8,12 @@ on:
|
||||
jobs:
|
||||
|
||||
trigger-nightly:
|
||||
if: github.repository_owner == 'syncthing'
|
||||
runs-on: ubuntu-latest
|
||||
name: Push to release-nightly to trigger build
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
token: ${{ secrets.ACTIONS_GITHUB_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -10,11 +10,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Update translations and documentation
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.ACTIONS_GITHUB_TOKEN }}
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: stable
|
||||
- run: |
|
||||
|
||||
19
.policy.yml
19
.policy.yml
@@ -8,17 +8,20 @@
|
||||
policy:
|
||||
approval:
|
||||
- subject is conventional commit
|
||||
- project metadata requires maintainer approval
|
||||
- or:
|
||||
- project metadata requires maintainer approval
|
||||
- a maintainer claims responsibility
|
||||
- or:
|
||||
- is approved by a syncthing contributor
|
||||
- is a translation or dependency update by a contributor
|
||||
- is a trivial change by a contributor
|
||||
- a maintainer claims responsibility
|
||||
|
||||
# Additionally, contributors can disapprove of a PR
|
||||
# Additionally, maintainers can disapprove of a PR
|
||||
disapproval:
|
||||
requires:
|
||||
teams:
|
||||
- syncthing/contributors
|
||||
- syncthing/maintainers
|
||||
|
||||
# The rules for the policy are described below.
|
||||
|
||||
@@ -96,3 +99,13 @@ approval_rules:
|
||||
has_author_in:
|
||||
teams:
|
||||
- syncthing/contributors
|
||||
|
||||
# A member of the maintainers group can take responsibility by adding the
|
||||
# appropriate label.
|
||||
- name: a maintainer claims responsibility
|
||||
if:
|
||||
has_labels:
|
||||
- maintainer-responsibility
|
||||
has_author_in:
|
||||
teams:
|
||||
- syncthing/maintainers
|
||||
|
||||
@@ -8,6 +8,7 @@ package serve
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"reflect"
|
||||
"slices"
|
||||
@@ -335,12 +336,12 @@ func (q *metricSummary) Collect(c chan<- prometheus.Metric) {
|
||||
}
|
||||
|
||||
slices.Sort(vs)
|
||||
c <- prometheus.MustNewConstMetric(q.qDesc, prometheus.GaugeValue, vs[0], append(labelVals, "0")...)
|
||||
c <- prometheus.MustNewConstMetric(q.qDesc, prometheus.GaugeValue, vs[len(vs)*5/100], append(labelVals, "0.05")...)
|
||||
c <- prometheus.MustNewConstMetric(q.qDesc, prometheus.GaugeValue, vs[len(vs)/2], append(labelVals, "0.5")...)
|
||||
c <- prometheus.MustNewConstMetric(q.qDesc, prometheus.GaugeValue, vs[len(vs)*9/10], append(labelVals, "0.9")...)
|
||||
c <- prometheus.MustNewConstMetric(q.qDesc, prometheus.GaugeValue, vs[len(vs)*95/100], append(labelVals, "0.95")...)
|
||||
c <- prometheus.MustNewConstMetric(q.qDesc, prometheus.GaugeValue, vs[len(vs)-1], append(labelVals, "1")...)
|
||||
|
||||
pctiles := []float64{0, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.975, 0.99, 1}
|
||||
for _, pct := range pctiles {
|
||||
idx := int(float64(len(vs)-1) * pct)
|
||||
c <- prometheus.MustNewConstMetric(q.qDesc, prometheus.GaugeValue, vs[idx], append(labelVals, fmt.Sprint(pct))...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,8 @@ var (
|
||||
{regexp.MustCompile(`\svagrant@bullseye`), "F-Droid"},
|
||||
{regexp.MustCompile(`\svagrant@bookworm`), "F-Droid"},
|
||||
|
||||
{regexp.MustCompile(`Anwender@NET2017`), "Syncthing-Fork (3rd party)"},
|
||||
{regexp.MustCompile(`\sreproducible-build@Catfriend1-syncthing-android`), "Syncthing-Fork Catfriend1 (3rd party)"},
|
||||
{regexp.MustCompile(`\sreproducible-build@nel0x-syncthing-android-gplay`), "Syncthing-Fork nel0x (3rd party)"},
|
||||
|
||||
{regexp.MustCompile(`\sbuilduser@(archlinux|svetlemodry)`), "Arch (3rd party)"},
|
||||
{regexp.MustCompile(`\ssyncthing@archlinux`), "Arch (3rd party)"},
|
||||
|
||||
@@ -781,40 +781,39 @@ func initialAutoUpgradeCheck(misc *db.Typed) (upgrade.Release, error) {
|
||||
// suitable time after they have gone out of fashion.
|
||||
func cleanConfigDirectory() {
|
||||
patterns := map[string]time.Duration{
|
||||
"panic-*.log": 7 * 24 * time.Hour, // keep panic logs for a week
|
||||
"audit-*.log": 7 * 24 * time.Hour, // keep audit logs for a week
|
||||
"index": 14 * 24 * time.Hour, // keep old index format for two weeks
|
||||
"index-v0.11.0.db": 14 * 24 * time.Hour, // keep old index format for two weeks
|
||||
"index-v0.13.0.db": 14 * 24 * time.Hour, // keep old index format for two weeks
|
||||
"index*.converted": 14 * 24 * time.Hour, // keep old converted indexes for two weeks
|
||||
"config.xml.v*": 30 * 24 * time.Hour, // old config versions for a month
|
||||
"*.idx.gz": 30 * 24 * time.Hour, // these should for sure no longer exist
|
||||
"backup-of-v0.8": 30 * 24 * time.Hour, // these neither
|
||||
"tmp-index-sorter.*": time.Minute, // these should never exist on startup
|
||||
"support-bundle-*": 30 * 24 * time.Hour, // keep old support bundle zip or folder for a month
|
||||
"csrftokens.txt": 0, // deprecated, remove immediately
|
||||
"panic-*.log": 7 * 24 * time.Hour, // keep panic logs for a week
|
||||
"audit-*.log": 7 * 24 * time.Hour, // keep audit logs for a week
|
||||
"index-v0.14.0.db-migrated": 14 * 24 * time.Hour, // keep old index format for two weeks
|
||||
"config.xml.v*": 30 * 24 * time.Hour, // old config versions for a month
|
||||
"support-bundle-*": 30 * 24 * time.Hour, // keep old support bundle zip or folder for a month
|
||||
}
|
||||
|
||||
for pat, dur := range patterns {
|
||||
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, locations.GetBaseDir(locations.ConfigBaseDir))
|
||||
files, err := fs.Glob(pat)
|
||||
if err != nil {
|
||||
slog.Warn("Failed to clean config directory", slogutil.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
info, err := fs.Lstat(file)
|
||||
locations := slices.Compact([]string{
|
||||
locations.GetBaseDir(locations.ConfigBaseDir),
|
||||
locations.GetBaseDir(locations.DataBaseDir),
|
||||
})
|
||||
for _, loc := range locations {
|
||||
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, loc)
|
||||
for pat, dur := range patterns {
|
||||
entries, err := fs.Glob(pat)
|
||||
if err != nil {
|
||||
slog.Warn("Failed to clean config directory", slogutil.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
if time.Since(info.ModTime()) > dur {
|
||||
if err = fs.RemoveAll(file); err != nil {
|
||||
for _, entry := range entries {
|
||||
info, err := fs.Lstat(entry)
|
||||
if err != nil {
|
||||
slog.Warn("Failed to clean config directory", slogutil.Error(err))
|
||||
} else {
|
||||
slog.Warn("Cleaned away old file", slogutil.FilePath(filepath.Base(file)))
|
||||
continue
|
||||
}
|
||||
|
||||
if time.Since(info.ModTime()) > dur {
|
||||
if err = fs.RemoveAll(entry); err != nil {
|
||||
slog.Warn("Failed to clean config directory", slogutil.Error(err))
|
||||
} else {
|
||||
slog.Warn("Cleaned away old file", slogutil.FilePath(filepath.Base(entry)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/locations"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
@@ -61,7 +62,7 @@ func savePerfStats(file string) {
|
||||
rss,
|
||||
rate(prevIn, in, timeDiff, 1e3),
|
||||
rate(prevOut, out, timeDiff, 1e3),
|
||||
dirsize(locations.Get(locations.Database))/1024,
|
||||
osutil.DirSize(locations.Get(locations.Database))/1024,
|
||||
)
|
||||
|
||||
prevTime = t
|
||||
@@ -84,21 +85,3 @@ func rate[T number](prev, cur T, d time.Duration, div float64) float64 {
|
||||
rate := float64(diff) / d.Seconds() / div
|
||||
return rate
|
||||
}
|
||||
|
||||
func dirsize(location string) int64 {
|
||||
entries, err := os.ReadDir(location)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
var size int64
|
||||
for _, entry := range entries {
|
||||
fi, err := entry.Info()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
size += fi.Size()
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"Allowed Networks": "Дазволеныя Сеткі",
|
||||
"Alphabetic": "Па Алфавіту",
|
||||
"Altered by ignoring deletes.": "Зменена з-за ігнаравання выдаленняў.",
|
||||
"Always turned on when the folder type is \"{%foldertype%}\".": "Заўсёды ўключана для папак з тыпам \"{{foldertype}}\".",
|
||||
"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?": "Фармат ананімнай спрадвыздачы аб выкарыстанні быў зменены. Ці жадаеце вы выкарыстоўваць новы фармат?",
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Вида „{{receiveEncrypted}}“ може да бъде избран само при добавяне на папка.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Видът папката „{{receiveEncrypted}}“ не може да бъде променян след нейното създаване. Трябва да я премахнете, изтриете или разшифровате съдържанието и да добавите папката отново.",
|
||||
"Folders": "Папки",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "Грешка при започване на наблюдението за промени на следните папки. Всяка минута ще бъде извършван нов опит, така че грешката скоро може да изчезне. Ако все пак не изчезне, отстранете нейната първопричина или потърсете помощ ако не съумявате.",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "Грешка при започване на наблюдението за промени на следните папки. Всяка минута ще бъде извършван нов опит, така че грешката скоро може да изчезне. Ако все пак не изчезне, отстранете първопричината или ако не съумявате потърсете помощ.",
|
||||
"Forever": "Завинаги",
|
||||
"Full Rescan Interval (s)": "Интервал на пълно обхождане (секунди)",
|
||||
"GUI": "Интерфейс",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"Allowed Networks": "Redes permitidas",
|
||||
"Alphabetic": "Alfabético",
|
||||
"Altered by ignoring deletes.": "Alterado ignorando eliminaciones.",
|
||||
"Always turned on when the folder type is \"{%foldertype%}\".": "Siempre activado cuando el tipo de carpeta es \"{{foldertype}}\".",
|
||||
"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.": "Un comando externo maneja las versiones. Tienes que eliminar el archivo de la carpeta compartida. Si la ruta a la aplicación contiene espacios, ésta debe estar entre comillas.",
|
||||
"Anonymous Usage Reporting": "Informe anónimo de uso",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "El formato del informe de uso anónimo a cambiado. ¿Le gustaría pasar al nuevo formato?",
|
||||
@@ -52,6 +53,7 @@
|
||||
"Body:": "Contenido:",
|
||||
"Bugs": "Errores",
|
||||
"Cancel": "Cancelar",
|
||||
"Cannot be enabled when the folder type is \"{%foldertype%}\".": "No se puede habilitar cuando el tipo de carpeta es \"{{foldertype}}\".",
|
||||
"Changelog": "Registro de cambios",
|
||||
"Clean out after": "Limpiar tras",
|
||||
"Cleaning Versions": "Limpiando Versiones",
|
||||
@@ -80,6 +82,7 @@
|
||||
"Custom Range": "Rango personalizado",
|
||||
"Danger!": "¡Peligro!",
|
||||
"Database Location": "Ubicación de la base de datos",
|
||||
"Debug": "Depurar",
|
||||
"Debugging Facilities": "Servicios de depuración",
|
||||
"Default": "Predeterminado",
|
||||
"Default Configuration": "Configuración Predeterminada",
|
||||
@@ -208,6 +211,7 @@
|
||||
"Incoming Rate Limit (KiB/s)": "Límite de descarga (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Una configuración incorrecta puede corromper el contenido de la carpeta y poner a Syncthing en un estado inoperante.",
|
||||
"Incorrect user name or password.": "Nombre de usuario o contraseña incorrectos.",
|
||||
"Info": "Información",
|
||||
"Internally used paths:": "Rutas de uso interno:",
|
||||
"Introduced By": "Introducido por",
|
||||
"Introducer": "Presentador",
|
||||
@@ -225,6 +229,7 @@
|
||||
"Learn more": "Saber más",
|
||||
"Learn more at {%url%}": "Más información en {{url}}",
|
||||
"Limit": "Límite",
|
||||
"Limit Bandwidth in LAN": "Limitar el ancho de banda en LAN",
|
||||
"Listener Failures": "Fallos de Oyente",
|
||||
"Listener Status": "Estado de Oyente",
|
||||
"Listeners": "Oyentes",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"A device with that ID is already added.": "Sellise tunnusega seade on juba lisatud.",
|
||||
"A negative number of days doesn't make sense.": "Negatiivne päevade arv ei ole loogiline.",
|
||||
"A new major version may not be compatible with previous versions.": "Uus põhiversioon ei pruugi ühilduv varasemate versioonidega.",
|
||||
"API Key": "API võti",
|
||||
"About": "Rakenduse teave",
|
||||
"Action": "Tegevus",
|
||||
@@ -19,20 +20,34 @@
|
||||
"Apply": "Rakenda",
|
||||
"Automatic upgrades": "Automaatsed uuendused",
|
||||
"Be careful!": "Ettevaatust!",
|
||||
"Cancel": "Loobu",
|
||||
"Changelog": "Muudatuste nimekiri",
|
||||
"Bugs": "Vead",
|
||||
"Cancel": "Katkesta",
|
||||
"Cannot be enabled when the folder type is \"{%foldertype%}\".": "Kui kausta tüüp on „{{foldertype}}“, siis seda ei saa kasutada.",
|
||||
"Changelog": "Muudatuste ajalugu",
|
||||
"Close": "Sulge",
|
||||
"Compression": "Pakkimine",
|
||||
"Configuration Directory": "Seadistuste kaust",
|
||||
"Configuration File": "Seadistuste fail",
|
||||
"Configured": "Seadistatud",
|
||||
"Connected (Unused)": "Ühendatud (pole kasutusel)",
|
||||
"Connection Error": "Ühenduse viga",
|
||||
"Connection Management": "Ühenduste haldus",
|
||||
"Connection Type": "Ühenduse tüüp",
|
||||
"Connections": "Ühendused",
|
||||
"Copied from elsewhere": "Kopeeritud mujalt",
|
||||
"Copied from original": "Kopeeritud algallikast",
|
||||
"Copied!": "Kopeeritud!",
|
||||
"Delete": "Kustuta",
|
||||
"Device": "Seade",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Seade \"{{name}}\" ({{device}} aadressil {{address}}) soovib luua ühendust. Kas lisada uus seade?",
|
||||
"Device ID": "Seadme ID",
|
||||
"Device Certificate": "Seadme sertifikaat",
|
||||
"Device ID": "Seadme tunnus",
|
||||
"Device Identification": "Seadme tuvastamine",
|
||||
"Device Name": "Seadme nimi",
|
||||
"Devices": "Seadmed",
|
||||
"Disconnected": "Ühendus puudub",
|
||||
"Do not restore": "Ära taasta",
|
||||
"Do not restore all": "Ära taasta kõiki",
|
||||
"Documentation": "Dokumentatsioon",
|
||||
"Download Rate": "Allalaadimise Kiirus",
|
||||
"Downloaded": "Alla laetud",
|
||||
@@ -55,33 +70,48 @@
|
||||
"GUI Authentication User": "GUI Autentimise Kasutajatunnus",
|
||||
"GUI Theme": "GUI Teema",
|
||||
"Generate": "Genereeri",
|
||||
"Global State": "Globaalne Olek",
|
||||
"Help": "Abi",
|
||||
"Global State": "Üldine olek",
|
||||
"Help": "Abiteave",
|
||||
"Ignore": "Ignoreeri",
|
||||
"Ignore Patterns": "Ignoreeri Mustreid",
|
||||
"Ignore Permissions": "Ignoreeri Õigusi",
|
||||
"Incoming Rate Limit (KiB/s)": "Siseneva Kiiruse Piirang (KiB/s)",
|
||||
"Ignored Devices": "Eiratud seadmed",
|
||||
"Ignored Folders": "Eiratud kaustad",
|
||||
"Incoming Rate Limit (KiB/s)": "Siseneva liikluse kiiruspiirang (KiB/s)",
|
||||
"Keep Versions": "Säilita Versioone",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Suurim Enne",
|
||||
"Last 30 Days": "Viimased 30 päeva",
|
||||
"Last 7 Days": "Viimased 7 päeva",
|
||||
"Last Month": "Viimane kuu",
|
||||
"Last Scan": "Viimane skaneerimine",
|
||||
"Last seen": "Viimati nähtud",
|
||||
"Latest Change": "Viimane Muudatus",
|
||||
"Learn more": "Veel infot",
|
||||
"Learn more at {%url%}": "Lisateavet leiad siit: {{url}}",
|
||||
"Local State": "Kohalik Olek",
|
||||
"Local State (Total)": "Kohalik Olek (Summaarne)",
|
||||
"Maximum Age": "Maksimaalne Vanus",
|
||||
"Metadata Only": "Ainult Meta-andmed",
|
||||
"Maximum Age": "Maksimaalne vanus",
|
||||
"Maximum single entry size": "Maksimaalne ühe objekti maht",
|
||||
"Maximum total size": "Maksimaalne kogumaht",
|
||||
"Metadata Only": "Ainult metaandmed",
|
||||
"Minimum Free Disk Space": "Minimaalne Vaba Kettaruum",
|
||||
"More than a month ago": "Enam, kui kuu tagasi",
|
||||
"More than a week ago": "Enam, kui nädal tagasi",
|
||||
"More than a year ago": "Enam, kui aasta tagasi",
|
||||
"Move to top of queue": "Liiguta järjekorra algusesse",
|
||||
"Never": "Eikunagi",
|
||||
"New Device": "Uus Seade",
|
||||
"New Folder": "Uus Kaust",
|
||||
"Newest First": "Uusimad Ennem",
|
||||
"No": "Ei",
|
||||
"Number of Connections": "Ühenduste arv",
|
||||
"OK": "Sobib",
|
||||
"Oldest First": "Vanimad Ennem",
|
||||
"Options": "Valikud",
|
||||
"Outgoing Rate Limit (KiB/s)": "Väljuva Kiiruse Piirang (KiB/s)",
|
||||
"Out of Sync": "Pole sünkroonis",
|
||||
"Out of Sync Items": "Sünkroonimata objektid",
|
||||
"Outgoing Rate Limit (KiB/s)": "Väljuva kiiruse piirang (KiB/s)",
|
||||
"Override Changes": "Kirjuta Muudatused Üle",
|
||||
"Pause": "Peata",
|
||||
"Pause All": "Peata Kõik",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"A device with that ID is already added.": "May naidagdag na device na may ganitong ding ID.",
|
||||
"A negative number of days doesn't make sense.": "Walang saysay ang negatibong numero ng araw.",
|
||||
"A new major version may not be compatible with previous versions.": "Maaring hindi compatible ang isang bagong major na beryson sa mga nakaraang bersyon.",
|
||||
"A device with that ID is already added.": "May naidagdag na device na may ganito ring ID.",
|
||||
"A negative number of days doesn't make sense.": "Walang saysay ang negatibong bilang ng araw.",
|
||||
"A new major version may not be compatible with previous versions.": "Maaring hindi compatible ang isang bagong major na bersiyon sa mga nakaraang bersiyon.",
|
||||
"API Key": "API Key",
|
||||
"About": "Tungkol sa",
|
||||
"Action": "Aksyon",
|
||||
"Actions": "Mga Aksyon",
|
||||
"Action": "Aksiyon",
|
||||
"Actions": "Mga Aksiyon",
|
||||
"Active filter rules": "Mga aktibong tuntunin sa pag-filter",
|
||||
"Add": "Magdagdag",
|
||||
"Add Device": "Magdagdag ng Device",
|
||||
@@ -56,7 +56,7 @@
|
||||
"Cannot be enabled when the folder type is \"{%foldertype%}\".": "Hindi maaaring paganahin kapag ang uri ng folder ay \"{{foldertype}}\".",
|
||||
"Changelog": "Mga Pagbabago",
|
||||
"Clean out after": "Linisin pagkatapos",
|
||||
"Cleaning Versions": "Mga Bersyon ng Paglinis",
|
||||
"Cleaning Versions": "Mga Bersiyon ng Paglinis",
|
||||
"Cleanup Interval": "Pagitan ng Paglinis",
|
||||
"Click to see full identification string and QR code.": "I-click upang makita ang buong string ng pagkakakilanlan at QR code.",
|
||||
"Close": "Isara",
|
||||
@@ -155,14 +155,14 @@
|
||||
"External": "Panlabas",
|
||||
"External File Versioning": "Panlabas na File Versioning",
|
||||
"Failed Items": "Mga Nabigong Item",
|
||||
"Failed to load file versions.": "Nabigong i-load ang mga bersyon ng file.",
|
||||
"Failed to load file versions.": "Nabigong i-load ang mga bersiyon ng file.",
|
||||
"Failed to load ignore patterns.": "Nabigong i-load ang mga ignore pattern.",
|
||||
"Failed to set up, retrying": "Nabigong i-set up, sinusubukan muli",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Inaasahan ang pagbigo sa pagkonekta sa mga IPv6 na server kapag walang konektibidad sa IPv6.",
|
||||
"File Pull Order": "Order ng Pagkuha ng File",
|
||||
"File Versioning": "File Versioning",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Nilipat ang mga file sa .stversions na direktoryo kapag pinalitan o binura ng Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Nililipat ang mga file sa mga naka-date stamp na bersyon sa .stversions na direktoryo kapag pinalitan o binura ng Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Nililipat ang mga file sa mga naka-date stamp na bersiyon sa .stversions na direktoryo kapag pinalitan o binura ng Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Pinoprotektahan ang mga file mula sa mga pagbabago sa ibang device, pero ipapadala sa ibang cluster ang mga pagbabago na ginawa sa device na ito.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Sini-synchronize mula sa cluster ang mga file, pero hindi ipapadala sa mga ibang device ang mgaanumang pagbabago.",
|
||||
"Filesystem Watcher Errors": "Mga Error sa Taganood ng Filesystem",
|
||||
@@ -217,7 +217,7 @@
|
||||
"Introducer": "Tagapagpakilala",
|
||||
"Introduction": "Panimula",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Pabaliktad ng ibinigay na kundisyon (hal. huwag ibukod)",
|
||||
"Keep Versions": "Panatilihin ang mga Bersyon",
|
||||
"Keep Versions": "Panatilihin ang mga Bersiyon",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Pinakamalaki Muna",
|
||||
"Last 30 Days": "Huling 30 Araw",
|
||||
@@ -245,12 +245,12 @@
|
||||
"Log In": "Mag-Log In",
|
||||
"Log Out": "Mag-Log Out",
|
||||
"Log in to see paths information.": "Mag-log in upang makita ang impormasyon ng mga path.",
|
||||
"Log in to see version information.": "Mag-log in upang makita ang impormasyon ng bersyon.",
|
||||
"Log in to see version information.": "Mag-log in upang makita ang impormasyon ng bersiyon.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Na-pause ang tailing ng tala. Mag-scroll pababa para magpatuloy.",
|
||||
"Login failed, see Syncthing logs for details.": "Nabigo ang pag-login, tignan ang mga tala ng Syncthing para sa mga detalye.",
|
||||
"Logs": "Mga Tala",
|
||||
"Major Upgrade": "Major na Upgrade",
|
||||
"Mass actions": "Mga maramihang aksyon",
|
||||
"Mass actions": "Mga maramihang aksiyon",
|
||||
"Maximum Age": "Pinakamataas na Edad",
|
||||
"Maximum single entry size": "Pinakamataas na laki ng isang entry",
|
||||
"Maximum total size": "Pinakamataas na kabuuang laki",
|
||||
@@ -289,7 +289,7 @@
|
||||
"Password": "Password",
|
||||
"Path": "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 papunta sa folder sa computer na ito. Gagawin kapag hindi umiiral. Maaring gamitin ang tilde na character (~) bilang shortcut sa",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path kung saan ilalagay ang mga bersyon (iwanang walang laman para sa default .stversions na direktoryo sa binabahaging folder).",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path kung saan ilalagay ang mga bersiyon (iwanang walang laman para sa default .stversions na direktoryo sa binabahaging folder).",
|
||||
"Paths": "Mga Path",
|
||||
"Pause": "I-pause",
|
||||
"Pause All": "I-pause Lahat",
|
||||
@@ -335,7 +335,7 @@
|
||||
"Restart Needed": "Kinakailangan ng Restart",
|
||||
"Restarting": "Nagre-restart",
|
||||
"Restore": "I-restore",
|
||||
"Restore Versions": "I-restore ang Mga Bersyon",
|
||||
"Restore Versions": "I-restore ang Mga Bersiyon",
|
||||
"Resume": "I-resume",
|
||||
"Resume All": "I-resume Lahat",
|
||||
"Reused": "Ginamit muli",
|
||||
@@ -345,13 +345,13 @@
|
||||
"Saving changes": "Sine-save ang mga pagbabago",
|
||||
"Scan Time Remaining": "Natitirang Oras sa Pag-scan",
|
||||
"Scanning": "Sina-scan",
|
||||
"See external versioning help for supported templated command line parameters.": "Tingnan ang tulong sa external na pag-bersyon para sa mga sinusuportahang naka-template na parameter ng command line.",
|
||||
"See external versioning help for supported templated command line parameters.": "Tingnan ang tulong sa external na pag-bersiyon para sa mga sinusuportahang naka-template na parameter ng command line.",
|
||||
"Select All": "Piliin Lahat",
|
||||
"Select a version": "Pumili ng bersyon",
|
||||
"Select a version": "Pumili ng bersiyon",
|
||||
"Select additional devices to share this folder with.": "Pumili ng mga karagdagang device para ibagagi ang folder na ito.",
|
||||
"Select additional folders to share with this device.": "Pumili ng mga karagdagang folder para ibagagi sa device na ito.",
|
||||
"Select latest version": "Piliin ang pinakabagong bersyon",
|
||||
"Select oldest version": "Piliin ang pinakalumang bersyon",
|
||||
"Select latest version": "Piliin ang pinakabagong bersiyon",
|
||||
"Select oldest version": "Piliin ang pinakalumang bersiyon",
|
||||
"Send & Receive": "Magpadala at Makatanggap",
|
||||
"Send Extended Attributes": "Magpadala ng mga Pinalawak na Attribute",
|
||||
"Send Only": "Magpadala Lamang",
|
||||
@@ -370,7 +370,7 @@
|
||||
"Show QR": "Ipakita ang QR",
|
||||
"Show detailed discovery status": "Magpakita ng detalyadong status sa pagtuklas",
|
||||
"Show detailed listener status": "Ipakita ang detalyadong status sa listener",
|
||||
"Show diff with previous version": "Ipakita ang diff sa nakaraang bersyon",
|
||||
"Show diff with previous version": "Ipakita ang diff sa nakaraang bersiyon",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Ipinapakita sa halip na Device ID sa status ng cluster. Ia-advertise sa iba pang mga device bilang opsyonal na default na pangalan.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Ipinapakita sa halip na Device ID sa status ng cluster. Ia-update sa pangalan na ina-advertise ng device kung iiwanang walang laman.",
|
||||
"Shut Down": "I-shutdown",
|
||||
@@ -425,15 +425,15 @@
|
||||
"The cleanup interval cannot be blank.": "Hindi maaaring walang laman ang pagitan ng paglinis.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Na-save na ang configuration ngunit hindi naka-activate. Kailangang mag-restart ang Syncthing para i-activate ang bagong configuration.",
|
||||
"The device ID cannot be blank.": "Hindi maaaring walang laman ang Device ID.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Mahahanap ang device ID na ilalagay dito sa \"Mga Aksyon > Ipakita ang ID\" na dialog sa isa pang device. Opsyonal ang mga puwang at gitling (hindi pinapansin).",
|
||||
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes, and app versions. If the reported data set is changed you will be prompted with this dialog again.": "Araw-araw na pinapadala ang naka-encrypt na ulat sa paggamit. Ginagamit ito sa pag-track ng mga karaniwang platform, laki ng folder, at bersyon ng app. Kapag nabago ang tinakdang data ng ulat ipo-prompt kang muli ng dialog na ito.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Mahahanap ang device ID na ilalagay dito sa \"Mga Aksiyon > Ipakita ang ID\" na dialog sa isa pang device. Opsyonal ang mga puwang at gitling (hindi pinapansin).",
|
||||
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes, and app versions. If the reported data set is changed you will be prompted with this dialog again.": "Araw-araw na pinapadala ang naka-encrypt na ulat sa paggamit. Ginagamit ito sa pag-track ng mga karaniwang platform, laki ng folder, at bersiyon ng app. Kapag nabago ang tinakdang data ng ulat ipo-prompt kang muli ng dialog na ito.",
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Mukhang hindi angkop ang inilagay na device ID. Dapat itong 52 o 56 na character na string na binubuo ng mga titik at numero, na may mga puwang at gitling bilang opsyonal.",
|
||||
"The folder ID cannot be blank.": "Hindi maaaring walang laman ang folder ID.",
|
||||
"The folder ID must be unique.": "Kailangang kakaiba ang folder ID.",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "Io-overwrite ang nilalaman ng folder sa mga ibang device para maging magkapareho sa device na ito. Ang mga file na hindi nandito ay buburahin sa mga ibang device.",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "Io-overwrite ang nilalaman ng folder sa mga ibang device para maging magkapareho sa device na ito. Ang mga file na kamakilang dinagdag dito ay buburahin sa mga ibang device.",
|
||||
"The folder path cannot be blank.": "Hindi maaaring walang laman ang path ng folder.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Ang mga sumusunod na pagitan ay ginagamit: sa unang oras ang isang bersyon ay pinapanatili bawat 30 segundo, sa unang araw ang isang bersyon ay pinapanatili bawat oras, sa unang 30 araw ang isang bersyon ay pinapanatili bawat araw, hanggang sa pinakamataas na edad ang isang bersyon ay pinapanatili bawat linggo.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Ang mga sumusunod na pagitan ay ginagamit: sa unang oras ang isang bersiyon ay pinapanatili bawat 30 segundo, sa unang araw ang isang bersiyon ay pinapanatili bawat oras, sa unang 30 araw ang isang bersiyon ay pinapanatili bawat araw, hanggang sa pinakamataas na edad ang isang bersiyon ay pinapanatili bawat linggo.",
|
||||
"The following items could not be synchronized.": "Hindi ma-synchronize ang mga sumusunod na item.",
|
||||
"The following items were changed locally.": "Binago ng lokal ang mga sumusunod na item.",
|
||||
"The following methods are used to discover other devices on the network and announce this device to be found by others:": "Ang mga sumusunod na paraan ay ginagamit upang tumuklas ng mga ibang device sa network at ipahayag ang device na ito na mahanap ng iba:",
|
||||
@@ -442,12 +442,12 @@
|
||||
"The interval must be a positive number of seconds.": "Dapat positibong numero ng segundo ang pagitan.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Ang pagitan, bilang segundo, para sa pagtakbo ng paglinis sa versions na direktoryo. Sero para i-disable ang periodical na paglinis.",
|
||||
"The maximum age must be a number and cannot be blank.": "Dapat numero ang pinakamataas na edad at hindi maaaring walang laman.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Ang pinakamataas na oras para panatilihin ang bersyon (bilang araw, itakda sa 0 para panatilihin ang mga bersyon magpakailanman).",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Ang pinakamataas na oras para panatilihin ang bersiyon (bilang araw, itakda sa 0 para panatilihin ang mga bersiyon magpakailanman).",
|
||||
"The number of connections must be a non-negative number.": "Dapat hindi negatibong numero ang bilang ng mga koneksyon.",
|
||||
"The number of days must be a number and cannot be blank.": "Dapat numero ang bilang ng araw at hindi maaaring walang laman.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Ang bilang ng araw para panatilihin ang mga file sa basurahan. Ang sero ay ibig sabihin ay magpakailanman.",
|
||||
"The number of old versions to keep, per file.": "Ang bilang ng mga lumang bersyon na dapat panatilihin, bawat file.",
|
||||
"The number of versions must be a number and cannot be blank.": "Dapat numero ang bilang ng mga bersyon at hindi maaaring walang laman.",
|
||||
"The number of old versions to keep, per file.": "Ang bilang ng mga lumang bersiyon na dapat panatilihin, bawat file.",
|
||||
"The number of versions must be a number and cannot be blank.": "Dapat numero ang bilang ng mga bersiyon at hindi maaaring walang laman.",
|
||||
"The path cannot be blank.": "Hindi maaaring walang laman ang path.",
|
||||
"The rate limit is applied to the accumulated traffic of all connections to this device.": "Ina-apply ang rate limit sa naipon na traffic ng lahat ng mga koneksyon sa device na ito.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Dapat hindi negatibong numero ang rate limit (0: walang limitasyon)",
|
||||
@@ -462,7 +462,7 @@
|
||||
"This Month": "Itong Buwan",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Madali nitong mabibigyan ang mga hacker ng access na basahin at baguhin ang anumang mga file sa iyong computer.",
|
||||
"This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.": "Hindi awtomatikong tutuklasin ng device na ito ng mga ibang device o i-annouce ang sarili nitong address para mahanap ng iba. Makakakonekta lamang ang mga device na may static na naka-configure na address.",
|
||||
"This is a major version upgrade.": "Ito ay isang upgrade sa major na bersyon.",
|
||||
"This is a major version upgrade.": "Ito ay isang upgrade sa major na bersiyon.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Kinokontrol ng setting na ito ang kinakailangan na bakanteng espasyo sa home (hal., index database) disk.",
|
||||
"Time": "Oras",
|
||||
"Time the item was last modified": "Oras na huling binago ang file",
|
||||
@@ -501,10 +501,10 @@
|
||||
"Using a QUIC connection over WAN": "Gumagamit ng QUIC na koneksyon mula sa WAN",
|
||||
"Using a direct TCP connection over LAN": "Gumagamit ng direktang TCP na koneksyon mula sa LAN",
|
||||
"Using a direct TCP connection over WAN": "Gumagamit ng direktang TCP na koneksyon mula sa WAN",
|
||||
"Version": "Bersyon",
|
||||
"Versions": "Mga Bersyon",
|
||||
"Versions Path": "Path ng Mga Bersyon",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Awtomatikong buburahin ang mgs bersyon kapag mas matanda sila kaysa sa pinakamataas na edad o lumalagpas sa numero ng mga file na pinapayagan sa pagitan.",
|
||||
"Version": "Bersiyon",
|
||||
"Versions": "Mga Bersiyon",
|
||||
"Versions Path": "Path ng Mga Bersiyon",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Awtomatikong buburahin ang mgs bersiyon kapag mas matanda sila kaysa sa pinakamataas na edad o lumalagpas sa numero ng mga file na pinapayagan sa pagitan.",
|
||||
"Waiting to Clean": "Naghihintay para Linisin",
|
||||
"Waiting to Scan": "Naghihintay para Mag-scan",
|
||||
"Waiting to Sync": "Naghihintay para Mag-sync",
|
||||
@@ -529,7 +529,7 @@
|
||||
"You have no ignored devices.": "Wala kang mga hindi pinapansin na device.",
|
||||
"You have no ignored folders.": "Wala kang mga hindi pinapansin na folder.",
|
||||
"You have unsaved changes. Do you really want to discard them?": "Mayroon kang mga hindi na-save na pagbabago. Gusto mo ba talagang i-discard ang mga ito?",
|
||||
"You must keep at least one version.": "Kailangan mong magpanatili ng kahit isang bersyon.",
|
||||
"You must keep at least one version.": "Kailangan mong magpanatili ng kahit isang bersiyon.",
|
||||
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "Hindi ka dapat magdagdag o magpalit ng anumang lokal sa folder na \"{{receiveEncrypted}}\".",
|
||||
"Your SMS app should open to let you choose the recipient and send it from your own number.": "Magbubukas ang iyong SMS app para hayaan kang pumili ng tatanggap at ipadala ito mula sa sarili mong numero.",
|
||||
"Your email app should open to let you choose the recipient and send it from your own address.": "Magbubukas ang iyong email app para hayaan kang pumili ng tatanggap at ipadala mula sa sarili mong address.",
|
||||
|
||||
@@ -256,8 +256,8 @@
|
||||
"Maximum total size": "Taille maximum totale",
|
||||
"Metadata Only": "Métadonnées uniquement",
|
||||
"Minimum Free Disk Space": "Espace disque libre minimum",
|
||||
"Mod. Device": "Appareil modificateur",
|
||||
"Mod. Time": "Date de modification",
|
||||
"Mod. Device": "Modificateur",
|
||||
"Mod. Time": "Dernière modif.",
|
||||
"More than a month ago": "Plus d'un mois",
|
||||
"More than a week ago": "Plus d'une semaine",
|
||||
"More than a year ago": "Plus d'un an",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"Allowed Networks": "Redes permitidas",
|
||||
"Alphabetic": "Alfabética",
|
||||
"Altered by ignoring deletes.": "Cambiado por ignorar o borrado.",
|
||||
"Always turned on when the folder type is \"{%foldertype%}\".": "Sempre acendido cando o cartafol é de tipo \"{{foldertype}}\".",
|
||||
"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.": "Un comando externo xestiona as versións. Ten que eliminar o ficheiro do cartafol compartido. Si a ruta ao aplicativo contén espazos, deberían ir acotados.",
|
||||
"Anonymous Usage Reporting": "Informe anónimo de uso",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "O formato do informe de uso anónimo cambiou. Quere usar o novo formato?",
|
||||
@@ -52,6 +53,7 @@
|
||||
"Body:": "Corpo:",
|
||||
"Bugs": "Erros",
|
||||
"Cancel": "Cancelar",
|
||||
"Cannot be enabled when the folder type is \"{%foldertype%}\".": "Non se pode activar cando o cartafol é de tipo \"{{foldertype}}\".",
|
||||
"Changelog": "Rexistro de cambios",
|
||||
"Clean out after": "Limpar despois",
|
||||
"Cleaning Versions": "Limpando Versións",
|
||||
@@ -80,6 +82,7 @@
|
||||
"Custom Range": "Rango personalizado",
|
||||
"Danger!": "Perigo!",
|
||||
"Database Location": "Localización da Base de Datos",
|
||||
"Debug": "Depurar",
|
||||
"Debugging Facilities": "Ferramentas de depuración",
|
||||
"Default": "Predeterminado",
|
||||
"Default Configuration": "Configuración Predeterminada",
|
||||
@@ -140,6 +143,7 @@
|
||||
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Activa o envío de atributos extendidos a outros dispositivos, e aplicar os atributos extendidos recibidos. Podería requerir a execución con privilexios elevados.",
|
||||
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Activa o envío de atributos extendidos a outros dispositivos, pero non aplica atributos extendidos que se reciben. Isto podería afectar significativamente ao rendemento. Sempre está activado cando «Sincr Atributos Extendidos\" está activado.",
|
||||
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Activa o envío de información sobre a propiedade a outros dispositivos, e aplica a información sobre a propiedade cando se recibe. Normalmente require a execución con privilexios elevados.",
|
||||
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Activa o envío a outros dispositivos de información sobre a propiedade, pero non aplica información entrante sobre a propiedade. Isto pode afectar en gran medida ao rendemento. Está sempre activado cando \"Sincronización da propiedade\" está activada.",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Introduza un número non negativo (por exemplo, \"2.35\") e seleccione unha unidade. As porcentaxes son como partes totais do tamaño do disco.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Introduza un número de porto non privilexiado (1024-65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduza direccións separadas por comas (\"tcp://ip:porto\", \"tcp://host:porto\") ou \"dynamic\" para realizar o descubrimento automático da dirección.",
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
"Custom Range": "טווח מותאם אישית",
|
||||
"Danger!": "סכנה!",
|
||||
"Database Location": "מיקום מסד נתונים",
|
||||
"Debug": "איתור באגים",
|
||||
"Debugging Facilities": "מתקני דיבוג",
|
||||
"Default": "ברירת מחדל",
|
||||
"Default Configuration": "תצורת ברירת מחדל",
|
||||
@@ -210,6 +211,7 @@
|
||||
"Incoming Rate Limit (KiB/s)": "מגבלת קצב נכנס (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "תצורה שגויה עלולה לגרום נזק לתכולת התיקייה שלך ולהפוך את Syncthing לבלתי ניתן להפעלה.",
|
||||
"Incorrect user name or password.": "שם משתמש או סיסמה שגויים.",
|
||||
"Info": "מידע",
|
||||
"Internally used paths:": "נתיבים בשימוש פנימי:",
|
||||
"Introduced By": "הוצג על ידי",
|
||||
"Introducer": "מציג",
|
||||
|
||||
@@ -187,13 +187,14 @@ angular.module('syncthing.core')
|
||||
$scope.version = data;
|
||||
}).error($scope.emitHTTPError);
|
||||
|
||||
$http.get(urlbase + '/svc/report').success(function (data) {
|
||||
$scope.reportData = data;
|
||||
if ($scope.system && $scope.config.options.urAccepted > -1 && $scope.config.options.urSeen < $scope.system.urVersionMax && $scope.config.options.urAccepted < $scope.system.urVersionMax) {
|
||||
// Usage reporting format has changed, prompt the user to re-accept.
|
||||
if ($scope.system && $scope.config.options.urAccepted > -1 && $scope.config.options.urSeen < $scope.system.urVersionMax && $scope.config.options.urAccepted < $scope.system.urVersionMax) {
|
||||
// Usage reporting decision has not been taken or format
|
||||
// has changed, prompt the user to (re-)accept.
|
||||
$http.get(urlbase + '/svc/report').success(function (data) {
|
||||
$scope.reportData = data;
|
||||
showModal('#ur');
|
||||
}
|
||||
}).error($scope.emitHTTPError);
|
||||
}).error($scope.emitHTTPError);
|
||||
}
|
||||
|
||||
$http.get(urlbase + '/system/upgrade').success(function (data) {
|
||||
$scope.upgradeInfo = data;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"embed"
|
||||
"io/fs"
|
||||
@@ -26,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
currentSchemaVersion = 4
|
||||
currentSchemaVersion = 5
|
||||
applicationIDMain = 0x53546d6e // "STmn", Syncthing main database
|
||||
applicationIDFolder = 0x53546664 // "STfd", Syncthing folder database
|
||||
)
|
||||
@@ -87,7 +88,31 @@ func openBase(path string, maxConns int, pragmas, schemaScripts, migrationScript
|
||||
},
|
||||
}
|
||||
|
||||
tx, err := db.sql.Beginx()
|
||||
// Create a specific connection for the schema setup and migration to
|
||||
// run in. We do this because we need to disable foreign keys for the
|
||||
// duration, which is a thing that needs to happen outside of a
|
||||
// transaction and affects the connection it's run on. So we need to a)
|
||||
// make sure all our commands run on this specific connection (which the
|
||||
// transaction accomplishes naturally) and b) make sure these pragmas
|
||||
// don't leak to anyone else afterwards.
|
||||
ctx := context.TODO()
|
||||
conn, err := db.sql.Connx(ctx)
|
||||
if err != nil {
|
||||
return nil, wrap(err)
|
||||
}
|
||||
defer func() {
|
||||
_, _ = conn.ExecContext(ctx, "PRAGMA foreign_keys = ON")
|
||||
_, _ = conn.ExecContext(ctx, "PRAGMA legacy_alter_table = OFF")
|
||||
conn.Close()
|
||||
}()
|
||||
if _, err := conn.ExecContext(ctx, "PRAGMA foreign_keys = OFF"); err != nil {
|
||||
return nil, wrap(err)
|
||||
}
|
||||
if _, err := conn.ExecContext(ctx, "PRAGMA legacy_alter_table = ON"); err != nil {
|
||||
return nil, wrap(err)
|
||||
}
|
||||
|
||||
tx, err := conn.BeginTxx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, wrap(err)
|
||||
}
|
||||
@@ -100,7 +125,7 @@ func openBase(path string, maxConns int, pragmas, schemaScripts, migrationScript
|
||||
}
|
||||
|
||||
ver, _ := db.getAppliedSchemaVersion(tx)
|
||||
shouldVacuum := false
|
||||
appliedMigrations := false
|
||||
if ver.SchemaVersion > 0 {
|
||||
filter := func(scr string) bool {
|
||||
scr = filepath.Base(scr)
|
||||
@@ -114,7 +139,7 @@ func openBase(path string, maxConns int, pragmas, schemaScripts, migrationScript
|
||||
}
|
||||
if int(n) > ver.SchemaVersion {
|
||||
slog.Info("Applying database migration", slogutil.FilePath(db.baseName), slog.String("script", scr))
|
||||
shouldVacuum = true
|
||||
appliedMigrations = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -124,6 +149,24 @@ func openBase(path string, maxConns int, pragmas, schemaScripts, migrationScript
|
||||
return nil, wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the initial schema scripts once more. This is generally a
|
||||
// no-op. However, dropping a table removes associated triggers etc,
|
||||
// and that's a thing we sometimes do in migrations. To avoid having
|
||||
// to repeat the setup of associated triggers and indexes in the
|
||||
// migration, we re-run the initial schema scripts.
|
||||
for _, script := range schemaScripts {
|
||||
if err := db.runScripts(tx, script); err != nil {
|
||||
return nil, wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, ensure nothing we've done along the way has violated key integrity.
|
||||
if appliedMigrations {
|
||||
if _, err := conn.ExecContext(ctx, "PRAGMA foreign_key_check"); err != nil {
|
||||
return nil, wrap(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the current schema version, if not already set
|
||||
@@ -135,7 +178,7 @@ func openBase(path string, maxConns int, pragmas, schemaScripts, migrationScript
|
||||
return nil, wrap(err)
|
||||
}
|
||||
|
||||
if shouldVacuum {
|
||||
if appliedMigrations {
|
||||
// We applied migrations and should take the opportunity to vaccuum
|
||||
// the database.
|
||||
if err := db.vacuumAndOptimize(); err != nil {
|
||||
@@ -271,7 +314,12 @@ nextScript:
|
||||
// also statement-internal semicolons in the triggers.
|
||||
for _, stmt := range strings.Split(string(bs), "\n;") {
|
||||
if _, err := tx.Exec(s.expandTemplateVars(stmt)); err != nil {
|
||||
return wrap(err, stmt)
|
||||
if strings.Contains(stmt, "syncthing:ignore-failure") {
|
||||
// We're ok with this failing. Just note it.
|
||||
slog.Debug("Script failed, but with ignore-failure annotation", slog.String("script", scr), slogutil.Error(wrap(err, stmt)))
|
||||
} else {
|
||||
return wrap(err, stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,13 @@ package sqlite
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/timeutil"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
)
|
||||
@@ -223,7 +225,7 @@ func BenchmarkUpdate(b *testing.B) {
|
||||
}
|
||||
|
||||
func TestBenchmarkDropAllRemote(t *testing.T) {
|
||||
if testing.Short() {
|
||||
if testing.Short() || os.Getenv("LONG_TEST") == "" {
|
||||
t.Skip("slow test")
|
||||
}
|
||||
|
||||
@@ -266,3 +268,61 @@ func TestBenchmarkDropAllRemote(t *testing.T) {
|
||||
d := time.Since(t0)
|
||||
t.Log("drop all took", d)
|
||||
}
|
||||
|
||||
func TestBenchmarkSizeManyFilesRemotes(t *testing.T) {
|
||||
// Reports the database size for a setup with many files and many remote
|
||||
// devices each announcing every files, with fairly long file names and
|
||||
// "worst case" version vectors.
|
||||
|
||||
if testing.Short() || os.Getenv("LONG_TEST") == "" {
|
||||
t.Skip("slow test")
|
||||
}
|
||||
|
||||
dir := t.TempDir()
|
||||
db, err := Open(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := db.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
// This is equivalent to about 800 GiB in 100k files (i.e., 8 MiB per
|
||||
// file), shared between 31 devices where each have touched every file.
|
||||
const numFiles = 1e5
|
||||
const numRemotes = 30
|
||||
const numBlocks = 64
|
||||
const filenameLen = 64
|
||||
|
||||
fs := make([]protocol.FileInfo, 1000)
|
||||
n := 0
|
||||
seq := 0
|
||||
for n < numFiles {
|
||||
for i := range fs {
|
||||
seq++
|
||||
fs[i] = genFile(rand.String(filenameLen), numBlocks, seq)
|
||||
for r := range numRemotes {
|
||||
fs[i].Version = fs[i].Version.Update(42 + protocol.ShortID(r))
|
||||
}
|
||||
}
|
||||
if err := db.Update(folderID, protocol.LocalDeviceID, fs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for r := range numRemotes {
|
||||
if err := db.Update(folderID, protocol.DeviceID{byte(42 + r)}, fs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
n += len(fs)
|
||||
t.Log(n, (numRemotes+1)*n)
|
||||
}
|
||||
|
||||
if err := db.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
size := osutil.DirSize(dir)
|
||||
t.Logf("Total size: %.02f MiB", float64(size)/1024/1024)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/internal/db"
|
||||
"github.com/syncthing/syncthing/internal/slogutil"
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -65,6 +66,8 @@ func Open(path string, opts ...Option) (*DB, error) {
|
||||
}
|
||||
|
||||
_ = os.MkdirAll(path, 0o700)
|
||||
initTmpDir(path)
|
||||
|
||||
mainPath := filepath.Join(path, "main.db")
|
||||
mainBase, err := openBase(mainPath, maxDBConns, pragmas, schemas, migrations)
|
||||
if err != nil {
|
||||
@@ -114,6 +117,8 @@ func OpenForMigration(path string) (*DB, error) {
|
||||
}
|
||||
|
||||
_ = os.MkdirAll(path, 0o700)
|
||||
initTmpDir(path)
|
||||
|
||||
mainPath := filepath.Join(path, "main.db")
|
||||
mainBase, err := openBase(mainPath, 1, pragmas, schemas, migrations)
|
||||
if err != nil {
|
||||
@@ -143,3 +148,24 @@ func (s *DB) Close() error {
|
||||
}
|
||||
return wrap(s.baseDB.Close())
|
||||
}
|
||||
|
||||
func initTmpDir(path string) {
|
||||
if build.IsWindows || build.IsDarwin || os.Getenv("SQLITE_TMPDIR") != "" {
|
||||
// Doesn't use SQLITE_TMPDIR, isn't likely to have a tiny
|
||||
// ram-backed temp directory, or already set to something.
|
||||
return
|
||||
}
|
||||
|
||||
// Attempt to override the SQLite temporary directory by setting the
|
||||
// env var prior to the (first) database being opened and hence
|
||||
// SQLite becoming initialized. We set the temp dir to the same
|
||||
// place we store the database, in the hope that there will be
|
||||
// enough space there for the operations it needs to perform, as
|
||||
// opposed to /tmp and similar, on some systems.
|
||||
dbTmpDir := filepath.Join(path, ".tmp")
|
||||
if err := os.MkdirAll(dbTmpDir, 0o700); err == nil {
|
||||
os.Setenv("SQLITE_TMPDIR", dbTmpDir)
|
||||
} else {
|
||||
slog.Warn("Failed to create temp directory for SQLite", slogutil.FilePath(dbTmpDir), slogutil.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
const (
|
||||
dbDriver = "sqlite"
|
||||
commonOptions = "_pragma=foreign_keys(1)&_pragma=recursive_triggers(1)&_pragma=synchronous(1)"
|
||||
commonOptions = "_pragma=foreign_keys(1)&_pragma=recursive_triggers(1)&_pragma=synchronous(1)&_txlock=immediate"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -8,19 +8,28 @@ package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/syncthing/syncthing/internal/db"
|
||||
"github.com/syncthing/syncthing/internal/slogutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/thejerf/suture/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
internalMetaPrefix = "dbsvc"
|
||||
lastMaintKey = "lastMaint"
|
||||
internalMetaPrefix = "dbsvc"
|
||||
lastMaintKey = "lastMaint"
|
||||
lastSuccessfulGCSeqKey = "lastSuccessfulGCSeq"
|
||||
|
||||
gcMinChunks = 5
|
||||
gcChunkSize = 100_000 // approximate number of rows to process in a single gc query
|
||||
gcMaxRuntime = 5 * time.Minute // max time to spend on gc, per table, per run
|
||||
)
|
||||
|
||||
func (s *DB) Service(maintenanceInterval time.Duration) suture.Service {
|
||||
@@ -91,16 +100,44 @@ func (s *Service) periodic(ctx context.Context) error {
|
||||
}
|
||||
|
||||
return wrap(s.sdb.forEachFolder(func(fdb *folderDB) error {
|
||||
fdb.updateLock.Lock()
|
||||
defer fdb.updateLock.Unlock()
|
||||
// Get the current device sequence, for comparison in the next step.
|
||||
seq, err := fdb.GetDeviceSequence(protocol.LocalDeviceID)
|
||||
if err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
// Get the last successful GC sequence. If it's the same as the
|
||||
// current sequence, nothing has changed and we can skip the GC
|
||||
// entirely.
|
||||
meta := db.NewTyped(fdb, internalMetaPrefix)
|
||||
if prev, _, err := meta.Int64(lastSuccessfulGCSeqKey); err != nil {
|
||||
return wrap(err)
|
||||
} else if seq == prev {
|
||||
slog.DebugContext(ctx, "Skipping unnecessary GC", "folder", fdb.folderID, "fdb", fdb.baseName)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := garbageCollectOldDeletedLocked(ctx, fdb); err != nil {
|
||||
// Run the GC steps, in a function to be able to use a deferred
|
||||
// unlock.
|
||||
if err := func() error {
|
||||
fdb.updateLock.Lock()
|
||||
defer fdb.updateLock.Unlock()
|
||||
|
||||
if err := garbageCollectOldDeletedLocked(ctx, fdb); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
if err := garbageCollectNamesAndVersions(ctx, fdb); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
if err := garbageCollectBlocklistsAndBlocksLocked(ctx, fdb); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
return tidy(ctx, fdb.sql)
|
||||
}(); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
if err := garbageCollectBlocklistsAndBlocksLocked(ctx, fdb); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
return tidy(ctx, fdb.sql)
|
||||
|
||||
// Update the successful GC sequence.
|
||||
return wrap(meta.PutInt64(lastSuccessfulGCSeqKey, seq))
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -118,8 +155,36 @@ func tidy(ctx context.Context, db *sqlx.DB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func garbageCollectNamesAndVersions(ctx context.Context, fdb *folderDB) error {
|
||||
l := slog.With("folder", fdb.folderID, "fdb", fdb.baseName)
|
||||
|
||||
res, err := fdb.stmt(`
|
||||
DELETE FROM file_names
|
||||
WHERE NOT EXISTS (SELECT 1 FROM files f WHERE f.name_idx = idx)
|
||||
`).Exec()
|
||||
if err != nil {
|
||||
return wrap(err, "delete names")
|
||||
}
|
||||
if aff, err := res.RowsAffected(); err == nil {
|
||||
l.DebugContext(ctx, "Removed old file names", "affected", aff)
|
||||
}
|
||||
|
||||
res, err = fdb.stmt(`
|
||||
DELETE FROM file_versions
|
||||
WHERE NOT EXISTS (SELECT 1 FROM files f WHERE f.version_idx = idx)
|
||||
`).Exec()
|
||||
if err != nil {
|
||||
return wrap(err, "delete versions")
|
||||
}
|
||||
if aff, err := res.RowsAffected(); err == nil {
|
||||
l.DebugContext(ctx, "Removed old file versions", "affected", aff)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func garbageCollectOldDeletedLocked(ctx context.Context, fdb *folderDB) error {
|
||||
l := slog.With("fdb", fdb.baseDB)
|
||||
l := slog.With("folder", fdb.folderID, "fdb", fdb.baseName)
|
||||
if fdb.deleteRetention <= 0 {
|
||||
slog.DebugContext(ctx, "Delete retention is infinite, skipping cleanup")
|
||||
return nil
|
||||
@@ -171,37 +236,108 @@ func garbageCollectBlocklistsAndBlocksLocked(ctx context.Context, fdb *folderDB)
|
||||
}
|
||||
defer tx.Rollback() //nolint:errcheck
|
||||
|
||||
if res, err := tx.ExecContext(ctx, `
|
||||
DELETE FROM blocklists
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM files WHERE files.blocklist_hash = blocklists.blocklist_hash
|
||||
)`); err != nil {
|
||||
return wrap(err, "delete blocklists")
|
||||
} else {
|
||||
slog.DebugContext(ctx, "Blocklist GC", "fdb", fdb.baseName, "result", slogutil.Expensive(func() any {
|
||||
rows, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return slogutil.Error(err)
|
||||
}
|
||||
return slog.Int64("rows", rows)
|
||||
}))
|
||||
}
|
||||
// Both blocklists and blocks refer to blocklists_hash from the files table.
|
||||
for _, table := range []string{"blocklists", "blocks"} {
|
||||
// Count the number of rows
|
||||
var rows int64
|
||||
if err := tx.GetContext(ctx, &rows, `SELECT count(*) FROM `+table); err != nil {
|
||||
return wrap(err)
|
||||
}
|
||||
|
||||
if res, err := tx.ExecContext(ctx, `
|
||||
DELETE FROM blocks
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM blocklists WHERE blocklists.blocklist_hash = blocks.blocklist_hash
|
||||
)`); err != nil {
|
||||
return wrap(err, "delete blocks")
|
||||
} else {
|
||||
slog.DebugContext(ctx, "Blocks GC", "fdb", fdb.baseName, "result", slogutil.Expensive(func() any {
|
||||
rows, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return slogutil.Error(err)
|
||||
chunks := max(gcMinChunks, rows/gcChunkSize)
|
||||
l := slog.With("folder", fdb.folderID, "fdb", fdb.baseName, "table", table, "rows", rows, "chunks", chunks)
|
||||
|
||||
// Process rows in chunks up to a given time limit. We always use at
|
||||
// least gcMinChunks chunks, then increase the number as the number of rows
|
||||
// exceeds gcMinChunks*gcChunkSize.
|
||||
t0 := time.Now()
|
||||
for i, br := range randomBlobRanges(int(chunks)) {
|
||||
if d := time.Since(t0); d > gcMaxRuntime {
|
||||
l.InfoContext(ctx, "GC was interrupted due to exceeding time limit", "processed", i, "runtime", time.Since(t0))
|
||||
break
|
||||
}
|
||||
return slog.Int64("rows", rows)
|
||||
}))
|
||||
|
||||
// The limit column must be an indexed column with a mostly random distribution of blobs.
|
||||
// That's the blocklist_hash column for blocklists, and the hash column for blocks.
|
||||
limitColumn := table + ".blocklist_hash"
|
||||
if table == "blocks" {
|
||||
limitColumn = "blocks.hash"
|
||||
}
|
||||
|
||||
q := fmt.Sprintf(`
|
||||
DELETE FROM %s
|
||||
WHERE %s AND NOT EXISTS (
|
||||
SELECT 1 FROM files WHERE files.blocklist_hash = %s.blocklist_hash
|
||||
)`, table, br.SQL(limitColumn), table)
|
||||
|
||||
if res, err := tx.ExecContext(ctx, q); err != nil {
|
||||
return wrap(err, "delete from "+table)
|
||||
} else {
|
||||
l.DebugContext(ctx, "GC query result", "processed", i, "runtime", time.Since(t0), "result", slogutil.Expensive(func() any {
|
||||
rows, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return slogutil.Error(err)
|
||||
}
|
||||
return slog.Int64("rows", rows)
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wrap(tx.Commit())
|
||||
}
|
||||
|
||||
// blobRange defines a range for blob searching. A range is open ended if
|
||||
// start or end is nil.
|
||||
type blobRange struct {
|
||||
start, end []byte
|
||||
}
|
||||
|
||||
// SQL returns the SQL where clause for the given range, e.g.
|
||||
// `column >= x'49249248' AND column < x'6db6db6c'`
|
||||
func (r blobRange) SQL(name string) string {
|
||||
var sb strings.Builder
|
||||
if r.start != nil {
|
||||
fmt.Fprintf(&sb, "%s >= x'%x'", name, r.start)
|
||||
}
|
||||
if r.start != nil && r.end != nil {
|
||||
sb.WriteString(" AND ")
|
||||
}
|
||||
if r.end != nil {
|
||||
fmt.Fprintf(&sb, "%s < x'%x'", name, r.end)
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// randomBlobRanges returns n blobRanges in random order
|
||||
func randomBlobRanges(n int) []blobRange {
|
||||
ranges := blobRanges(n)
|
||||
rand.Shuffle(len(ranges), func(i, j int) { ranges[i], ranges[j] = ranges[j], ranges[i] })
|
||||
return ranges
|
||||
}
|
||||
|
||||
// blobRanges returns n blobRanges
|
||||
func blobRanges(n int) []blobRange {
|
||||
// We use three byte (24 bit) prefixes to get fairly granular ranges and easy bit
|
||||
// conversions.
|
||||
rangeSize := (1 << 24) / n
|
||||
ranges := make([]blobRange, 0, n)
|
||||
var prev []byte
|
||||
for i := range n {
|
||||
var pref []byte
|
||||
if i < n-1 {
|
||||
end := (i + 1) * rangeSize
|
||||
pref = intToBlob(end)
|
||||
}
|
||||
ranges = append(ranges, blobRange{prev, pref})
|
||||
prev = pref
|
||||
}
|
||||
return ranges
|
||||
}
|
||||
|
||||
func intToBlob(n int) []byte {
|
||||
var pref [4]byte
|
||||
binary.BigEndian.PutUint32(pref[:], uint32(n)) //nolint:gosec
|
||||
// first byte is always zero and not part of the range
|
||||
return pref[1:]
|
||||
}
|
||||
|
||||
37
internal/db/sqlite/db_service_test.go
Normal file
37
internal/db/sqlite/db_service_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2025 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 sqlite
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBlobRange(t *testing.T) {
|
||||
exp := `
|
||||
hash < x'249249'
|
||||
hash >= x'249249' AND hash < x'492492'
|
||||
hash >= x'492492' AND hash < x'6db6db'
|
||||
hash >= x'6db6db' AND hash < x'924924'
|
||||
hash >= x'924924' AND hash < x'b6db6d'
|
||||
hash >= x'b6db6d' AND hash < x'db6db6'
|
||||
hash >= x'db6db6'
|
||||
`
|
||||
|
||||
ranges := blobRanges(7)
|
||||
buf := new(bytes.Buffer)
|
||||
for _, r := range ranges {
|
||||
fmt.Fprintln(buf, r.SQL("hash"))
|
||||
}
|
||||
|
||||
if strings.TrimSpace(buf.String()) != strings.TrimSpace(exp) {
|
||||
t.Log(buf.String())
|
||||
t.Error("unexpected output")
|
||||
}
|
||||
}
|
||||
@@ -1206,6 +1206,47 @@ func TestOpenSpecialName(t *testing.T) {
|
||||
db.Close()
|
||||
}
|
||||
|
||||
func TestBlocksInserted(t *testing.T) {
|
||||
// Verifies that blocks are inserted after syncing a file
|
||||
|
||||
t.Parallel()
|
||||
|
||||
sdb, err := Open(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := sdb.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
// Add remote file
|
||||
|
||||
files := []protocol.FileInfo{genFile("test1", 100, 1)}
|
||||
if err := sdb.Update(folderID, protocol.DeviceID{42}, files); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Add the same file locally
|
||||
|
||||
if err := sdb.Update(folderID, protocol.LocalDeviceID, files); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify all the blocks are here
|
||||
|
||||
for i, block := range files[0].Blocks {
|
||||
bs, err := itererr.Collect(sdb.AllLocalBlocksWithHash(folderID, block.Hash))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(bs) == 0 {
|
||||
t.Error("missing blocks for", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustCollect[T any](t *testing.T) func(it iter.Seq[T], errFn func() error) []T {
|
||||
t.Helper()
|
||||
return func(it iter.Seq[T], errFn func() error) []T {
|
||||
|
||||
@@ -84,7 +84,7 @@ func (s *folderDB) needSizeRemote(device protocol.DeviceID) (db.Counts, error) {
|
||||
WHERE g.local_flags & {{.FlagLocalGlobal}} != 0 AND NOT g.deleted AND g.local_flags & {{.LocalInvalidFlags}} = 0 AND NOT EXISTS (
|
||||
SELECT 1 FROM FILES f
|
||||
INNER JOIN devices d ON d.idx = f.device_idx
|
||||
WHERE f.name = g.name AND f.version = g.version AND d.device_id = ?
|
||||
WHERE f.name_idx = g.name_idx AND f.version_idx = g.version_idx AND d.device_id = ?
|
||||
)
|
||||
GROUP BY g.type, g.local_flags, g.deleted
|
||||
|
||||
@@ -94,7 +94,7 @@ func (s *folderDB) needSizeRemote(device protocol.DeviceID) (db.Counts, error) {
|
||||
WHERE g.local_flags & {{.FlagLocalGlobal}} != 0 AND g.deleted AND g.local_flags & {{.LocalInvalidFlags}} = 0 AND EXISTS (
|
||||
SELECT 1 FROM FILES f
|
||||
INNER JOIN devices d ON d.idx = f.device_idx
|
||||
WHERE f.name = g.name AND d.device_id = ? AND NOT f.deleted AND f.local_flags & {{.LocalInvalidFlags}} = 0
|
||||
WHERE f.name_idx = g.name_idx AND d.device_id = ? AND NOT f.deleted AND f.local_flags & {{.LocalInvalidFlags}} = 0
|
||||
)
|
||||
GROUP BY g.type, g.local_flags, g.deleted
|
||||
`).Select(&res, device.String(),
|
||||
|
||||
@@ -27,7 +27,8 @@ func (s *folderDB) GetGlobalFile(file string) (protocol.FileInfo, bool, error) {
|
||||
SELECT fi.fiprotobuf, bl.blprotobuf FROM fileinfos fi
|
||||
INNER JOIN files f on fi.sequence = f.sequence
|
||||
LEFT JOIN blocklists bl ON bl.blocklist_hash = f.blocklist_hash
|
||||
WHERE f.name = ? AND f.local_flags & {{.FlagLocalGlobal}} != 0
|
||||
INNER JOIN file_names n ON f.name_idx = n.idx
|
||||
WHERE n.name = ? AND f.local_flags & {{.FlagLocalGlobal}} != 0
|
||||
`).Get(&ind, file)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return protocol.FileInfo{}, false, nil
|
||||
@@ -49,8 +50,9 @@ func (s *folderDB) GetGlobalAvailability(file string) ([]protocol.DeviceID, erro
|
||||
err := s.stmt(`
|
||||
SELECT d.device_id FROM files f
|
||||
INNER JOIN devices d ON d.idx = f.device_idx
|
||||
INNER JOIN files g ON g.version = f.version AND g.name = f.name
|
||||
WHERE g.name = ? AND g.local_flags & {{.FlagLocalGlobal}} != 0 AND f.device_idx != {{.LocalDeviceIdx}}
|
||||
INNER JOIN files g ON g.version_idx = f.version_idx AND g.name_idx = f.name_idx
|
||||
INNER JOIN file_names n ON f.name_idx = n.idx
|
||||
WHERE n.name = ? AND g.local_flags & {{.FlagLocalGlobal}} != 0 AND f.device_idx != {{.LocalDeviceIdx}}
|
||||
ORDER BY d.device_id
|
||||
`).Select(&devStrs, file)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
@@ -74,9 +76,10 @@ func (s *folderDB) GetGlobalAvailability(file string) ([]protocol.DeviceID, erro
|
||||
|
||||
func (s *folderDB) AllGlobalFiles() (iter.Seq[db.FileMetadata], func() error) {
|
||||
it, errFn := iterStructs[db.FileMetadata](s.stmt(`
|
||||
SELECT f.sequence, f.name, f.type, f.modified as modnanos, f.size, f.deleted, f.local_flags as localflags FROM files f
|
||||
SELECT f.sequence, n.name, f.type, f.modified as modnanos, f.size, f.deleted, f.local_flags as localflags FROM files f
|
||||
INNER JOIN file_names n ON f.name_idx = n.idx
|
||||
WHERE f.local_flags & {{.FlagLocalGlobal}} != 0
|
||||
ORDER BY f.name
|
||||
ORDER BY n.name
|
||||
`).Queryx())
|
||||
return itererr.Map(it, errFn, func(m db.FileMetadata) (db.FileMetadata, error) {
|
||||
m.Name = osutil.NativeFilename(m.Name)
|
||||
@@ -93,9 +96,10 @@ func (s *folderDB) AllGlobalFilesPrefix(prefix string) (iter.Seq[db.FileMetadata
|
||||
end := prefixEnd(prefix)
|
||||
|
||||
it, errFn := iterStructs[db.FileMetadata](s.stmt(`
|
||||
SELECT f.sequence, f.name, f.type, f.modified as modnanos, f.size, f.deleted, f.local_flags as localflags FROM files f
|
||||
WHERE f.name >= ? AND f.name < ? AND f.local_flags & {{.FlagLocalGlobal}} != 0
|
||||
ORDER BY f.name
|
||||
SELECT f.sequence, n.name, f.type, f.modified as modnanos, f.size, f.deleted, f.local_flags as localflags FROM files f
|
||||
INNER JOIN file_names n ON f.name_idx = n.idx
|
||||
WHERE n.name >= ? AND n.name < ? AND f.local_flags & {{.FlagLocalGlobal}} != 0
|
||||
ORDER BY n.name
|
||||
`).Queryx(prefix, end))
|
||||
return itererr.Map(it, errFn, func(m db.FileMetadata) (db.FileMetadata, error) {
|
||||
m.Name = osutil.NativeFilename(m.Name)
|
||||
@@ -109,7 +113,7 @@ func (s *folderDB) AllNeededGlobalFiles(device protocol.DeviceID, order config.P
|
||||
case config.PullOrderRandom:
|
||||
selectOpts = "ORDER BY RANDOM()"
|
||||
case config.PullOrderAlphabetic:
|
||||
selectOpts = "ORDER BY g.name ASC"
|
||||
selectOpts = "ORDER BY n.name ASC"
|
||||
case config.PullOrderSmallestFirst:
|
||||
selectOpts = "ORDER BY g.size ASC"
|
||||
case config.PullOrderLargestFirst:
|
||||
@@ -137,9 +141,10 @@ func (s *folderDB) AllNeededGlobalFiles(device protocol.DeviceID, order config.P
|
||||
func (s *folderDB) neededGlobalFilesLocal(selectOpts string) (iter.Seq[protocol.FileInfo], func() error) {
|
||||
// Select all the non-ignored files with the need bit set.
|
||||
it, errFn := iterStructs[indirectFI](s.stmt(`
|
||||
SELECT fi.fiprotobuf, bl.blprotobuf, g.name, g.size, g.modified FROM fileinfos fi
|
||||
SELECT fi.fiprotobuf, bl.blprotobuf, n.name, g.size, g.modified FROM fileinfos fi
|
||||
INNER JOIN files g on fi.sequence = g.sequence
|
||||
LEFT JOIN blocklists bl ON bl.blocklist_hash = g.blocklist_hash
|
||||
INNER JOIN file_names n ON g.name_idx = n.idx
|
||||
WHERE g.local_flags & {{.FlagLocalIgnored}} = 0 AND g.local_flags & {{.FlagLocalNeeded}} != 0
|
||||
` + selectOpts).Queryx())
|
||||
return itererr.Map(it, errFn, indirectFI.FileInfo)
|
||||
@@ -155,24 +160,26 @@ func (s *folderDB) neededGlobalFilesRemote(device protocol.DeviceID, selectOpts
|
||||
// non-deleted and valid remote file (of any version)
|
||||
|
||||
it, errFn := iterStructs[indirectFI](s.stmt(`
|
||||
SELECT fi.fiprotobuf, bl.blprotobuf, g.name, g.size, g.modified FROM fileinfos fi
|
||||
SELECT fi.fiprotobuf, bl.blprotobuf, n.name, g.size, g.modified FROM fileinfos fi
|
||||
INNER JOIN files g on fi.sequence = g.sequence
|
||||
LEFT JOIN blocklists bl ON bl.blocklist_hash = g.blocklist_hash
|
||||
INNER JOIN file_names n ON g.name_idx = n.idx
|
||||
WHERE g.local_flags & {{.FlagLocalGlobal}} != 0 AND NOT g.deleted AND g.local_flags & {{.LocalInvalidFlags}} = 0 AND NOT EXISTS (
|
||||
SELECT 1 FROM FILES f
|
||||
INNER JOIN devices d ON d.idx = f.device_idx
|
||||
WHERE f.name = g.name AND f.version = g.version AND d.device_id = ?
|
||||
WHERE f.name_idx = g.name_idx AND f.version_idx = g.version_idx AND d.device_id = ?
|
||||
)
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT fi.fiprotobuf, bl.blprotobuf, g.name, g.size, g.modified FROM fileinfos fi
|
||||
SELECT fi.fiprotobuf, bl.blprotobuf, n.name, g.size, g.modified FROM fileinfos fi
|
||||
INNER JOIN files g on fi.sequence = g.sequence
|
||||
LEFT JOIN blocklists bl ON bl.blocklist_hash = g.blocklist_hash
|
||||
INNER JOIN file_names n ON g.name_idx = n.idx
|
||||
WHERE g.local_flags & {{.FlagLocalGlobal}} != 0 AND g.deleted AND g.local_flags & {{.LocalInvalidFlags}} = 0 AND EXISTS (
|
||||
SELECT 1 FROM FILES f
|
||||
INNER JOIN devices d ON d.idx = f.device_idx
|
||||
WHERE f.name = g.name AND d.device_id = ? AND NOT f.deleted AND f.local_flags & {{.LocalInvalidFlags}} = 0
|
||||
WHERE f.name_idx = g.name_idx AND d.device_id = ? AND NOT f.deleted AND f.local_flags & {{.LocalInvalidFlags}} = 0
|
||||
)
|
||||
`+selectOpts).Queryx(
|
||||
device.String(),
|
||||
|
||||
@@ -32,7 +32,8 @@ func (s *folderDB) GetDeviceFile(device protocol.DeviceID, file string) (protoco
|
||||
INNER JOIN files f on fi.sequence = f.sequence
|
||||
LEFT JOIN blocklists bl ON bl.blocklist_hash = f.blocklist_hash
|
||||
INNER JOIN devices d ON f.device_idx = d.idx
|
||||
WHERE d.device_id = ? AND f.name = ?
|
||||
INNER JOIN file_names n ON f.name_idx = n.idx
|
||||
WHERE d.device_id = ? AND n.name = ?
|
||||
`).Get(&ind, device.String(), file)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return protocol.FileInfo{}, false, nil
|
||||
@@ -87,14 +88,16 @@ func (s *folderDB) AllLocalFilesWithPrefix(device protocol.DeviceID, prefix stri
|
||||
INNER JOIN files f on fi.sequence = f.sequence
|
||||
LEFT JOIN blocklists bl ON bl.blocklist_hash = f.blocklist_hash
|
||||
INNER JOIN devices d ON d.idx = f.device_idx
|
||||
WHERE d.device_id = ? AND f.name >= ? AND f.name < ?
|
||||
INNER JOIN file_names n ON f.name_idx = n.idx
|
||||
WHERE d.device_id = ? AND n.name >= ? AND n.name < ?
|
||||
`, device.String(), prefix, end))
|
||||
return itererr.Map(it, errFn, indirectFI.FileInfo)
|
||||
}
|
||||
|
||||
func (s *folderDB) AllLocalFilesWithBlocksHash(h []byte) (iter.Seq[db.FileMetadata], func() error) {
|
||||
return iterStructs[db.FileMetadata](s.stmt(`
|
||||
SELECT f.sequence, f.name, f.type, f.modified as modnanos, f.size, f.deleted, f.local_flags as localflags FROM files f
|
||||
SELECT f.sequence, n.name, f.type, f.modified as modnanos, f.size, f.deleted, f.local_flags as localflags FROM files f
|
||||
INNER JOIN file_names n ON f.name_idx = n.idx
|
||||
WHERE f.device_idx = {{.LocalDeviceIdx}} AND f.blocklist_hash = ?
|
||||
`).Queryx(h))
|
||||
}
|
||||
@@ -104,7 +107,8 @@ func (s *folderDB) AllLocalBlocksWithHash(hash []byte) (iter.Seq[db.BlockMapEntr
|
||||
// & blocklists is deferred (garbage collected) while the files list is
|
||||
// not. This filters out blocks that are in fact deleted.
|
||||
return iterStructs[db.BlockMapEntry](s.stmt(`
|
||||
SELECT f.blocklist_hash as blocklisthash, b.idx as blockindex, b.offset, b.size, f.name as filename FROM files f
|
||||
SELECT f.blocklist_hash as blocklisthash, b.idx as blockindex, b.offset, b.size, n.name as filename FROM files f
|
||||
INNER JOIN file_names n ON f.name_idx = n.idx
|
||||
LEFT JOIN blocks b ON f.blocklist_hash = b.blocklist_hash
|
||||
WHERE f.device_idx = {{.LocalDeviceIdx}} AND b.hash = ?
|
||||
`).Queryx(hash))
|
||||
@@ -170,10 +174,12 @@ func (s *folderDB) DebugFilePattern(out io.Writer, name string) error {
|
||||
}
|
||||
name = "%" + name + "%"
|
||||
res := itererr.Zip(iterStructs[hashFileMetadata](s.stmt(`
|
||||
SELECT f.sequence, f.name, f.type, f.modified as modnanos, f.size, f.deleted, f.local_flags as localflags, f.version, f.blocklist_hash as blocklisthash, d.device_id as deviceid FROM files f
|
||||
SELECT f.sequence, n.name, f.type, f.modified as modnanos, f.size, f.deleted, f.local_flags as localflags, v.version, f.blocklist_hash as blocklisthash, d.device_id as deviceid FROM files f
|
||||
INNER JOIN devices d ON d.idx = f.device_idx
|
||||
WHERE f.name LIKE ?
|
||||
ORDER BY f.name, f.device_idx
|
||||
INNER JOIN file_names n ON n.idx = f.name_idx
|
||||
INNER JOIN file_versions v ON v.idx = f.version_idx
|
||||
WHERE n.name LIKE ?
|
||||
ORDER BY n.name, f.device_idx
|
||||
`).Queryx(name)))
|
||||
|
||||
delMap := map[bool]string{
|
||||
|
||||
@@ -95,16 +95,13 @@ func openFolderDBForMigration(folder, path string, deleteRetention time.Duration
|
||||
|
||||
func (s *folderDB) deviceIdxLocked(deviceID protocol.DeviceID) (int64, error) {
|
||||
devStr := deviceID.String()
|
||||
if _, err := s.stmt(`
|
||||
INSERT OR IGNORE INTO devices(device_id)
|
||||
VALUES (?)
|
||||
`).Exec(devStr); err != nil {
|
||||
return 0, wrap(err)
|
||||
}
|
||||
var idx int64
|
||||
if err := s.stmt(`
|
||||
SELECT idx FROM devices
|
||||
WHERE device_id = ?
|
||||
INSERT INTO devices(device_id)
|
||||
VALUES (?)
|
||||
ON CONFLICT(device_id) DO UPDATE
|
||||
SET device_id = excluded.device_id
|
||||
RETURNING idx
|
||||
`).Get(&idx, devStr); err != nil {
|
||||
return 0, wrap(err)
|
||||
}
|
||||
|
||||
@@ -46,9 +46,33 @@ func (s *folderDB) Update(device protocol.DeviceID, fs []protocol.FileInfo) erro
|
||||
defer tx.Rollback() //nolint:errcheck
|
||||
txp := &txPreparedStmts{Tx: tx}
|
||||
|
||||
//nolint:sqlclosecheck
|
||||
insertNameStmt, err := txp.Preparex(`
|
||||
INSERT INTO file_names(name)
|
||||
VALUES (?)
|
||||
ON CONFLICT(name) DO UPDATE
|
||||
SET name = excluded.name
|
||||
RETURNING idx
|
||||
`)
|
||||
if err != nil {
|
||||
return wrap(err, "prepare insert name")
|
||||
}
|
||||
|
||||
//nolint:sqlclosecheck
|
||||
insertVersionStmt, err := txp.Preparex(`
|
||||
INSERT INTO file_versions (version)
|
||||
VALUES (?)
|
||||
ON CONFLICT(version) DO UPDATE
|
||||
SET version = excluded.version
|
||||
RETURNING idx
|
||||
`)
|
||||
if err != nil {
|
||||
return wrap(err, "prepare insert version")
|
||||
}
|
||||
|
||||
//nolint:sqlclosecheck
|
||||
insertFileStmt, err := txp.Preparex(`
|
||||
INSERT OR REPLACE INTO files (device_idx, remote_sequence, name, type, modified, size, version, deleted, local_flags, blocklist_hash)
|
||||
INSERT OR REPLACE INTO files (device_idx, remote_sequence, type, modified, size, deleted, local_flags, blocklist_hash, name_idx, version_idx)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING sequence
|
||||
`)
|
||||
@@ -102,8 +126,19 @@ func (s *folderDB) Update(device protocol.DeviceID, fs []protocol.FileInfo) erro
|
||||
prevRemoteSeq = f.Sequence
|
||||
remoteSeq = &f.Sequence
|
||||
}
|
||||
|
||||
var nameIdx int64
|
||||
if err := insertNameStmt.Get(&nameIdx, f.Name); err != nil {
|
||||
return wrap(err, "insert name")
|
||||
}
|
||||
|
||||
var versionIdx int64
|
||||
if err := insertVersionStmt.Get(&versionIdx, f.Version.String()); err != nil {
|
||||
return wrap(err, "insert version")
|
||||
}
|
||||
|
||||
var localSeq int64
|
||||
if err := insertFileStmt.Get(&localSeq, deviceIdx, remoteSeq, f.Name, f.Type, f.ModTime().UnixNano(), f.Size, f.Version.String(), f.IsDeleted(), f.LocalFlags, blockshash); err != nil {
|
||||
if err := insertFileStmt.Get(&localSeq, deviceIdx, remoteSeq, f.Type, f.ModTime().UnixNano(), f.Size, f.IsDeleted(), f.LocalFlags, blockshash, nameIdx, versionIdx); err != nil {
|
||||
return wrap(err, "insert file")
|
||||
}
|
||||
|
||||
@@ -114,9 +149,9 @@ func (s *folderDB) Update(device protocol.DeviceID, fs []protocol.FileInfo) erro
|
||||
if err != nil {
|
||||
return wrap(err, "marshal blocklist")
|
||||
}
|
||||
if res, err := insertBlockListStmt.Exec(f.BlocksHash, bs); err != nil {
|
||||
if _, err := insertBlockListStmt.Exec(f.BlocksHash, bs); err != nil {
|
||||
return wrap(err, "insert blocklist")
|
||||
} else if aff, _ := res.RowsAffected(); aff != 0 && device == protocol.LocalDeviceID {
|
||||
} else if device == protocol.LocalDeviceID {
|
||||
// Insert all blocks
|
||||
if err := s.insertBlocksLocked(txp, f.BlocksHash, f.Blocks); err != nil {
|
||||
return wrap(err, "insert blocks")
|
||||
@@ -246,7 +281,9 @@ func (s *folderDB) DropFilesNamed(device protocol.DeviceID, names []string) erro
|
||||
|
||||
query, args, err := sqlx.In(`
|
||||
DELETE FROM files
|
||||
WHERE device_idx = ? AND name IN (?)
|
||||
WHERE device_idx = ? AND name_idx IN (
|
||||
SELECT idx FROM file_names WHERE name IN (?)
|
||||
)
|
||||
`, deviceIdx, names)
|
||||
if err != nil {
|
||||
return wrap(err)
|
||||
@@ -299,12 +336,13 @@ func (s *folderDB) recalcGlobalForFolder(txp *txPreparedStmts) error {
|
||||
// recalculate.
|
||||
//nolint:sqlclosecheck
|
||||
namesStmt, err := txp.Preparex(`
|
||||
SELECT f.name FROM files f
|
||||
SELECT n.name FROM files f
|
||||
INNER JOIN file_names n ON n.idx = f.name_idx
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM files g
|
||||
WHERE g.name = f.name AND g.local_flags & ? != 0
|
||||
WHERE g.name_idx = f.name_idx AND g.local_flags & ? != 0
|
||||
)
|
||||
GROUP BY name
|
||||
GROUP BY n.name
|
||||
`)
|
||||
if err != nil {
|
||||
return wrap(err)
|
||||
@@ -329,11 +367,13 @@ func (s *folderDB) recalcGlobalForFolder(txp *txPreparedStmts) error {
|
||||
func (s *folderDB) recalcGlobalForFile(txp *txPreparedStmts, file string) error {
|
||||
//nolint:sqlclosecheck
|
||||
selStmt, err := txp.Preparex(`
|
||||
SELECT name, device_idx, sequence, modified, version, deleted, local_flags FROM files
|
||||
WHERE name = ?
|
||||
SELECT n.name, f.device_idx, f.sequence, f.modified, v.version, f.deleted, f.local_flags FROM files f
|
||||
INNER JOIN file_versions v ON v.idx = f.version_idx
|
||||
INNER JOIN file_names n ON n.idx = f.name_idx
|
||||
WHERE n.name = ?
|
||||
`)
|
||||
if err != nil {
|
||||
return wrap(err)
|
||||
return wrap(err, "prepare select")
|
||||
}
|
||||
es, err := itererr.Collect(iterStructs[fileRow](selStmt.Queryx(file)))
|
||||
if err != nil {
|
||||
@@ -389,10 +429,10 @@ func (s *folderDB) recalcGlobalForFile(txp *txPreparedStmts, file string) error
|
||||
//nolint:sqlclosecheck
|
||||
upStmt, err = txp.Preparex(`
|
||||
UPDATE files SET local_flags = local_flags & ?
|
||||
WHERE name = ? AND sequence != ? AND local_flags & ? != 0
|
||||
WHERE name_idx = (SELECT idx FROM file_names WHERE name = ?) AND sequence != ? AND local_flags & ? != 0
|
||||
`)
|
||||
if err != nil {
|
||||
return wrap(err)
|
||||
return wrap(err, "prepare update")
|
||||
}
|
||||
if _, err := upStmt.Exec(^(protocol.FlagLocalNeeded | protocol.FlagLocalGlobal), global.Name, global.Sequence, protocol.FlagLocalNeeded|protocol.FlagLocalGlobal); err != nil {
|
||||
return wrap(err)
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
-- Copyright (C) 2025 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/.
|
||||
|
||||
-- Grab all unique names into the names table
|
||||
|
||||
INSERT INTO file_names (idx, name) SELECT DISTINCT null, name FROM files
|
||||
;
|
||||
|
||||
-- Grab all unique versions into the versions table
|
||||
|
||||
INSERT INTO file_versions (idx, version) SELECT DISTINCT null, version FROM files
|
||||
;
|
||||
|
||||
-- Create the new files table
|
||||
|
||||
DROP TABLE IF EXISTS files_v5
|
||||
;
|
||||
|
||||
CREATE TABLE files_v5 (
|
||||
device_idx INTEGER NOT NULL,
|
||||
sequence INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
remote_sequence INTEGER,
|
||||
name_idx INTEGER NOT NULL, -- changed
|
||||
type INTEGER NOT NULL,
|
||||
modified INTEGER NOT NULL,
|
||||
size INTEGER NOT NULL,
|
||||
version_idx INTEGER NOT NULL, -- changed
|
||||
deleted INTEGER NOT NULL,
|
||||
local_flags INTEGER NOT NULL,
|
||||
blocklist_hash BLOB,
|
||||
FOREIGN KEY(device_idx) REFERENCES devices(idx) ON DELETE CASCADE,
|
||||
FOREIGN KEY(name_idx) REFERENCES file_names(idx), -- added
|
||||
FOREIGN KEY(version_idx) REFERENCES file_versions(idx) -- added
|
||||
) STRICT
|
||||
;
|
||||
|
||||
-- Populate the new files table and move it in place
|
||||
|
||||
INSERT INTO files_v5
|
||||
SELECT f.device_idx, f.sequence, f.remote_sequence, n.idx as name_idx, f.type, f.modified, f.size, v.idx as version_idx, f.deleted, f.local_flags, f.blocklist_hash
|
||||
FROM files f
|
||||
INNER JOIN file_names n ON n.name = f.name
|
||||
INNER JOIN file_versions v ON v.version = f.version
|
||||
;
|
||||
|
||||
DROP TABLE files
|
||||
;
|
||||
|
||||
ALTER TABLE files_v5 RENAME TO files
|
||||
;
|
||||
@@ -25,15 +25,27 @@ CREATE TABLE IF NOT EXISTS files (
|
||||
device_idx INTEGER NOT NULL, -- actual device ID or LocalDeviceID
|
||||
sequence INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, -- our local database sequence, for each and every entry
|
||||
remote_sequence INTEGER, -- remote device's sequence number, null for local or synthetic entries
|
||||
name TEXT NOT NULL COLLATE BINARY,
|
||||
name_idx INTEGER NOT NULL,
|
||||
type INTEGER NOT NULL, -- protocol.FileInfoType
|
||||
modified INTEGER NOT NULL, -- Unix nanos
|
||||
size INTEGER NOT NULL,
|
||||
version TEXT NOT NULL COLLATE BINARY,
|
||||
version_idx INTEGER NOT NULL,
|
||||
deleted INTEGER NOT NULL, -- boolean
|
||||
local_flags INTEGER NOT NULL,
|
||||
blocklist_hash BLOB, -- null when there are no blocks
|
||||
FOREIGN KEY(device_idx) REFERENCES devices(idx) ON DELETE CASCADE
|
||||
FOREIGN KEY(device_idx) REFERENCES devices(idx) ON DELETE CASCADE,
|
||||
FOREIGN KEY(name_idx) REFERENCES file_names(idx),
|
||||
FOREIGN KEY(version_idx) REFERENCES file_versions(idx)
|
||||
) STRICT
|
||||
;
|
||||
CREATE TABLE IF NOT EXISTS file_names (
|
||||
idx INTEGER NOT NULL PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE COLLATE BINARY
|
||||
) STRICT
|
||||
;
|
||||
CREATE TABLE IF NOT EXISTS file_versions (
|
||||
idx INTEGER NOT NULL PRIMARY KEY,
|
||||
version TEXT NOT NULL UNIQUE COLLATE BINARY
|
||||
) STRICT
|
||||
;
|
||||
-- FileInfos store the actual protobuf object. We do this separately to keep
|
||||
@@ -49,11 +61,17 @@ CREATE UNIQUE INDEX IF NOT EXISTS files_remote_sequence ON files (device_idx, re
|
||||
WHERE remote_sequence IS NOT NULL
|
||||
;
|
||||
-- There can be only one file per folder, device, and name
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS files_device_name ON files (device_idx, name)
|
||||
;
|
||||
-- We want to be able to look up & iterate files based on just folder and name
|
||||
CREATE INDEX IF NOT EXISTS files_name_only ON files (name)
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS files_device_name ON files (device_idx, name_idx)
|
||||
;
|
||||
-- We want to be able to look up & iterate files based on blocks hash
|
||||
CREATE INDEX IF NOT EXISTS files_blocklist_hash_only ON files (blocklist_hash, device_idx) WHERE blocklist_hash IS NOT NULL
|
||||
;
|
||||
-- We need to look by name_idx or version_idx for garbage collection.
|
||||
-- This will fail pre-migration for v4 schemas, which is fine.
|
||||
-- syncthing:ignore-failure
|
||||
CREATE INDEX IF NOT EXISTS files_name_idx_only ON files (name_idx)
|
||||
;
|
||||
-- This will fail pre-migration for v4 schemas, which is fine.
|
||||
-- syncthing:ignore-failure
|
||||
CREATE INDEX IF NOT EXISTS files_version_idx_only ON files (version_idx)
|
||||
;
|
||||
|
||||
@@ -944,28 +944,29 @@ type FileInfo struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
|
||||
ModifiedS int64 `protobuf:"varint,5,opt,name=modified_s,json=modifiedS,proto3" json:"modified_s,omitempty"`
|
||||
ModifiedBy uint64 `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3" json:"modified_by,omitempty"`
|
||||
Version *Vector `protobuf:"bytes,9,opt,name=version,proto3" json:"version,omitempty"`
|
||||
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
||||
Blocks []*BlockInfo `protobuf:"bytes,16,rep,name=blocks,proto3" json:"blocks,omitempty"`
|
||||
SymlinkTarget []byte `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
|
||||
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocks_hash,omitempty"`
|
||||
Encrypted []byte `protobuf:"bytes,19,opt,name=encrypted,proto3" json:"encrypted,omitempty"`
|
||||
Type FileInfoType `protobuf:"varint,2,opt,name=type,proto3,enum=bep.FileInfoType" json:"type,omitempty"`
|
||||
Permissions uint32 `protobuf:"varint,4,opt,name=permissions,proto3" json:"permissions,omitempty"`
|
||||
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
|
||||
BlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
|
||||
Platform *PlatformData `protobuf:"bytes,14,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
|
||||
ModifiedS int64 `protobuf:"varint,5,opt,name=modified_s,json=modifiedS,proto3" json:"modified_s,omitempty"`
|
||||
ModifiedBy uint64 `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3" json:"modified_by,omitempty"`
|
||||
Version *Vector `protobuf:"bytes,9,opt,name=version,proto3" json:"version,omitempty"`
|
||||
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
||||
Blocks []*BlockInfo `protobuf:"bytes,16,rep,name=blocks,proto3" json:"blocks,omitempty"`
|
||||
SymlinkTarget []byte `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
|
||||
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocks_hash,omitempty"`
|
||||
PreviousBlocksHash []byte `protobuf:"bytes,20,opt,name=previous_blocks_hash,json=previousBlocksHash,proto3" json:"previous_blocks_hash,omitempty"`
|
||||
Encrypted []byte `protobuf:"bytes,19,opt,name=encrypted,proto3" json:"encrypted,omitempty"`
|
||||
Type FileInfoType `protobuf:"varint,2,opt,name=type,proto3,enum=bep.FileInfoType" json:"type,omitempty"`
|
||||
Permissions uint32 `protobuf:"varint,4,opt,name=permissions,proto3" json:"permissions,omitempty"`
|
||||
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
|
||||
BlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
|
||||
Platform *PlatformData `protobuf:"bytes,14,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
// The local_flags fields stores flags that are relevant to the local
|
||||
// host only. It is not part of the protocol, doesn't get sent or
|
||||
// received (we make sure to zero it), nonetheless we need it on our
|
||||
// struct and to be able to serialize it to/from the database.
|
||||
LocalFlags uint32 `protobuf:"varint,1000,opt,name=local_flags,json=localFlags,proto3" json:"local_flags,omitempty"`
|
||||
// The version_hash is an implementation detail and not part of the wire
|
||||
// format.
|
||||
// format. It is used in the old database format.
|
||||
VersionHash []byte `protobuf:"bytes,1001,opt,name=version_hash,json=versionHash,proto3" json:"version_hash,omitempty"`
|
||||
// The time when the inode was last changed (i.e., permissions, xattrs
|
||||
// etc changed). This is host-local, not sent over the wire.
|
||||
@@ -1071,6 +1072,13 @@ func (x *FileInfo) GetBlocksHash() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FileInfo) GetPreviousBlocksHash() []byte {
|
||||
if x != nil {
|
||||
return x.PreviousBlocksHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FileInfo) GetEncrypted() []byte {
|
||||
if x != nil {
|
||||
return x.Encrypted
|
||||
@@ -2084,7 +2092,7 @@ var file_bep_bep_proto_rawDesc = []byte{
|
||||
0x0c, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x23, 0x0a,
|
||||
0x0d, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x76, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e,
|
||||
0x63, 0x65, 0x22, 0xfe, 0x05, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12,
|
||||
0x63, 0x65, 0x22, 0xb0, 0x06, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12,
|
||||
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66,
|
||||
@@ -2102,198 +2110,201 @@ var file_bep_bep_proto_rawDesc = []byte{
|
||||
0x72, 0x67, 0x65, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x79, 0x6d, 0x6c,
|
||||
0x69, 0x6e, 0x6b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f,
|
||||
0x63, 0x6b, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e,
|
||||
0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65,
|
||||
0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x46, 0x69, 0x6c,
|
||||
0x65, 0x49, 0x6e, 0x66, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
|
||||
0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6e, 0x73,
|
||||
0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64,
|
||||
0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x69, 0x7a, 0x65,
|
||||
0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x7a,
|
||||
0x65, 0x12, 0x2d, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0e, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
|
||||
0x72, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
|
||||
0x12, 0x20, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18,
|
||||
0xe8, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x6c, 0x61,
|
||||
0x67, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61,
|
||||
0x73, 0x68, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x5f,
|
||||
0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6e, 0x73, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x03,
|
||||
0x52, 0x0d, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x73, 0x12,
|
||||
0x37, 0x0a, 0x17, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x72,
|
||||
0x61, 0x69, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28,
|
||||
0x05, 0x52, 0x15, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61,
|
||||
0x69, 0x6c, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65,
|
||||
0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74,
|
||||
0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x07, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e,
|
||||
0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x6f, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x22, 0x51, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f,
|
||||
0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04,
|
||||
0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65,
|
||||
0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x32, 0x0a, 0x06, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72,
|
||||
0x12, 0x28, 0x0a, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0x2f, 0x0a, 0x07, 0x43, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xfd, 0x01, 0x0a, 0x0c,
|
||||
0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x04,
|
||||
0x75, 0x6e, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62, 0x65, 0x70,
|
||||
0x2e, 0x55, 0x6e, 0x69, 0x78, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x12,
|
||||
0x2a, 0x0a, 0x07, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x10, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x61,
|
||||
0x74, 0x61, 0x52, 0x07, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, 0x24, 0x0a, 0x05, 0x6c,
|
||||
0x69, 0x6e, 0x75, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x65, 0x70,
|
||||
0x2e, 0x58, 0x61, 0x74, 0x74, 0x72, 0x44, 0x61, 0x74, 0x61, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x75,
|
||||
0x78, 0x12, 0x26, 0x0a, 0x06, 0x64, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x58, 0x61, 0x74, 0x74, 0x72, 0x44, 0x61, 0x74,
|
||||
0x61, 0x52, 0x06, 0x64, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x12, 0x28, 0x0a, 0x07, 0x66, 0x72, 0x65,
|
||||
0x65, 0x62, 0x73, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x65, 0x70,
|
||||
0x2e, 0x58, 0x61, 0x74, 0x74, 0x72, 0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x66, 0x72, 0x65, 0x65,
|
||||
0x62, 0x73, 0x64, 0x12, 0x26, 0x0a, 0x06, 0x6e, 0x65, 0x74, 0x62, 0x73, 0x64, 0x18, 0x06, 0x20,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x72,
|
||||
0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x68, 0x61,
|
||||
0x73, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f,
|
||||
0x75, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09,
|
||||
0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||
0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79,
|
||||
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x46,
|
||||
0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70,
|
||||
0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f,
|
||||
0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,
|
||||
0x65, 0x64, 0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x69,
|
||||
0x7a, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53,
|
||||
0x69, 0x7a, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18,
|
||||
0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x50, 0x6c, 0x61, 0x74,
|
||||
0x66, 0x6f, 0x72, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f,
|
||||
0x72, 0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67,
|
||||
0x73, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x46,
|
||||
0x6c, 0x61, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x68, 0x61, 0x73, 0x68, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x6f, 0x64,
|
||||
0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6e, 0x73, 0x18, 0xea, 0x07, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e,
|
||||
0x73, 0x12, 0x37, 0x0a, 0x17, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x74, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0xeb, 0x07, 0x20,
|
||||
0x01, 0x28, 0x05, 0x52, 0x15, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54,
|
||||
0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65,
|
||||
0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c,
|
||||
0x65, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18,
|
||||
0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x25,
|
||||
0x0a, 0x0e, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x6f, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x51, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e,
|
||||
0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12,
|
||||
0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x69,
|
||||
0x7a, 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x32, 0x0a, 0x06, 0x56, 0x65, 0x63, 0x74,
|
||||
0x6f, 0x72, 0x12, 0x28, 0x0a, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0x2f, 0x0a, 0x07,
|
||||
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xfd, 0x01,
|
||||
0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21,
|
||||
0x0a, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x62,
|
||||
0x65, 0x70, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x75, 0x6e, 0x69,
|
||||
0x78, 0x12, 0x2a, 0x0a, 0x07, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73,
|
||||
0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x12, 0x24, 0x0a,
|
||||
0x05, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62,
|
||||
0x65, 0x70, 0x2e, 0x58, 0x61, 0x74, 0x74, 0x72, 0x44, 0x61, 0x74, 0x61, 0x52, 0x05, 0x6c, 0x69,
|
||||
0x6e, 0x75, 0x78, 0x12, 0x26, 0x0a, 0x06, 0x64, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x58, 0x61, 0x74, 0x74, 0x72, 0x44,
|
||||
0x61, 0x74, 0x61, 0x52, 0x06, 0x6e, 0x65, 0x74, 0x62, 0x73, 0x64, 0x22, 0x6c, 0x0a, 0x08, 0x55,
|
||||
0x6e, 0x69, 0x78, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72,
|
||||
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e,
|
||||
0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75,
|
||||
0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x67, 0x69, 0x64, 0x22, 0x52, 0x0a, 0x0b, 0x57, 0x69, 0x6e,
|
||||
0x64, 0x6f, 0x77, 0x73, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, 0x65,
|
||||
0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x77,
|
||||
0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x72,
|
||||
0x5f, 0x69, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||
0x0c, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x2f, 0x0a,
|
||||
0x09, 0x58, 0x61, 0x74, 0x74, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x06, 0x78, 0x61,
|
||||
0x74, 0x74, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x62, 0x65, 0x70,
|
||||
0x2e, 0x58, 0x61, 0x74, 0x74, 0x72, 0x52, 0x06, 0x78, 0x61, 0x74, 0x74, 0x72, 0x73, 0x22, 0x31,
|
||||
0x0a, 0x05, 0x58, 0x61, 0x74, 0x74, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x22, 0xcd, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a,
|
||||
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a,
|
||||
0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66,
|
||||
0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66,
|
||||
0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65,
|
||||
0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||
0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x72, 0x6f,
|
||||
0x6d, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79,
|
||||
0x12, 0x19, 0x0a, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x6f, 0x18, 0x09, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, 0x4a, 0x04, 0x08, 0x08, 0x10,
|
||||
0x09, 0x22, 0x52, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a,
|
||||
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74,
|
||||
0x61, 0x12, 0x22, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32,
|
||||
0x0e, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52,
|
||||
0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x65, 0x0a, 0x10, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
|
||||
0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x6c,
|
||||
0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65,
|
||||
0x72, 0x12, 0x39, 0x0a, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x6f, 0x77,
|
||||
0x61, 0x74, 0x61, 0x52, 0x06, 0x64, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x12, 0x28, 0x0a, 0x07, 0x66,
|
||||
0x72, 0x65, 0x65, 0x62, 0x73, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62,
|
||||
0x65, 0x70, 0x2e, 0x58, 0x61, 0x74, 0x74, 0x72, 0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x66, 0x72,
|
||||
0x65, 0x65, 0x62, 0x73, 0x64, 0x12, 0x26, 0x0a, 0x06, 0x6e, 0x65, 0x74, 0x62, 0x73, 0x64, 0x18,
|
||||
0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x58, 0x61, 0x74, 0x74,
|
||||
0x72, 0x44, 0x61, 0x74, 0x61, 0x52, 0x06, 0x6e, 0x65, 0x74, 0x62, 0x73, 0x64, 0x22, 0x6c, 0x0a,
|
||||
0x08, 0x55, 0x6e, 0x69, 0x78, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e,
|
||||
0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f,
|
||||
0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x72, 0x6f, 0x75,
|
||||
0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72,
|
||||
0x6f, 0x75, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x67, 0x69, 0x64, 0x22, 0x52, 0x0a, 0x0b, 0x57,
|
||||
0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77,
|
||||
0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x77, 0x6e,
|
||||
0x65, 0x72, 0x5f, 0x69, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x08, 0x52, 0x0c, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x73, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22,
|
||||
0x2f, 0x0a, 0x09, 0x58, 0x61, 0x74, 0x74, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x06,
|
||||
0x78, 0x61, 0x74, 0x74, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x62,
|
||||
0x65, 0x70, 0x2e, 0x58, 0x61, 0x74, 0x74, 0x72, 0x52, 0x06, 0x78, 0x61, 0x74, 0x74, 0x72, 0x73,
|
||||
0x22, 0x31, 0x0a, 0x05, 0x58, 0x61, 0x74, 0x74, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x22, 0xcd, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12,
|
||||
0x16, 0x0a, 0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x06, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f,
|
||||
0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6f, 0x66, 0x66,
|
||||
0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||
0x05, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18,
|
||||
0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x66,
|
||||
0x72, 0x6f, 0x6d, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x18, 0x07, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x54, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61,
|
||||
0x72, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x6f, 0x18, 0x09,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, 0x4a, 0x04, 0x08,
|
||||
0x08, 0x10, 0x09, 0x22, 0x52, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12,
|
||||
0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64,
|
||||
0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x0e, 0x32, 0x0e, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64,
|
||||
0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x65, 0x0a, 0x10, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
|
||||
0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x66,
|
||||
0x6f, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x6c,
|
||||
0x64, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44,
|
||||
0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x55,
|
||||
0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0xe5,
|
||||
0x01, 0x0a, 0x1a, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50,
|
||||
0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x44, 0x0a,
|
||||
0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0e, 0x32, 0x23, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x6f, 0x77,
|
||||
0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a,
|
||||
0x1a, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f,
|
||||
0x67, 0x72, 0x65, 0x73, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x75,
|
||||
0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
|
||||
0x32, 0x23, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
|
||||
0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70,
|
||||
0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x56, 0x65, 0x63,
|
||||
0x74, 0x6f, 0x72, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0d,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x18, 0x04, 0x20,
|
||||
0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x00, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73,
|
||||
0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x53, 0x69, 0x7a, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x22, 0x1f, 0x0a, 0x05,
|
||||
0x43, 0x6c, 0x6f, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x2a, 0xed, 0x01,
|
||||
0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a,
|
||||
0x1b, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4c,
|
||||
0x55, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, 0x12, 0x16,
|
||||
0x0a, 0x12, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49,
|
||||
0x4e, 0x44, 0x45, 0x58, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47,
|
||||
0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x5f, 0x55, 0x50, 0x44,
|
||||
0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45,
|
||||
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, 0x12,
|
||||
0x19, 0x0a, 0x15, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
|
||||
0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x04, 0x12, 0x22, 0x0a, 0x1e, 0x4d, 0x45,
|
||||
0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x4c,
|
||||
0x4f, 0x41, 0x44, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x05, 0x12, 0x15,
|
||||
0x0a, 0x11, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50,
|
||||
0x49, 0x4e, 0x47, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45,
|
||||
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x10, 0x07, 0x2a, 0x4f, 0x0a,
|
||||
0x12, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x43,
|
||||
0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10,
|
||||
0x00, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x43, 0x4f, 0x4d,
|
||||
0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, 0x5a, 0x34, 0x10, 0x01, 0x2a, 0x56,
|
||||
0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a,
|
||||
0x14, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x54,
|
||||
0x41, 0x44, 0x41, 0x54, 0x41, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4d, 0x50, 0x52,
|
||||
0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x45, 0x56, 0x45, 0x52, 0x10, 0x01, 0x12, 0x16,
|
||||
0x0a, 0x12, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x4c,
|
||||
0x57, 0x41, 0x59, 0x53, 0x10, 0x02, 0x2a, 0x86, 0x01, 0x0a, 0x0a, 0x46, 0x6f, 0x6c, 0x64, 0x65,
|
||||
0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f,
|
||||
0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x56,
|
||||
0x45, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x54, 0x59,
|
||||
0x50, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x01, 0x12, 0x1c,
|
||||
0x0a, 0x18, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45,
|
||||
0x43, 0x45, 0x49, 0x56, 0x45, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d,
|
||||
0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x45,
|
||||
0x49, 0x56, 0x45, 0x5f, 0x45, 0x4e, 0x43, 0x52, 0x59, 0x50, 0x54, 0x45, 0x44, 0x10, 0x03, 0x2a,
|
||||
0x51, 0x0a, 0x10, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x61,
|
||||
0x73, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x1a, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x53, 0x54,
|
||||
0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e,
|
||||
0x47, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x53, 0x54,
|
||||
0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x55, 0x53, 0x45, 0x44,
|
||||
0x10, 0x01, 0x2a, 0xb0, 0x01, 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x54,
|
||||
0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f,
|
||||
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18,
|
||||
0x46, 0x49, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44,
|
||||
0x49, 0x52, 0x45, 0x43, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1b, 0x46, 0x49,
|
||||
0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x4d,
|
||||
0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x02, 0x1a, 0x02, 0x08, 0x01, 0x12,
|
||||
0x28, 0x0a, 0x20, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x54, 0x59, 0x50,
|
||||
0x45, 0x5f, 0x53, 0x59, 0x4d, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54,
|
||||
0x4f, 0x52, 0x59, 0x10, 0x03, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x49, 0x4c,
|
||||
0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x4d, 0x4c,
|
||||
0x49, 0x4e, 0x4b, 0x10, 0x04, 0x2a, 0x76, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f,
|
||||
0x64, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45,
|
||||
0x5f, 0x4e, 0x4f, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x45,
|
||||
0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x49,
|
||||
0x43, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44,
|
||||
0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x53, 0x55, 0x43, 0x48, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x02,
|
||||
0x12, 0x1b, 0x0a, 0x17, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x49,
|
||||
0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x03, 0x2a, 0x7e, 0x0a,
|
||||
0x1e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x72, 0x6f,
|
||||
0x67, 0x72, 0x65, 0x73, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12,
|
||||
0x2d, 0x0a, 0x29, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, 0x44,
|
||||
0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45,
|
||||
0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x50, 0x50, 0x45, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x2d,
|
||||
0x0a, 0x29, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41, 0x44, 0x5f,
|
||||
0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f,
|
||||
0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x47, 0x45, 0x54, 0x10, 0x01, 0x42, 0x70, 0x0a,
|
||||
0x07, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x65, 0x70, 0x42, 0x08, 0x42, 0x65, 0x70, 0x50, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74,
|
||||
0x68, 0x69, 0x6e, 0x67, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65,
|
||||
0x6e, 0x2f, 0x62, 0x65, 0x70, 0xa2, 0x02, 0x03, 0x42, 0x58, 0x58, 0xaa, 0x02, 0x03, 0x42, 0x65,
|
||||
0x70, 0xca, 0x02, 0x03, 0x42, 0x65, 0x70, 0xe2, 0x02, 0x0f, 0x42, 0x65, 0x70, 0x5c, 0x47, 0x50,
|
||||
0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x03, 0x42, 0x65, 0x70, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x61, 0x74, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54,
|
||||
0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x56,
|
||||
0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27,
|
||||
0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x18,
|
||||
0x04, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x00, 0x52, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x6c, 0x6f,
|
||||
0x63, 0x6b, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x22, 0x1f,
|
||||
0x0a, 0x05, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f,
|
||||
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x2a,
|
||||
0xed, 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12,
|
||||
0x1f, 0x0a, 0x1b, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
|
||||
0x43, 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00,
|
||||
0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45,
|
||||
0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x10, 0x01, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x45, 0x53, 0x53,
|
||||
0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x5f, 0x55,
|
||||
0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x53, 0x53, 0x41,
|
||||
0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10,
|
||||
0x03, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50,
|
||||
0x45, 0x5f, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x04, 0x12, 0x22, 0x0a, 0x1e,
|
||||
0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x57,
|
||||
0x4e, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x05,
|
||||
0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45,
|
||||
0x5f, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x53, 0x53, 0x41,
|
||||
0x47, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x10, 0x07, 0x2a,
|
||||
0x4f, 0x0a, 0x12, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65,
|
||||
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45,
|
||||
0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e,
|
||||
0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x43,
|
||||
0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, 0x5a, 0x34, 0x10, 0x01,
|
||||
0x2a, 0x56, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12,
|
||||
0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d,
|
||||
0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4f, 0x4d,
|
||||
0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x45, 0x56, 0x45, 0x52, 0x10, 0x01,
|
||||
0x12, 0x16, 0x0a, 0x12, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f,
|
||||
0x41, 0x4c, 0x57, 0x41, 0x59, 0x53, 0x10, 0x02, 0x2a, 0x86, 0x01, 0x0a, 0x0a, 0x46, 0x6f, 0x6c,
|
||||
0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x4f, 0x4c, 0x44, 0x45,
|
||||
0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x43, 0x45,
|
||||
0x49, 0x56, 0x45, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f,
|
||||
0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x01,
|
||||
0x12, 0x1c, 0x0a, 0x18, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
|
||||
0x52, 0x45, 0x43, 0x45, 0x49, 0x56, 0x45, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x21,
|
||||
0x0a, 0x1d, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45,
|
||||
0x43, 0x45, 0x49, 0x56, 0x45, 0x5f, 0x45, 0x4e, 0x43, 0x52, 0x59, 0x50, 0x54, 0x45, 0x44, 0x10,
|
||||
0x03, 0x2a, 0x51, 0x0a, 0x10, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x70, 0x52,
|
||||
0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x1a, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f,
|
||||
0x53, 0x54, 0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x52, 0x55, 0x4e, 0x4e,
|
||||
0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x5f,
|
||||
0x53, 0x54, 0x4f, 0x50, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x55, 0x53,
|
||||
0x45, 0x44, 0x10, 0x01, 0x2a, 0xb0, 0x01, 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66,
|
||||
0x6f, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x49, 0x4e,
|
||||
0x46, 0x4f, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x00, 0x12, 0x1c,
|
||||
0x0a, 0x18, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x54, 0x59, 0x50, 0x45,
|
||||
0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1b,
|
||||
0x46, 0x49, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53,
|
||||
0x59, 0x4d, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x02, 0x1a, 0x02, 0x08,
|
||||
0x01, 0x12, 0x28, 0x0a, 0x20, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x54,
|
||||
0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x4d, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x44, 0x49, 0x52, 0x45,
|
||||
0x43, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x03, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x46,
|
||||
0x49, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x59,
|
||||
0x4d, 0x4c, 0x49, 0x4e, 0x4b, 0x10, 0x04, 0x2a, 0x76, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72,
|
||||
0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f,
|
||||
0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x16, 0x0a,
|
||||
0x12, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x47, 0x45, 0x4e, 0x45,
|
||||
0x52, 0x49, 0x43, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43,
|
||||
0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x53, 0x55, 0x43, 0x48, 0x5f, 0x46, 0x49, 0x4c, 0x45,
|
||||
0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45,
|
||||
0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x03, 0x2a,
|
||||
0x7e, 0x0a, 0x1e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50,
|
||||
0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x79, 0x70,
|
||||
0x65, 0x12, 0x2d, 0x0a, 0x29, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f,
|
||||
0x41, 0x44, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x50, 0x44, 0x41,
|
||||
0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x50, 0x50, 0x45, 0x4e, 0x44, 0x10, 0x00,
|
||||
0x12, 0x2d, 0x0a, 0x29, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x4c, 0x4f, 0x41,
|
||||
0x44, 0x5f, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54,
|
||||
0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x47, 0x45, 0x54, 0x10, 0x01, 0x42,
|
||||
0x70, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x65, 0x70, 0x42, 0x08, 0x42, 0x65, 0x70, 0x50,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x73, 0x79, 0x6e,
|
||||
0x63, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
|
||||
0x67, 0x65, 0x6e, 0x2f, 0x62, 0x65, 0x70, 0xa2, 0x02, 0x03, 0x42, 0x58, 0x58, 0xaa, 0x02, 0x03,
|
||||
0x42, 0x65, 0x70, 0xca, 0x02, 0x03, 0x42, 0x65, 0x70, 0xe2, 0x02, 0x0f, 0x42, 0x65, 0x70, 0x5c,
|
||||
0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x03, 0x42, 0x65,
|
||||
0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -28,20 +28,21 @@ type FileInfoTruncated struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
|
||||
ModifiedS int64 `protobuf:"varint,5,opt,name=modified_s,json=modifiedS,proto3" json:"modified_s,omitempty"`
|
||||
ModifiedBy uint64 `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3" json:"modified_by,omitempty"`
|
||||
Version *bep.Vector `protobuf:"bytes,9,opt,name=version,proto3" json:"version,omitempty"`
|
||||
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
||||
SymlinkTarget []byte `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
|
||||
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocks_hash,omitempty"`
|
||||
Encrypted []byte `protobuf:"bytes,19,opt,name=encrypted,proto3" json:"encrypted,omitempty"`
|
||||
Type bep.FileInfoType `protobuf:"varint,2,opt,name=type,proto3,enum=bep.FileInfoType" json:"type,omitempty"`
|
||||
Permissions uint32 `protobuf:"varint,4,opt,name=permissions,proto3" json:"permissions,omitempty"`
|
||||
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
|
||||
BlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
|
||||
Platform *bep.PlatformData `protobuf:"bytes,14,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Size int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
|
||||
ModifiedS int64 `protobuf:"varint,5,opt,name=modified_s,json=modifiedS,proto3" json:"modified_s,omitempty"`
|
||||
ModifiedBy uint64 `protobuf:"varint,12,opt,name=modified_by,json=modifiedBy,proto3" json:"modified_by,omitempty"`
|
||||
Version *bep.Vector `protobuf:"bytes,9,opt,name=version,proto3" json:"version,omitempty"`
|
||||
Sequence int64 `protobuf:"varint,10,opt,name=sequence,proto3" json:"sequence,omitempty"`
|
||||
SymlinkTarget []byte `protobuf:"bytes,17,opt,name=symlink_target,json=symlinkTarget,proto3" json:"symlink_target,omitempty"`
|
||||
BlocksHash []byte `protobuf:"bytes,18,opt,name=blocks_hash,json=blocksHash,proto3" json:"blocks_hash,omitempty"`
|
||||
PreviousBlocksHash []byte `protobuf:"bytes,20,opt,name=previous_blocks_hash,json=previousBlocksHash,proto3" json:"previous_blocks_hash,omitempty"`
|
||||
Encrypted []byte `protobuf:"bytes,19,opt,name=encrypted,proto3" json:"encrypted,omitempty"`
|
||||
Type bep.FileInfoType `protobuf:"varint,2,opt,name=type,proto3,enum=bep.FileInfoType" json:"type,omitempty"`
|
||||
Permissions uint32 `protobuf:"varint,4,opt,name=permissions,proto3" json:"permissions,omitempty"`
|
||||
ModifiedNs int32 `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3" json:"modified_ns,omitempty"`
|
||||
BlockSize int32 `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3" json:"block_size,omitempty"`
|
||||
Platform *bep.PlatformData `protobuf:"bytes,14,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
// The local_flags fields stores flags that are relevant to the local
|
||||
// host only. It is not part of the protocol, doesn't get sent or
|
||||
// received (we make sure to zero it), nonetheless we need it on our
|
||||
@@ -147,6 +148,13 @@ func (x *FileInfoTruncated) GetBlocksHash() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FileInfoTruncated) GetPreviousBlocksHash() []byte {
|
||||
if x != nil {
|
||||
return x.PreviousBlocksHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FileInfoTruncated) GetEncrypted() []byte {
|
||||
if x != nil {
|
||||
return x.Encrypted
|
||||
@@ -747,7 +755,7 @@ var file_dbproto_structs_proto_rawDesc = []byte{
|
||||
0x1a, 0x0d, 0x62, 0x65, 0x70, 0x2f, 0x62, 0x65, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
|
||||
0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x22, 0xe5, 0x05, 0x0a, 0x11, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x54, 0x72, 0x75,
|
||||
0x22, 0x97, 0x06, 0x0a, 0x11, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x54, 0x72, 0x75,
|
||||
0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69,
|
||||
0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x1d,
|
||||
@@ -763,107 +771,110 @@ var file_dbproto_structs_proto_rawDesc = []byte{
|
||||
0x67, 0x65, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x73, 0x79, 0x6d, 0x6c, 0x69,
|
||||
0x6e, 0x6b, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x62,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x63,
|
||||
0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x6e,
|
||||
0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x46, 0x69, 0x6c, 0x65,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x20,
|
||||
0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x18,
|
||||
0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4e,
|
||||
0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
|
||||
0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x7a, 0x65,
|
||||
0x12, 0x2d, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0e, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
|
||||
0x6d, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12,
|
||||
0x20, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0xe8,
|
||||
0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x6c, 0x61, 0x67,
|
||||
0x73, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73,
|
||||
0x68, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63,
|
||||
0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6e, 0x73, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52,
|
||||
0x0d, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x73, 0x12, 0x37,
|
||||
0x0a, 0x17, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x72, 0x61,
|
||||
0x69, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0xeb, 0x07, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x15, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x61, 0x69,
|
||||
0x6c, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74,
|
||||
0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65,
|
||||
0x64, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6e,
|
||||
0x6f, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x6f, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x4a, 0x04, 0x08, 0x10, 0x10, 0x11, 0x22, 0x91, 0x01, 0x0a, 0x0b, 0x46, 0x69, 0x6c,
|
||||
0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x65, 0x70, 0x2e,
|
||||
0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69,
|
||||
0x63, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x64,
|
||||
0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e, 0x69, 0x6e,
|
||||
0x76, 0x61, 0x6c, 0x69, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3f, 0x0a, 0x0b,
|
||||
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x08, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e,
|
||||
0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x56, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x33, 0x0a,
|
||||
0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06, 0x62, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62, 0x65, 0x70,
|
||||
0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x73, 0x22, 0x5c, 0x0a, 0x15, 0x49, 0x6e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x62,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0xe9, 0x07, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68,
|
||||
0x22, 0xe6, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66,
|
||||
0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65,
|
||||
0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72,
|
||||
0x69, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74,
|
||||
0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12,
|
||||
0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x03, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x64,
|
||||
0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08,
|
||||
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61,
|
||||
0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c,
|
||||
0x6f, 0x63, 0x61, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x4e, 0x0a, 0x09, 0x43, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x73, 0x53, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73,
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
|
||||
0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0xae, 0x01, 0x0a, 0x0e, 0x4f, 0x62,
|
||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x04,
|
||||
0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05,
|
||||
0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62,
|
||||
0x65, 0x6c, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x6e,
|
||||
0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72,
|
||||
0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12,
|
||||
0x29, 0x0a, 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70,
|
||||
0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x6d, 0x6f, 0x74,
|
||||
0x65, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x22, 0x6e, 0x0a, 0x0e, 0x4f, 0x62,
|
||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x04,
|
||||
0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x8c, 0x01, 0x0a, 0x0b, 0x63,
|
||||
0x6f, 0x6d, 0x2e, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x0c, 0x53, 0x74, 0x72, 0x75,
|
||||
0x63, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67,
|
||||
0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xa2,
|
||||
0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x44, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xca,
|
||||
0x02, 0x07, 0x44, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xe2, 0x02, 0x13, 0x44, 0x62, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea,
|
||||
0x02, 0x07, 0x44, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x72, 0x65,
|
||||
0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x68, 0x61, 0x73,
|
||||
0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x12, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75,
|
||||
0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x65,
|
||||
0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09,
|
||||
0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x46, 0x69,
|
||||
0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18,
|
||||
0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6e,
|
||||
0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65,
|
||||
0x64, 0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x69, 0x7a,
|
||||
0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69,
|
||||
0x7a, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0e,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x62, 0x65, 0x70, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66,
|
||||
0x6f, 0x72, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
|
||||
0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73,
|
||||
0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x6c,
|
||||
0x61, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x68,
|
||||
0x61, 0x73, 0x68, 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x6f, 0x64, 0x65,
|
||||
0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6e, 0x73, 0x18, 0xea, 0x07, 0x20, 0x01, 0x28,
|
||||
0x03, 0x52, 0x0d, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x73,
|
||||
0x12, 0x37, 0x0a, 0x17, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74,
|
||||
0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0xeb, 0x07, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x15, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72,
|
||||
0x61, 0x69, 0x6c, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c,
|
||||
0x65, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65,
|
||||
0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x07,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x25, 0x0a,
|
||||
0x0e, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18,
|
||||
0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x6f, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x4a, 0x04, 0x08, 0x10, 0x10, 0x11, 0x22, 0x91, 0x01, 0x0a, 0x0b, 0x46,
|
||||
0x69, 0x6c, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x07, 0x76, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x62, 0x65,
|
||||
0x70, 0x2e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x64,
|
||||
0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x64, 0x65,
|
||||
0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
|
||||
0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0e,
|
||||
0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3f,
|
||||
0x0a, 0x0b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x30, 0x0a,
|
||||
0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x14, 0x2e, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x56, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22,
|
||||
0x33, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x06,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x62,
|
||||
0x65, 0x70, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x62, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x73, 0x22, 0x5c, 0x0a, 0x15, 0x49, 0x6e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1f, 0x0a,
|
||||
0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x12, 0x20, 0x01,
|
||||
0x28, 0x0c, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x48, 0x61, 0x73, 0x68, 0x12, 0x22,
|
||||
0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0xe9,
|
||||
0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x61,
|
||||
0x73, 0x68, 0x22, 0xe6, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x66, 0x69,
|
||||
0x6c, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69,
|
||||
0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
||||
0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b,
|
||||
0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b,
|
||||
0x73, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62,
|
||||
0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65,
|
||||
0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x03, 0x52, 0x08, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x0a,
|
||||
0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f,
|
||||
0x63, 0x61, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0d, 0x52,
|
||||
0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x4e, 0x0a, 0x09, 0x43,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x53, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x64, 0x62, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x22, 0xae, 0x01, 0x0a, 0x0e,
|
||||
0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x2e,
|
||||
0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
|
||||
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x14,
|
||||
0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c,
|
||||
0x61, 0x62, 0x65, 0x6c, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f,
|
||||
0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||
0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65,
|
||||
0x64, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x65, 0x6e, 0x63, 0x72,
|
||||
0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x6d,
|
||||
0x6f, 0x74, 0x65, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x22, 0x6e, 0x0a, 0x0e,
|
||||
0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2e,
|
||||
0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
|
||||
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x12,
|
||||
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x8c, 0x01, 0x0a,
|
||||
0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x0c, 0x53, 0x74,
|
||||
0x72, 0x75, 0x63, 0x74, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69,
|
||||
0x6e, 0x67, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2f, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x64, 0x62, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x44, 0x62, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0xca, 0x02, 0x07, 0x44, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xe2, 0x02, 0x13, 0x44, 0x62,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||
0x61, 0xea, 0x02, 0x07, 0x44, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -1772,22 +1772,23 @@ func (f jsonFileInfo) MarshalJSON() ([]byte, error) {
|
||||
|
||||
func fileIntfJSONMap(f protocol.FileInfo) map[string]interface{} {
|
||||
out := map[string]interface{}{
|
||||
"name": f.FileName(),
|
||||
"type": f.FileType().String(),
|
||||
"size": f.FileSize(),
|
||||
"deleted": f.IsDeleted(),
|
||||
"invalid": f.IsInvalid(),
|
||||
"ignored": f.IsIgnored(),
|
||||
"mustRescan": f.MustRescan(),
|
||||
"noPermissions": !f.HasPermissionBits(),
|
||||
"modified": f.ModTime(),
|
||||
"modifiedBy": f.FileModifiedBy().String(),
|
||||
"sequence": f.SequenceNo(),
|
||||
"version": jsonVersionVector(f.FileVersion()),
|
||||
"localFlags": f.FileLocalFlags(),
|
||||
"platform": f.PlatformData(),
|
||||
"inodeChange": f.InodeChangeTime(),
|
||||
"blocksHash": f.FileBlocksHash(),
|
||||
"name": f.FileName(),
|
||||
"type": f.FileType().String(),
|
||||
"size": f.FileSize(),
|
||||
"deleted": f.IsDeleted(),
|
||||
"invalid": f.IsInvalid(),
|
||||
"ignored": f.IsIgnored(),
|
||||
"mustRescan": f.MustRescan(),
|
||||
"noPermissions": !f.HasPermissionBits(),
|
||||
"modified": f.ModTime(),
|
||||
"modifiedBy": f.FileModifiedBy().String(),
|
||||
"sequence": f.SequenceNo(),
|
||||
"version": jsonVersionVector(f.FileVersion()),
|
||||
"localFlags": f.FileLocalFlags(),
|
||||
"platform": f.PlatformData(),
|
||||
"inodeChange": f.InodeChangeTime(),
|
||||
"blocksHash": f.FileBlocksHash(),
|
||||
"previousBlocksHash": f.PreviousBlocksHash,
|
||||
}
|
||||
if f.HasPermissionBits() {
|
||||
out["permissions"] = fmt.Sprintf("%#o", f.FilePermissions())
|
||||
|
||||
@@ -25,9 +25,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
maxSessionLifetime = 7 * 24 * time.Hour
|
||||
maxActiveSessions = 25
|
||||
randomTokenLength = 64
|
||||
maxSessionLifetime = 7 * 24 * time.Hour
|
||||
maxActiveSessions = 25
|
||||
randomTokenLength = 64
|
||||
maxLoginRequestSize = 1 << 10 // one kibibyte for username+password
|
||||
)
|
||||
|
||||
func emitLoginAttempt(success bool, username string, r *http.Request, evLogger events.Logger) {
|
||||
@@ -182,7 +183,7 @@ func (m *basicAuthAndSessionMiddleware) passwordAuthHandler(w http.ResponseWrite
|
||||
Password string
|
||||
StayLoggedIn bool
|
||||
}
|
||||
if err := unmarshalTo(r.Body, &req); err != nil {
|
||||
if err := unmarshalTo(http.MaxBytesReader(w, r.Body, maxLoginRequestSize), &req); err != nil {
|
||||
l.Debugln("Failed to parse username and password:", err)
|
||||
http.Error(w, "Failed to parse username and password.", http.StatusBadRequest)
|
||||
return
|
||||
|
||||
@@ -459,6 +459,7 @@ func TestRecvOnlyRevertOwnID(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
go func() {
|
||||
defer cancel()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@@ -466,9 +467,9 @@ func TestRecvOnlyRevertOwnID(t *testing.T) {
|
||||
case <-sub.C():
|
||||
if file, _ := m.testCurrentFolderFile(f.ID, name); file.Deleted {
|
||||
t.Error("local file was deleted")
|
||||
cancel()
|
||||
return
|
||||
} else if file.IsEquivalent(fi, f.modTimeWindow) {
|
||||
cancel() // That's what we are waiting for
|
||||
return // That's what we are waiting for
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,7 +602,7 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, dbUpdateChan chan<
|
||||
}
|
||||
|
||||
// Remove it to replace with the dir.
|
||||
if !curFile.IsSymlink() && f.inConflict(curFile.Version, file.Version) {
|
||||
if !curFile.IsSymlink() && file.InConflictWith(curFile) {
|
||||
// The new file has been changed in conflict with the existing one. We
|
||||
// should file it away as a conflict instead of just removing or
|
||||
// archiving.
|
||||
@@ -800,7 +800,7 @@ func (f *sendReceiveFolder) handleSymlinkCheckExisting(file protocol.FileInfo, s
|
||||
}
|
||||
// Remove it to replace with the symlink. This also handles the
|
||||
// "change symlink type" path.
|
||||
if !curFile.IsDirectory() && !curFile.IsSymlink() && f.inConflict(curFile.Version, file.Version) {
|
||||
if !curFile.IsDirectory() && !curFile.IsSymlink() && file.InConflictWith(curFile) {
|
||||
// The new file has been changed in conflict with the existing one. We
|
||||
// should file it away as a conflict instead of just removing or
|
||||
// archiving.
|
||||
@@ -923,7 +923,7 @@ func (f *sendReceiveFolder) deleteFileWithCurrent(file, cur protocol.FileInfo, h
|
||||
}
|
||||
|
||||
switch {
|
||||
case f.inConflict(cur.Version, file.Version) && !cur.IsSymlink():
|
||||
case file.InConflictWith(cur) && !cur.IsSymlink():
|
||||
// If the delete constitutes winning a conflict, we move the file to
|
||||
// a conflict copy instead of doing the delete
|
||||
err = f.inWritableDir(func(name string) error {
|
||||
@@ -1652,7 +1652,7 @@ func (f *sendReceiveFolder) performFinish(file, curFile protocol.FileInfo, hasCu
|
||||
return fmt.Errorf("checking existing file: %w", err)
|
||||
}
|
||||
|
||||
if !curFile.IsDirectory() && !curFile.IsSymlink() && f.inConflict(curFile.Version, file.Version) {
|
||||
if !curFile.IsDirectory() && !curFile.IsSymlink() && file.InConflictWith(curFile) {
|
||||
// The new file has been changed in conflict with the existing one. We
|
||||
// should file it away as a conflict instead of just removing or
|
||||
// archiving.
|
||||
@@ -1847,22 +1847,6 @@ func (f *sendReceiveFolder) pullScannerRoutine(scanChan <-chan string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *sendReceiveFolder) inConflict(current, replacement protocol.Vector) bool {
|
||||
if current.Concurrent(replacement) {
|
||||
// Obvious case
|
||||
return true
|
||||
}
|
||||
if replacement.Counter(f.shortID) > current.Counter(f.shortID) {
|
||||
// The replacement file contains a higher version for ourselves than
|
||||
// what we have. This isn't supposed to be possible, since it's only
|
||||
// we who can increment that counter. We take it as a sign that
|
||||
// something is wrong (our index may have been corrupted or removed)
|
||||
// and flag it as a conflict.
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *sendReceiveFolder) moveForConflict(name, lastModBy string, scanChan chan<- string) error {
|
||||
if isConflict(name) {
|
||||
f.sl.Info("Conflict on existing conflict copy; not copying again", slogutil.FilePath(name))
|
||||
|
||||
@@ -2615,6 +2615,7 @@ func (m *model) generateClusterConfigRLocked(device protocol.DeviceID) (*protoco
|
||||
protocolFolder.StopReason = protocol.FolderStopReasonPaused
|
||||
}
|
||||
|
||||
nextDevice:
|
||||
for _, folderDevice := range folderCfg.Devices {
|
||||
deviceCfg, _ := m.cfg.Device(folderDevice.DeviceID)
|
||||
|
||||
@@ -2630,9 +2631,17 @@ func (m *model) generateClusterConfigRLocked(device protocol.DeviceID) (*protoco
|
||||
if deviceCfg.DeviceID == m.id && hasEncryptionToken {
|
||||
protocolDevice.EncryptionPasswordToken = encryptionToken
|
||||
} else if folderDevice.EncryptionPassword != "" {
|
||||
protocolDevice.EncryptionPasswordToken = protocol.PasswordToken(m.keyGen, folderCfg.ID, folderDevice.EncryptionPassword)
|
||||
// For encrypted/untrusted devices we send the encryption
|
||||
// token and prepare the password. We do not send any
|
||||
// information about untrusted devices to _other_ devices,
|
||||
// as they are not normal peers sharing the folder and we
|
||||
// don't want things like the introducer features to kick in
|
||||
// for them.
|
||||
if folderDevice.DeviceID == device {
|
||||
protocolDevice.EncryptionPasswordToken = protocol.PasswordToken(m.keyGen, folderCfg.ID, folderDevice.EncryptionPassword)
|
||||
passwords[folderCfg.ID] = folderDevice.EncryptionPassword
|
||||
} else {
|
||||
continue nextDevice
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -474,6 +474,84 @@ func TestClusterConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestClusterConfigEncrypted(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := config.New(device1)
|
||||
cfg.Options.MinHomeDiskFree.Value = 0 // avoids unnecessary free space checks
|
||||
cfg.Devices = []config.DeviceConfiguration{
|
||||
{
|
||||
DeviceID: device1,
|
||||
},
|
||||
{
|
||||
DeviceID: device2,
|
||||
},
|
||||
}
|
||||
cfg.Folders = []config.FolderConfiguration{
|
||||
{
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder1",
|
||||
Path: "testdata1",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
{DeviceID: device1, EncryptionPassword: "trololol"}, // not included, untrusted
|
||||
{DeviceID: device2},
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder2",
|
||||
Path: "testdata2",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
{DeviceID: device1, EncryptionPassword: "trololol"}, // not included, untrusted
|
||||
{DeviceID: device2, EncryptionPassword: "trololol"}, // included, is destinationd device
|
||||
},
|
||||
},
|
||||
{
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
ID: "folder3",
|
||||
Path: "testdata3",
|
||||
Devices: []config.FolderDeviceConfiguration{
|
||||
{DeviceID: device1},
|
||||
// should not be included, does not include device2
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
wrapper, cancel := newConfigWrapper(cfg)
|
||||
defer cancel()
|
||||
m := newModel(t, wrapper, myID, nil)
|
||||
m.ServeBackground()
|
||||
defer cleanupModel(m)
|
||||
|
||||
cm, _ := m.generateClusterConfig(device2)
|
||||
|
||||
if l := len(cm.Folders); l != 2 {
|
||||
t.Fatalf("Incorrect number of folders %d != 2", l)
|
||||
}
|
||||
|
||||
r := cm.Folders[0]
|
||||
if r.ID != "folder1" {
|
||||
t.Errorf("Incorrect folder %q != folder1", r.ID)
|
||||
}
|
||||
if l := len(r.Devices); l != 1 {
|
||||
t.Errorf("Incorrect number of devices %d != 1", l)
|
||||
}
|
||||
if id := r.Devices[0].ID; id != device2 {
|
||||
t.Errorf("Incorrect device ID %s != %s", id, device2)
|
||||
}
|
||||
|
||||
r = cm.Folders[1]
|
||||
if r.ID != "folder2" {
|
||||
t.Errorf("Incorrect folder %q != folder2", r.ID)
|
||||
}
|
||||
if l := len(r.Devices); l != 1 {
|
||||
t.Errorf("Incorrect number of devices %d != 1", l)
|
||||
}
|
||||
if id := r.Devices[0].ID; id != device2 {
|
||||
t.Errorf("Incorrect device ID %s != %s", id, device2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntroducer(t *testing.T) {
|
||||
var introducedByAnyone protocol.DeviceID
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package osutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -142,3 +143,21 @@ func IsDeleted(ffs fs.Filesystem, name string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func DirSize(location string) int64 {
|
||||
entries, err := os.ReadDir(location)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
var size int64
|
||||
for _, entry := range entries {
|
||||
fi, err := entry.Info()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
size += fi.Size()
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
@@ -113,17 +113,18 @@ const (
|
||||
)
|
||||
|
||||
type FileInfo struct {
|
||||
Name string
|
||||
Size int64
|
||||
ModifiedS int64
|
||||
ModifiedBy ShortID
|
||||
Version Vector
|
||||
Sequence int64
|
||||
Blocks []BlockInfo
|
||||
SymlinkTarget []byte
|
||||
BlocksHash []byte
|
||||
Encrypted []byte
|
||||
Platform PlatformData
|
||||
Name string
|
||||
Size int64
|
||||
ModifiedS int64
|
||||
ModifiedBy ShortID
|
||||
Version Vector
|
||||
Sequence int64
|
||||
Blocks []BlockInfo
|
||||
SymlinkTarget []byte
|
||||
BlocksHash []byte
|
||||
PreviousBlocksHash []byte
|
||||
Encrypted []byte
|
||||
Platform PlatformData
|
||||
|
||||
Type FileInfoType
|
||||
Permissions uint32
|
||||
@@ -138,10 +139,6 @@ type FileInfo struct {
|
||||
// the protocol.
|
||||
LocalFlags FlagLocal
|
||||
|
||||
// The version_hash is an implementation detail and not part of the wire
|
||||
// format.
|
||||
VersionHash []byte
|
||||
|
||||
// The time when the inode was last changed (i.e., permissions, xattrs
|
||||
// etc changed). This is host-local, not sent over the wire.
|
||||
InodeChangeNs int64
|
||||
@@ -165,34 +162,54 @@ func (f *FileInfo) ToWire(withInternalFields bool) *bep.FileInfo {
|
||||
blocks[j] = b.ToWire()
|
||||
}
|
||||
w := &bep.FileInfo{
|
||||
Name: f.Name,
|
||||
Size: f.Size,
|
||||
ModifiedS: f.ModifiedS,
|
||||
ModifiedBy: uint64(f.ModifiedBy),
|
||||
Version: f.Version.ToWire(),
|
||||
Sequence: f.Sequence,
|
||||
Blocks: blocks,
|
||||
SymlinkTarget: f.SymlinkTarget,
|
||||
BlocksHash: f.BlocksHash,
|
||||
Encrypted: f.Encrypted,
|
||||
Type: f.Type,
|
||||
Permissions: f.Permissions,
|
||||
ModifiedNs: f.ModifiedNs,
|
||||
BlockSize: f.RawBlockSize,
|
||||
Platform: f.Platform.toWire(),
|
||||
Deleted: f.Deleted,
|
||||
Invalid: f.IsInvalid(),
|
||||
NoPermissions: f.NoPermissions,
|
||||
Name: f.Name,
|
||||
Size: f.Size,
|
||||
ModifiedS: f.ModifiedS,
|
||||
ModifiedBy: uint64(f.ModifiedBy),
|
||||
Version: f.Version.ToWire(),
|
||||
Sequence: f.Sequence,
|
||||
Blocks: blocks,
|
||||
SymlinkTarget: f.SymlinkTarget,
|
||||
BlocksHash: f.BlocksHash,
|
||||
PreviousBlocksHash: f.PreviousBlocksHash,
|
||||
Encrypted: f.Encrypted,
|
||||
Type: f.Type,
|
||||
Permissions: f.Permissions,
|
||||
ModifiedNs: f.ModifiedNs,
|
||||
BlockSize: f.RawBlockSize,
|
||||
Platform: f.Platform.toWire(),
|
||||
Deleted: f.Deleted,
|
||||
Invalid: f.IsInvalid(),
|
||||
NoPermissions: f.NoPermissions,
|
||||
}
|
||||
if withInternalFields {
|
||||
w.LocalFlags = uint32(f.LocalFlags)
|
||||
w.VersionHash = f.VersionHash
|
||||
w.InodeChangeNs = f.InodeChangeNs
|
||||
w.EncryptionTrailerSize = int32(f.EncryptionTrailerSize)
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
func (f *FileInfo) InConflictWith(previous FileInfo) bool {
|
||||
if f.Version.GreaterEqual(previous.Version) {
|
||||
// If the new file is strictly greater in the ordering than the
|
||||
// existing file, it is not a conflict. If any counter has moved
|
||||
// backwards, or different counters have increased independently,
|
||||
// then the file is not greater but concurrent and we don't take
|
||||
// this branch.
|
||||
return false
|
||||
}
|
||||
|
||||
if len(f.PreviousBlocksHash) == 0 || len(f.BlocksHash) == 0 {
|
||||
// Don't have data to make a content determination, or the type has
|
||||
// changed (file to directory, etc). Consider it a conflict.
|
||||
return true
|
||||
}
|
||||
// If the new file is based on the old contents we have, it's not really
|
||||
// a conflict.
|
||||
return !bytes.Equal(f.PreviousBlocksHash, previous.BlocksHash)
|
||||
}
|
||||
|
||||
// WinsConflict returns true if "f" is the one to choose when it is in
|
||||
// conflict with "other".
|
||||
func (f *FileInfo) WinsConflict(other FileInfo) bool {
|
||||
@@ -259,6 +276,7 @@ type FileInfoWithoutBlocks interface {
|
||||
// GetBlocks() []*bep.BlockInfo // not included
|
||||
GetSymlinkTarget() []byte
|
||||
GetBlocksHash() []byte
|
||||
GetPreviousBlocksHash() []byte
|
||||
GetEncrypted() []byte
|
||||
GetType() FileInfoType
|
||||
GetPermissions() uint32
|
||||
@@ -266,7 +284,6 @@ type FileInfoWithoutBlocks interface {
|
||||
GetBlockSize() int32
|
||||
GetPlatform() *bep.PlatformData
|
||||
GetLocalFlags() uint32
|
||||
GetVersionHash() []byte
|
||||
GetInodeChangeNs() int64
|
||||
GetEncryptionTrailerSize() int32
|
||||
GetDeleted() bool
|
||||
@@ -280,31 +297,31 @@ func fileInfoFromWireWithBlocks(w FileInfoWithoutBlocks, blocks []BlockInfo) Fil
|
||||
localFlags = FlagLocalRemoteInvalid
|
||||
}
|
||||
return FileInfo{
|
||||
Name: w.GetName(),
|
||||
Size: w.GetSize(),
|
||||
ModifiedS: w.GetModifiedS(),
|
||||
ModifiedBy: ShortID(w.GetModifiedBy()),
|
||||
Version: VectorFromWire(w.GetVersion()),
|
||||
Sequence: w.GetSequence(),
|
||||
Blocks: blocks,
|
||||
SymlinkTarget: w.GetSymlinkTarget(),
|
||||
BlocksHash: w.GetBlocksHash(),
|
||||
Encrypted: w.GetEncrypted(),
|
||||
Type: w.GetType(),
|
||||
Permissions: w.GetPermissions(),
|
||||
ModifiedNs: w.GetModifiedNs(),
|
||||
RawBlockSize: w.GetBlockSize(),
|
||||
Platform: platformDataFromWire(w.GetPlatform()),
|
||||
Deleted: w.GetDeleted(),
|
||||
LocalFlags: localFlags,
|
||||
NoPermissions: w.GetNoPermissions(),
|
||||
Name: w.GetName(),
|
||||
Size: w.GetSize(),
|
||||
ModifiedS: w.GetModifiedS(),
|
||||
ModifiedBy: ShortID(w.GetModifiedBy()),
|
||||
Version: VectorFromWire(w.GetVersion()),
|
||||
Sequence: w.GetSequence(),
|
||||
Blocks: blocks,
|
||||
SymlinkTarget: w.GetSymlinkTarget(),
|
||||
BlocksHash: w.GetBlocksHash(),
|
||||
PreviousBlocksHash: w.GetPreviousBlocksHash(),
|
||||
Encrypted: w.GetEncrypted(),
|
||||
Type: w.GetType(),
|
||||
Permissions: w.GetPermissions(),
|
||||
ModifiedNs: w.GetModifiedNs(),
|
||||
RawBlockSize: w.GetBlockSize(),
|
||||
Platform: platformDataFromWire(w.GetPlatform()),
|
||||
Deleted: w.GetDeleted(),
|
||||
LocalFlags: localFlags,
|
||||
NoPermissions: w.GetNoPermissions(),
|
||||
}
|
||||
}
|
||||
|
||||
func FileInfoFromDB(w *bep.FileInfo) FileInfo {
|
||||
f := FileInfoFromWire(w)
|
||||
f.LocalFlags = FlagLocal(w.LocalFlags)
|
||||
f.VersionHash = w.VersionHash
|
||||
f.InodeChangeNs = w.InodeChangeNs
|
||||
f.EncryptionTrailerSize = int(w.EncryptionTrailerSize)
|
||||
return f
|
||||
@@ -313,7 +330,6 @@ func FileInfoFromDB(w *bep.FileInfo) FileInfo {
|
||||
func FileInfoFromDBTruncated(w FileInfoWithoutBlocks) FileInfo {
|
||||
f := fileInfoFromWireWithBlocks(w, nil)
|
||||
f.LocalFlags = FlagLocal(w.GetLocalFlags())
|
||||
f.VersionHash = w.GetVersionHash()
|
||||
f.InodeChangeNs = w.GetInodeChangeNs()
|
||||
f.EncryptionTrailerSize = int(w.GetEncryptionTrailerSize())
|
||||
f.truncated = true
|
||||
@@ -323,14 +339,14 @@ func FileInfoFromDBTruncated(w FileInfoWithoutBlocks) FileInfo {
|
||||
func (f FileInfo) String() string {
|
||||
switch f.Type {
|
||||
case FileInfoTypeDirectory:
|
||||
return fmt.Sprintf("Directory{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, Platform:%v, InodeChangeTime:%v}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Deleted, f.IsInvalid(), f.LocalFlags, f.NoPermissions, f.Platform, f.InodeChangeTime())
|
||||
return fmt.Sprintf("Directory{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, Platform:%v, InodeChangeTime:%v}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Deleted, f.IsInvalid(), f.LocalFlags, f.NoPermissions, f.Platform, f.InodeChangeTime())
|
||||
case FileInfoTypeFile:
|
||||
return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Length:%d, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, BlockSize:%d, NumBlocks:%d, BlocksHash:%x, Platform:%v, InodeChangeTime:%v}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Size, f.Deleted, f.IsInvalid(), f.LocalFlags, f.NoPermissions, f.RawBlockSize, len(f.Blocks), f.BlocksHash, f.Platform, f.InodeChangeTime())
|
||||
return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Length:%d, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, BlockSize:%d, NumBlocks:%d, BlocksHash:%x, Platform:%v, InodeChangeTime:%v}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Size, f.Deleted, f.IsInvalid(), f.LocalFlags, f.NoPermissions, f.RawBlockSize, len(f.Blocks), f.BlocksHash, f.Platform, f.InodeChangeTime())
|
||||
case FileInfoTypeSymlink, FileInfoTypeSymlinkDirectory, FileInfoTypeSymlinkFile:
|
||||
return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, SymlinkTarget:%q, Platform:%v, InodeChangeTime:%v}",
|
||||
f.Name, f.Type, f.Sequence, f.Version, f.VersionHash, f.Deleted, f.IsInvalid(), f.LocalFlags, f.NoPermissions, f.SymlinkTarget, f.Platform, f.InodeChangeTime())
|
||||
return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, SymlinkTarget:%q, Platform:%v, InodeChangeTime:%v}",
|
||||
f.Name, f.Type, f.Sequence, f.Version, f.Deleted, f.IsInvalid(), f.LocalFlags, f.NoPermissions, f.SymlinkTarget, f.Platform, f.InodeChangeTime())
|
||||
default:
|
||||
panic("mystery file type detected")
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ var bufPool = sync.Pool{
|
||||
},
|
||||
}
|
||||
|
||||
const hashLength = sha256.Size
|
||||
|
||||
var hashPool = sync.Pool{
|
||||
New: func() any {
|
||||
return sha256.New()
|
||||
@@ -43,9 +45,6 @@ func Blocks(ctx context.Context, r io.Reader, blocksize int, sizehint int64, cou
|
||||
counter = &noopCounter{}
|
||||
}
|
||||
|
||||
hf := hashPool.Get().(hash.Hash) //nolint:forcetypeassert
|
||||
const hashLength = sha256.Size
|
||||
|
||||
var blocks []protocol.BlockInfo
|
||||
var hashes, thisHash []byte
|
||||
|
||||
@@ -62,8 +61,14 @@ func Blocks(ctx context.Context, r io.Reader, blocksize int, sizehint int64, cou
|
||||
hashes = make([]byte, 0, hashLength*numBlocks)
|
||||
}
|
||||
|
||||
hf := hashPool.Get().(hash.Hash) //nolint:forcetypeassert
|
||||
// A 32k buffer is used for copying into the hash function.
|
||||
buf := bufPool.Get().(*[bufSize]byte)[:] //nolint:forcetypeassert
|
||||
defer func() {
|
||||
bufPool.Put((*[bufSize]byte)(buf))
|
||||
hf.Reset()
|
||||
hashPool.Put(hf)
|
||||
}()
|
||||
|
||||
var offset int64
|
||||
lr := io.LimitReader(r, int64(blocksize)).(*io.LimitedReader)
|
||||
@@ -102,9 +107,6 @@ func Blocks(ctx context.Context, r io.Reader, blocksize int, sizehint int64, cou
|
||||
|
||||
hf.Reset()
|
||||
}
|
||||
bufPool.Put((*[bufSize]byte)(buf))
|
||||
hf.Reset()
|
||||
hashPool.Put(hf)
|
||||
|
||||
if len(blocks) == 0 {
|
||||
// Empty file
|
||||
|
||||
@@ -655,6 +655,7 @@ func (w *walker) updateFileInfo(dst, src protocol.FileInfo) protocol.FileInfo {
|
||||
dst.Version = src.Version.Update(w.ShortID)
|
||||
dst.ModifiedBy = w.ShortID
|
||||
dst.LocalFlags = w.LocalFlags
|
||||
dst.PreviousBlocksHash = src.BlocksHash
|
||||
|
||||
// Copy OS data from src to dst, unless it was already set on dst.
|
||||
dst.Platform.MergeWith(&src.Platform)
|
||||
|
||||
@@ -162,8 +162,12 @@ func (a *App) startup() error {
|
||||
}()
|
||||
}
|
||||
|
||||
perf := ur.CpuBench(context.Background(), 3, 150*time.Millisecond)
|
||||
slog.Info("Measured hashing performance", "perf", fmt.Sprintf("%.02f MB/s", perf))
|
||||
if slog.Default().Enabled(context.Background(), slog.LevelInfo) {
|
||||
go func() {
|
||||
perf := ur.CpuBench(context.Background(), 3, 150*time.Millisecond)
|
||||
slog.Info("Measured hashing performance", "perf", fmt.Sprintf("%.02f MB/s", perf))
|
||||
}()
|
||||
}
|
||||
|
||||
if a.opts.ResetDeltaIdxs {
|
||||
slog.Info("Reinitializing delta index IDs")
|
||||
|
||||
@@ -52,7 +52,7 @@ type Report struct {
|
||||
ExternalVersioning int `json:"externalVersioning,omitempty" metric:"folder_feature{feature=VersioningExternal},summary" since:"2"`
|
||||
StaggeredVersioning int `json:"staggeredVersioning,omitempty" metric:"folder_feature{feature=VersioningStaggered},summary" since:"2"`
|
||||
TrashcanVersioning int `json:"trashcanVersioning,omitempty" metric:"folder_feature{feature=VersioningTrashcan},summary" since:"2"`
|
||||
} `json:"folderUses,omitempty" since:"2"`
|
||||
} `json:"folderUses,omitzero" since:"2"`
|
||||
|
||||
DeviceUses struct {
|
||||
Introducer int `json:"introducer,omitempty" metric:"device_feature{feature=Introducer},summary" since:"2"`
|
||||
@@ -62,20 +62,20 @@ type Report struct {
|
||||
CompressNever int `json:"compressNever,omitempty" metric:"device_feature{feature=CompressNever},summary" since:"2"`
|
||||
DynamicAddr int `json:"dynamicAddr,omitempty" metric:"device_feature{feature=AddressDynamic},summary" since:"2"`
|
||||
StaticAddr int `json:"staticAddr,omitempty" metric:"device_feature{feature=AddressStatic},summary" since:"2"`
|
||||
} `json:"deviceUses,omitempty" since:"2"`
|
||||
} `json:"deviceUses,omitzero" since:"2"`
|
||||
|
||||
Announce struct {
|
||||
GlobalEnabled bool `json:"globalEnabled,omitempty" metric:"discovery_feature_count{feature=GlobalEnabled},gauge" since:"2"`
|
||||
LocalEnabled bool `json:"localEnabled,omitempty" metric:"discovery_feature_count{feature=LocalEnabled},gauge" since:"2"`
|
||||
DefaultServersDNS int `json:"defaultServersDNS,omitempty" metric:"discovery_default_servers,summary" since:"2"`
|
||||
OtherServers int `json:"otherServers,omitempty" metric:"discovery_other_servers,summary" since:"2"`
|
||||
} `json:"announce,omitempty" since:"2"`
|
||||
} `json:"announce,omitzero" since:"2"`
|
||||
|
||||
Relays struct {
|
||||
Enabled bool `json:"enabled,omitempty" metric:"relay_feature_enabled,gauge" since:"2"`
|
||||
DefaultServers int `json:"defaultServers,omitempty" metric:"relay_feature_count{feature=DefaultServers},summary" since:"2"`
|
||||
OtherServers int `json:"otherServers,omitempty" metric:"relay_feature_count{feature=OtherServers},summary" since:"2"`
|
||||
} `json:"relays,omitempty" since:"2"`
|
||||
} `json:"relays,omitzero" since:"2"`
|
||||
|
||||
UsesRateLimit bool `json:"usesRateLimit,omitempty" metric:"feature_count{feature=RateLimitsEnabled},gauge" since:"2"`
|
||||
UpgradeAllowedManual bool `json:"upgradeAllowedManual,omitempty" metric:"feature_count{feature=UpgradeAllowedManual},gauge" since:"2"`
|
||||
@@ -127,13 +127,13 @@ type Report struct {
|
||||
SyncXattrs int `json:"syncXattrs,omitempty" metric:"folder_feature{feature=SyncXattrs},summary" since:"3"`
|
||||
SendOwnership int `json:"sendOwnership,omitempty" metric:"folder_feature{feature=SendOwnership},summary" since:"3"`
|
||||
SyncOwnership int `json:"syncOwnership,omitempty" metric:"folder_feature{feature=SyncOwnership},summary" since:"3"`
|
||||
} `json:"folderUsesV3,omitempty" since:"3"`
|
||||
} `json:"folderUsesV3,omitzero" since:"3"`
|
||||
|
||||
DeviceUsesV3 struct {
|
||||
Untrusted int `json:"untrusted,omitempty" metric:"device_feature{feature=Untrusted},summary" since:"3"`
|
||||
UsesRateLimit int `json:"usesRateLimit,omitempty" metric:"device_feature{feature=RateLimitsEnabled},summary" since:"3"`
|
||||
MultipleConnections int `json:"multipleConnections,omitempty" metric:"device_feature{feature=MultipleConnections},summary" since:"3"`
|
||||
} `json:"deviceUsesV3,omitempty" since:"3"`
|
||||
} `json:"deviceUsesV3,omitzero" since:"3"`
|
||||
|
||||
GUIStats struct {
|
||||
Enabled int `json:"enabled,omitempty" metric:"gui_feature_count{feature=Enabled},summary" since:"3"`
|
||||
@@ -146,7 +146,7 @@ type Report struct {
|
||||
ListenLocal int `json:"listenLocal,omitempty" metric:"gui_feature_count{feature=ListenLocal},summary" since:"3"`
|
||||
ListenUnspecified int `json:"listenUnspecified,omitempty" metric:"gui_feature_count{feature=ListenUnspecified},summary" since:"3"`
|
||||
Theme map[string]int `json:"theme,omitempty" metric:"gui_theme,summaryVec:theme" since:"3"`
|
||||
} `json:"guiStats,omitempty" since:"3"`
|
||||
} `json:"guiStats,omitzero" since:"3"`
|
||||
|
||||
BlockStats struct {
|
||||
Total int `json:"total,omitempty" metric:"blocks_processed_total,gauge" since:"3"`
|
||||
@@ -155,7 +155,7 @@ type Report struct {
|
||||
Pulled int `json:"pulled,omitempty" metric:"blocks_processed{source=pulled},gauge" since:"3"`
|
||||
CopyOrigin int `json:"copyOrigin,omitempty" metric:"blocks_processed{source=copy_origin},gauge" since:"3"`
|
||||
CopyElsewhere int `json:"copyElsewhere,omitempty" metric:"blocks_processed{source=copy_elsewhere},gauge" since:"3"`
|
||||
} `json:"blockStats,omitempty" since:"3"`
|
||||
} `json:"blockStats,omitzero" since:"3"`
|
||||
|
||||
TransportStats map[string]int `json:"transportStats,omitempty" since:"3"`
|
||||
|
||||
@@ -169,32 +169,32 @@ type Report struct {
|
||||
EscapedIncludes int `json:"escapedIncludes,omitempty" metric:"folder_ignore_lines{kind=escapedIncludes},summary" since:"3"`
|
||||
DoubleStars int `json:"doubleStars,omitempty" metric:"folder_ignore_lines{kind=doubleStars},summary" since:"3"`
|
||||
Stars int `json:"stars,omitempty" metric:"folder_ignore_lines{kind=stars},summary" since:"3"`
|
||||
} `json:"ignoreStats,omitempty" since:"3"`
|
||||
} `json:"ignoreStats,omitzero" since:"3"`
|
||||
|
||||
// Added in post processing
|
||||
Received time.Time `json:"received,omitempty"`
|
||||
Received time.Time `json:"received,omitzero"`
|
||||
Date string `json:"date,omitempty"`
|
||||
Address string `json:"address,omitempty"`
|
||||
OS string `json:"os" metric:"reports_total,gaugeVec:os"`
|
||||
Arch string `json:"arch" metric:"reports_total,gaugeVec:arch"`
|
||||
Compiler string `json:"compiler" metric:"builder,gaugeVec:compiler"`
|
||||
Builder string `json:"builder" metric:"builder,gaugeVec:builder"`
|
||||
Distribution string `json:"distribution" metric:"builder,gaugeVec:distribution"`
|
||||
Country string `json:"country" metric:"location,gaugeVec:country"`
|
||||
CountryCode string `json:"countryCode" metric:"location,gaugeVec:countryCode"`
|
||||
MajorVersion string `json:"majorVersion" metric:"reports_by_major_total,gaugeVec:version"`
|
||||
OS string `json:"os,omitempty" metric:"reports_total,gaugeVec:os"`
|
||||
Arch string `json:"arch,omitempty" metric:"reports_total,gaugeVec:arch"`
|
||||
Compiler string `json:"compiler,omitempty" metric:"builder,gaugeVec:compiler"`
|
||||
Builder string `json:"builder,omitempty" metric:"builder,gaugeVec:builder"`
|
||||
Distribution string `json:"distribution,omitempty" metric:"builder,gaugeVec:distribution"`
|
||||
Country string `json:"country,omitempty" metric:"location,gaugeVec:country"`
|
||||
CountryCode string `json:"countryCode,omitempty" metric:"location,gaugeVec:countryCode"`
|
||||
MajorVersion string `json:"majorVersion,omitempty" metric:"reports_by_major_total,gaugeVec:version"`
|
||||
|
||||
// Once more to create a metric on OS, arch, distribution
|
||||
DistDist string `json:"distDist" metric:"distribution,gaugeVec:distribution"`
|
||||
DistOS string `json:"distOS" metric:"distribution,gaugeVec:os"`
|
||||
DistArch string `json:"distArch" metric:"distribution,gaugeVec:arch"`
|
||||
DistDist string `json:"distDist,omitempty" metric:"distribution,gaugeVec:distribution"`
|
||||
DistOS string `json:"distOS,omitempty" metric:"distribution,gaugeVec:os"`
|
||||
DistArch string `json:"distArch,omitempty" metric:"distribution,gaugeVec:arch"`
|
||||
|
||||
// Database counts
|
||||
Database struct {
|
||||
ModernCSQLite bool `json:"modernCSQLite" metric:"database_engine{engine=modernc-sqlite},gauge"`
|
||||
MattnSQLite bool `json:"mattnSQLite" metric:"database_engine{engine=mattn-sqlite},gauge"`
|
||||
LevelDB bool `json:"levelDB" metric:"database_engine{engine=leveldb},gauge"`
|
||||
} `json:"database"`
|
||||
ModernCSQLite bool `json:"modernCSQLite,omitempty" metric:"database_engine{engine=modernc-sqlite},gauge"`
|
||||
MattnSQLite bool `json:"mattnSQLite,omitempty" metric:"database_engine{engine=mattn-sqlite},gauge"`
|
||||
LevelDB bool `json:"levelDB,omitempty" metric:"database_engine{engine=leveldb},gauge"`
|
||||
} `json:"database,omitzero"`
|
||||
}
|
||||
|
||||
func New() *Report {
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "STDISCOSRV" "1" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
stdiscosrv \- Syncthing Discovery Server
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "STRELAYSRV" "1" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
strelaysrv \- Syncthing Relay Server
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -28,7 +28,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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-BEP" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-bep \- Block Exchange Protocol v1
|
||||
.SH INTRODUCTION AND DEFINITIONS
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-CONFIG" "5" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-config \- Syncthing Configuration
|
||||
.SH OVERVIEW
|
||||
@@ -148,7 +148,7 @@ may no longer correspond to the defaults.
|
||||
<markerName>.stfolder</markerName>
|
||||
<copyOwnershipFromParent>false</copyOwnershipFromParent>
|
||||
<modTimeWindowS>0</modTimeWindowS>
|
||||
<maxConcurrentWrites>2</maxConcurrentWrites>
|
||||
<maxConcurrentWrites>16</maxConcurrentWrites>
|
||||
<disableFsync>false</disableFsync>
|
||||
<blockPullOrder>standard</blockPullOrder>
|
||||
<copyRangeMethod>standard</copyRangeMethod>
|
||||
@@ -250,7 +250,7 @@ may no longer correspond to the defaults.
|
||||
<markerName>.stfolder</markerName>
|
||||
<copyOwnershipFromParent>false</copyOwnershipFromParent>
|
||||
<modTimeWindowS>0</modTimeWindowS>
|
||||
<maxConcurrentWrites>2</maxConcurrentWrites>
|
||||
<maxConcurrentWrites>16</maxConcurrentWrites>
|
||||
<disableFsync>false</disableFsync>
|
||||
<blockPullOrder>standard</blockPullOrder>
|
||||
<copyRangeMethod>standard</copyRangeMethod>
|
||||
@@ -340,7 +340,7 @@ GUI.
|
||||
<markerName>.stfolder</markerName>
|
||||
<copyOwnershipFromParent>false</copyOwnershipFromParent>
|
||||
<modTimeWindowS>0</modTimeWindowS>
|
||||
<maxConcurrentWrites>2</maxConcurrentWrites>
|
||||
<maxConcurrentWrites>16</maxConcurrentWrites>
|
||||
<disableFsync>false</disableFsync>
|
||||
<blockPullOrder>standard</blockPullOrder>
|
||||
<copyRangeMethod>standard</copyRangeMethod>
|
||||
@@ -607,7 +607,7 @@ folder is located on a FAT partition, and \fB0\fP otherwise.
|
||||
.TP
|
||||
.B maxConcurrentWrites
|
||||
Maximum number of concurrent write operations while syncing. Increasing this might increase or
|
||||
decrease disk performance, depending on the underlying storage. Default is \fB2\fP\&.
|
||||
decrease disk performance, depending on the underlying storage. Default is \fB16\fP\&.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -1555,7 +1555,7 @@ are set, \fI\%\-\-auditfile\fP takes priority.
|
||||
<markerName>.stfolder</markerName>
|
||||
<copyOwnershipFromParent>false</copyOwnershipFromParent>
|
||||
<modTimeWindowS>0</modTimeWindowS>
|
||||
<maxConcurrentWrites>2</maxConcurrentWrites>
|
||||
<maxConcurrentWrites>16</maxConcurrentWrites>
|
||||
<disableFsync>false</disableFsync>
|
||||
<blockPullOrder>standard</blockPullOrder>
|
||||
<copyRangeMethod>standard</copyRangeMethod>
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-DEVICE-IDS" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-device-ids \- Understanding Device IDs
|
||||
.sp
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-EVENT-API" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-event-api \- Event API
|
||||
.SH DESCRIPTION
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-FAQ" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-faq \- Frequently Asked Questions
|
||||
.INDENT 0.0
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-GLOBALDISCO" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-globaldisco \- Global Discovery Protocol v3
|
||||
.SH ANNOUNCEMENTS
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-LOCALDISCO" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-localdisco \- Local Discovery Protocol v4
|
||||
.SH MODE OF OPERATION
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-NETWORKING" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-networking \- Firewall Setup
|
||||
.SH ROUTER SETUP
|
||||
|
||||
@@ -28,7 +28,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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-RELAY" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-relay \- Relay Protocol v1
|
||||
.SH WHAT IS A RELAY?
|
||||
@@ -237,9 +237,10 @@ ResponseNotFound \- Session key is invalid
|
||||
ResponseAlreadyConnected \- Session is full (both sides already connected)
|
||||
.IP 3. 3
|
||||
ResponseSuccess \- You have successfully joined the session
|
||||
.IP 4. 3
|
||||
RelayFull \- Relay limits are too strict for you to be able to join the session.
|
||||
.UNINDENT
|
||||
.sp
|
||||
4. RelayFull \- Relay limits are too strict for you to be able to join the session.
|
||||
The relay immediately terminates the connection after sending this.
|
||||
.sp
|
||||
After the successful response, all the bytes written and received will be
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-REST-API" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-rest-api \- REST API
|
||||
.sp
|
||||
@@ -156,7 +156,7 @@ Returns the current configuration.
|
||||
\(dqmarkerName\(dq: \(dq.stfolder\(dq,
|
||||
\(dqcopyOwnershipFromParent\(dq: false,
|
||||
\(dqmodTimeWindowS\(dq: 0,
|
||||
\(dqmaxConcurrentWrites\(dq: 2,
|
||||
\(dqmaxConcurrentWrites\(dq: 16,
|
||||
\(dqdisableFsync\(dq: false,
|
||||
\(dqblockPullOrder\(dq: \(dqstandard\(dq,
|
||||
\(dqcopyRangeMethod\(dq: \(dqstandard\(dq,
|
||||
@@ -328,7 +328,7 @@ Returns the current configuration.
|
||||
\(dqmarkerName\(dq: \(dq.stfolder\(dq,
|
||||
\(dqcopyOwnershipFromParent\(dq: false,
|
||||
\(dqmodTimeWindowS\(dq: 0,
|
||||
\(dqmaxConcurrentWrites\(dq: 2,
|
||||
\(dqmaxConcurrentWrites\(dq: 16,
|
||||
\(dqdisableFsync\(dq: false,
|
||||
\(dqblockPullOrder\(dq: \(dqstandard\(dq,
|
||||
\(dqcopyRangeMethod\(dq: \(dqstandard\(dq,
|
||||
@@ -398,14 +398,14 @@ config, modify the needed parts and post it again.
|
||||
\fBNOTE:\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
Return format changed in versions 0.13.0, 1.19.0 and 1.23.0.
|
||||
Return format changed in versions 0.13.0, 0.14.14, 1.2.0, 1.19.0, 1.23.0 and 1.25.0.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
Returns the list of configured devices and some metadata associated
|
||||
with them. The list also contains the local device itself as not connected.
|
||||
with them.
|
||||
.sp
|
||||
The connection types are \fBTCP (Client)\fP, \fBTCP (Server)\fP, \fBRelay (Client)\fP and \fBRelay (Server)\fP\&.
|
||||
The connection types are \fBtcp\-client\fP, \fBtcp\-server\fP, \fBrelay\-client\fP, \fBrelay\-server\fP, \fBquic\-client\fP and \fBquic\-server\fP\&.
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
@@ -446,7 +446,7 @@ The connection types are \fBTCP (Client)\fP, \fBTCP (Server)\fP, \fBRelay (Clien
|
||||
\(dqoutBytesTotal\(dq: 550,
|
||||
\(dqpaused\(dq: false,
|
||||
\(dqstartedAt\(dq: \(dq2015\-11\-07T00:09:47Z\(dq,
|
||||
\(dqtype\(dq: \(dqTCP (Client)\(dq
|
||||
\(dqtype\(dq: \(dqtcp\-client\(dq
|
||||
}
|
||||
},
|
||||
\(dqtotal\(dq: {
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-SECURITY" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-security \- Security Principles
|
||||
.sp
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-STIGNORE" "5" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-stignore \- Prevent files from being synchronized to other nodes
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING-VERSIONING" "7" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing-versioning \- Keep automatic backups of deleted files by other nodes
|
||||
.sp
|
||||
|
||||
203
man/syncthing.1
203
man/syncthing.1
@@ -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" "Aug 29, 2025" "v2.0.0" "Syncthing"
|
||||
.TH "SYNCTHING" "1" "Sep 14, 2025" "v2.0.0" "Syncthing"
|
||||
.SH NAME
|
||||
syncthing \- Syncthing
|
||||
.SH SYNOPSIS
|
||||
@@ -43,10 +43,12 @@ syncthing [serve]
|
||||
[\-\-gui\-address=<address>] [\-\-gui\-apikey=<key>]
|
||||
[\-\-log\-level=<level>] [\-\-log\-file=<filename>]
|
||||
[\-\-log\-max\-old\-files=<num>] [\-\-log\-max\-size=<num>]
|
||||
[\-\-log\-format\-timestamp=<format>] [\-\-no\-log\-format\-level\-string]
|
||||
[\-\-log\-format\-level\-syslog]
|
||||
[\-\-no\-browser] [\-\-no\-console]
|
||||
[\-\-no\-port\-probing] [\-\-no\-restart] [\-\-no\-upgrade]
|
||||
[\-\-paused] [\-\-unpaused]
|
||||
[\-\-verbose] [\-\-version] [\-\-help] [\-\-debug\-*]
|
||||
[\-\-version] [\-\-help] [\-\-debug\-*]
|
||||
|
||||
syncthing cli
|
||||
[\-\-home=<dir> | \-\-config=<dir> \-\-data=<dir>]
|
||||
@@ -112,7 +114,7 @@ few log messages.
|
||||
.SH COMMON OPTIONS
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-home=<dir>, \-H <dir>
|
||||
.B \-\-home=<dir>, \-H <dir> ($STHOMEDIR)
|
||||
Set common configuration and data directory. The default configuration
|
||||
directory is \fB$XDG_STATE_HOME/syncthing\fP or
|
||||
\fB$HOME/.local/state/syncthing\fP (Unix\-like),
|
||||
@@ -121,13 +123,13 @@ directory is \fB$XDG_STATE_HOME/syncthing\fP or
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-config=<dir>, \-C <dir>
|
||||
.B \-\-config=<dir>, \-C <dir> ($STCONFDIR)
|
||||
Set configuration directory. Alternative to \fB\-\-home\fP and must be used
|
||||
together with \fB\-\-data\fP\&.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-data=<dir>, \-D <dir>
|
||||
.B \-\-data=<dir>, \-D <dir> ($STDATADIR)
|
||||
Set data (e.g. database) directory. Alternative to \fB\-\-home\fP and must be used
|
||||
together with \fB\-\-config\fP\&.
|
||||
.UNINDENT
|
||||
@@ -140,36 +142,38 @@ given subcommand.
|
||||
.SH SERVE OPTIONS
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-allow\-newer\-config
|
||||
.B \-\-allow\-newer\-config ($STALLOWNEWERCONFIG)
|
||||
Try loading a config file written by a newer program version, instead of
|
||||
failing immediately.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-audit
|
||||
.B \-\-audit ($STAUDIT)
|
||||
Write events to timestamped file \fBaudit\-YYYYMMDD\-HHMMSS.log\fP\&.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-auditfile=<file|\-|\-\->
|
||||
.B \-\-auditfile=<file|\-|\-\-> ($STAUDITFILE)
|
||||
Use specified file or stream (\fB\(dq\-\(dq\fP for stdout, \fB\(dq\-\-\(dq\fP for stderr) for
|
||||
audit events, rather than the timestamped default file name.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-db\-maintenance\-interval=<interval>
|
||||
.B \-\-db\-maintenance\-interval=<interval> ($STDBMAINTENANCEINTERVAL)
|
||||
Database maintenance interval – internal database maintenance routines
|
||||
run this often.
|
||||
run this often. The format is that of a Go duration string (see
|
||||
\X'tty: link https://pkg.go.dev/time#ParseDuration'\fI\%https://pkg.go.dev/time#ParseDuration\fP\X'tty: link').
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-db\-delete\-retention\-interval=<interval>
|
||||
.B \-\-db\-delete\-retention\-interval=<interval> ($STDBDELETERETENTIONINTERVAL)
|
||||
Database deleted item retention interval – deleted items are forgotten
|
||||
from the database after this interval.
|
||||
from the database after this interval. The format is that of a Go duration
|
||||
string (see \X'tty: link https://pkg.go.dev/time#ParseDuration'\fI\%https://pkg.go.dev/time#ParseDuration\fP\X'tty: link').
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-gui\-address=<address>
|
||||
.B \-\-gui\-address=<address> ($STGUIADDRESS)
|
||||
Override GUI listen address. Set this to an address (\fB0.0.0.0:8384\fP)
|
||||
or a URL (\fBhttp://0.0.0.0:8384\fP). Supported schemes are \fBhttp\fP for
|
||||
plain HTTP, \fBhttps\fP for HTTP over TLS, \fBunix\fP for plain Unix sockets
|
||||
@@ -179,79 +183,95 @@ as part of the URL structure, one to specify an absolute path).
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-gui\-apikey=<string>
|
||||
.B \-\-gui\-apikey=<string> ($STGUIAPIKEY)
|
||||
Override the API key needed to access the GUI / REST API.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-log\-level=<level>
|
||||
Set the log level for all packages. Valid levels are DEBUG, INFO, WARN,
|
||||
and ERROR.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-log\-file=<filename>
|
||||
.B \-\-log\-file=<filename> ($STLOGFILE)
|
||||
Set destination filename for logging (use \fB\(dq\-\(dq\fP for stdout, which is the
|
||||
default option).
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-log\-max\-old\-files=<num>
|
||||
.B \-\-log\-level=<level> ($STLOGLEVEL)
|
||||
Set the log level for all packages. Valid levels are DEBUG, INFO, WARN,
|
||||
and ERROR.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-log\-max\-old\-files=<num> ($STLOGMAXOLDFILES)
|
||||
Number of old files to keep (zero to keep only current). Applies only when
|
||||
log rotation is enabled through \fB\-\-log\-max\-size\fP\&.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-log\-max\-size=<num>
|
||||
Maximum size of any log file (zero to disable log rotation).
|
||||
.B \-\-log\-max\-size=<num> ($STLOGMAXSIZE)
|
||||
Maximum size in bytes of any log file (zero to disable log rotation).
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-browser
|
||||
.B \-\-log\-format\-timestamp=<format> ($STLOGFORMATTIMESTAMP)
|
||||
Format for timestamp, set to empty to disable timestamps. The format is that
|
||||
of the Go time formatter (see \X'tty: link https://pkg.go.dev/time#Layout'\fI\%https://pkg.go.dev/time#Layout\fP\X'tty: link').
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-[no\-]log\-format\-level\-string ($STLOGFORMATLEVELSTRING)
|
||||
Whether to include level string (e.g. “INF”) in log line.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-[no\-]log\-format\-level\-syslog ($STLOGFORMATLEVELSYSLOG)
|
||||
Whether to include level as syslog prefix (e.g. “<6>”) in log line.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-browser ($STNOBROWSER)
|
||||
Do not start a browser.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-console
|
||||
.B \-\-no\-console ($STNOCONSOLE)
|
||||
Hide the console window. (On Windows only)
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-port\-probing
|
||||
.B \-\-no\-port\-probing ($STNOPORTPROBING)
|
||||
Don’t try to find unused random ports for the GUI and listen address when
|
||||
generating an initial configuration / starting for the first time.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-restart
|
||||
.B \-\-no\-restart ($STNORESTART)
|
||||
Do not restart Syncthing when it exits. The monitor process will still run
|
||||
to handle crashes and writing to logfiles (if configured to).
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-upgrade
|
||||
Disable automatic upgrades. Equivalent to the \fBSTNOUPGRADE\fP environment
|
||||
variable, see below.
|
||||
.B \-\-no\-upgrade ($STNOUPGRADE)
|
||||
Disable automatic upgrades.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-paused
|
||||
.B \-\-paused ($STPAUSED)
|
||||
Start with all devices and folders paused.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-unpaused
|
||||
.B \-\-unpaused ($STUNPAUSED)
|
||||
Start with all devices and folders unpaused.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-upgrade
|
||||
Perform upgrade.
|
||||
.B \-\-version
|
||||
Show the current version information, then exit.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-verbose
|
||||
Print verbose log output.
|
||||
.B \-\-debug\-*
|
||||
Several debug options exist. See \fBsyncthing serve \-\-help\fP for the flags
|
||||
that apply to your version.
|
||||
.UNINDENT
|
||||
.SH DECRYPT OPTIONS
|
||||
.INDENT 0.0
|
||||
@@ -266,7 +286,7 @@ Don’t write decrypted files to disk (but verify plaintext hashes).
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-password=<pw>
|
||||
.B \-\-password=<pw> ($FOLDER_PASSWORD)
|
||||
Folder password for decryption / verification. Can be passed through the
|
||||
\fBFOLDER_PASSWORD\fP environment variable instead to avoid recording in a
|
||||
shell’s history buffer or sniffing from the running processes list.
|
||||
@@ -337,9 +357,9 @@ signal handler. Exit codes over 128+N on Unix usually represent the signal which
|
||||
caused the process to exit. For example, \fB128 + 9 (SIGKILL) = 137\fP\&.
|
||||
.SH SUBCOMMANDS
|
||||
.sp
|
||||
The command line syntax actually supports different modes of operation through
|
||||
several subcommands, specified as the first argument. If omitted, the default
|
||||
\fBserve\fP is assumed.
|
||||
The command line syntax supports different modes of operation through
|
||||
several subcommands, specified as the first argument. If omitted, the
|
||||
default \fBserve\fP is assumed.
|
||||
.sp
|
||||
The initial setup of a device ID and default configuration can be called
|
||||
explicitly with the \fBgenerate\fP subcommand. It can also update the configured
|
||||
@@ -423,38 +443,79 @@ facilities to trace: \fBapi,beacon\fP\&. Optionally, a log level can be
|
||||
given per facility to specify something other than DEBUG:
|
||||
\fBapi:WARN,beacon:ERR\fP, potentially overriding a global \fB\-\-log\-level\fP
|
||||
adjustment.
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
The valid facility strings are listed below; additionally, \fBsyncthing
|
||||
serve \-\-help\fP always outputs the most up\-to\-date list.
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
api \- REST API
|
||||
beacon \- Multicast and broadcast discovery
|
||||
config \- Configuration loading and saving
|
||||
connections \- Connection handling
|
||||
db/sqlite \- SQLite database
|
||||
dialer \- Dialing connections
|
||||
discover \- Remote device discovery
|
||||
events \- Event generation and logging
|
||||
fs \- Filesystem access
|
||||
main \- Main package
|
||||
model \- The root hub
|
||||
nat \- NAT discovery and port mapping
|
||||
pmp \- NAT\-PMP discovery and port mapping
|
||||
protocol \- The BEP protocol
|
||||
relay/client \- Relay client
|
||||
scanner \- File change detection and hashing
|
||||
stun \- STUN functionality
|
||||
syncthing \- Main run facility
|
||||
upgrade \- Binary upgrades
|
||||
upnp \- UPnP discovery and port mapping
|
||||
ur \- Usage reporting
|
||||
versioner \- File versioning
|
||||
watchaggregator \- Filesystem event watcher
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B api
|
||||
REST API
|
||||
.TP
|
||||
.B beacon
|
||||
Multicast and broadcast discovery
|
||||
.TP
|
||||
.B config
|
||||
Configuration loading and saving
|
||||
.TP
|
||||
.B connections
|
||||
Connection handling
|
||||
.TP
|
||||
.B db/sqlite
|
||||
SQLite database
|
||||
.TP
|
||||
.B dialer
|
||||
Dialing connections
|
||||
.TP
|
||||
.B discover
|
||||
Remote device discovery
|
||||
.TP
|
||||
.B events
|
||||
Event generation and logging
|
||||
.TP
|
||||
.B fs
|
||||
Filesystem access
|
||||
.TP
|
||||
.B main
|
||||
Main package
|
||||
.TP
|
||||
.B model
|
||||
The root hub
|
||||
.TP
|
||||
.B nat
|
||||
NAT discovery and port mapping
|
||||
.TP
|
||||
.B pmp
|
||||
NAT\-PMP discovery and port mapping
|
||||
.TP
|
||||
.B protocol
|
||||
The BEP protocol
|
||||
.TP
|
||||
.B relay/client
|
||||
Relay client
|
||||
.TP
|
||||
.B scanner
|
||||
File change detection and hashing
|
||||
.TP
|
||||
.B stun
|
||||
STUN functionality
|
||||
.TP
|
||||
.B syncthing
|
||||
Main run facility
|
||||
.TP
|
||||
.B upgrade
|
||||
Binary upgrades
|
||||
.TP
|
||||
.B upnp
|
||||
UPnP discovery and port mapping
|
||||
.TP
|
||||
.B ur
|
||||
Usage reporting
|
||||
.TP
|
||||
.B versioner
|
||||
File versioning
|
||||
.TP
|
||||
.B watchaggregator
|
||||
Filesystem event watcher
|
||||
.UNINDENT
|
||||
.TP
|
||||
.B STLOCKTHRESHOLD
|
||||
|
||||
@@ -113,6 +113,7 @@ message FileInfo {
|
||||
repeated BlockInfo blocks = 16;
|
||||
bytes symlink_target = 17;
|
||||
bytes blocks_hash = 18;
|
||||
bytes previous_blocks_hash = 20;
|
||||
bytes encrypted = 19;
|
||||
FileInfoType type = 2;
|
||||
uint32 permissions = 4;
|
||||
@@ -127,7 +128,7 @@ message FileInfo {
|
||||
uint32 local_flags = 1000;
|
||||
|
||||
// The version_hash is an implementation detail and not part of the wire
|
||||
// format.
|
||||
// format. It is used in the old database format.
|
||||
bytes version_hash = 1001;
|
||||
|
||||
// The time when the inode was last changed (i.e., permissions, xattrs
|
||||
|
||||
@@ -17,6 +17,7 @@ message FileInfoTruncated {
|
||||
reserved 16; // blocks
|
||||
bytes symlink_target = 17;
|
||||
bytes blocks_hash = 18;
|
||||
bytes previous_blocks_hash = 20;
|
||||
bytes encrypted = 19;
|
||||
bep.FileInfoType type = 2;
|
||||
uint32 permissions = 4;
|
||||
|
||||
Reference in New Issue
Block a user