aboutsummaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
authorJakob Borg <jakob@kastelo.net>2022-09-14 09:50:55 +0200
committerGitHub <noreply@github.com>2022-09-14 09:50:55 +0200
commit6cac308bcdf197f4bbe8bd36725d9ac92a622559 (patch)
tree5996cbd022cc8f54bcc3203fdfc45847730d3fb2 /proto
parent8065cf7e971019bcf1225756e0364760984ffd13 (diff)
downloadsyncthing-6cac308bcdf197f4bbe8bd36725d9ac92a622559.tar.gz
syncthing-6cac308bcdf197f4bbe8bd36725d9ac92a622559.zip
all: Support syncing extended attributes (fixes #2698) (#8513)
This adds support for syncing extended attributes on supported filesystem on Linux, macOS, FreeBSD and NetBSD. Windows is currently excluded because the APIs seem onerous and annoying and frankly the uses cases seem few and far between. On Unixes this also covers ACLs as those are stored as extended attributes. Similar to ownership syncing this will optional & opt-in, which two settings controlling the main behavior: one to "sync" xattrs (read & write) and another one to "scan" xattrs (only read them so other devices can "sync" them, but not apply any locally). Co-authored-by: Tomasz WilczyƄski <twilczynski@naver.com>
Diffstat (limited to 'proto')
-rw-r--r--proto/lib/config/folderconfiguration.proto23
-rw-r--r--proto/lib/db/structs.proto5
-rw-r--r--proto/lib/protocol/bep.proto18
3 files changed, 43 insertions, 3 deletions
diff --git a/proto/lib/config/folderconfiguration.proto b/proto/lib/config/folderconfiguration.proto
index 44e10f73f..63326a31e 100644
--- a/proto/lib/config/folderconfiguration.proto
+++ b/proto/lib/config/folderconfiguration.proto
@@ -55,10 +55,31 @@ message FolderConfiguration {
bool case_sensitive_fs = 33 [(ext.goname) = "CaseSensitiveFS", (ext.xml) = "caseSensitiveFS", (ext.json) = "caseSensitiveFS"];
bool follow_junctions = 34 [(ext.goname) = "JunctionsAsDirs", (ext.xml) = "junctionsAsDirs", (ext.json) = "junctionsAsDirs"];
bool sync_ownership = 35;
- bool scan_ownership = 36;
+ bool send_ownership = 36;
+ bool sync_xattrs = 37;
+ bool send_xattrs = 38;
+ XattrFilter xattr_filter = 39;
// Legacy deprecated
bool read_only = 9000 [deprecated=true, (ext.xml) = "ro,attr,omitempty"];
double min_disk_free_pct = 9001 [deprecated=true];
int32 pullers = 9002 [deprecated=true];
+ bool scan_ownership = 9003 [deprecated=true];
+}
+
+// Extended attribute filter. This is a list of patterns to match (glob
+// style), each with an action (permit or deny). First match is used. If the
+// filter is empty, all strings are permitted. If the filter is non-empty,
+// the default action becomes deny. To counter this, you can use the "*"
+// pattern to match all strings at the end of the filter. There are also
+// limits on the size of accepted attributes.
+message XattrFilter {
+ repeated XattrFilterEntry entries = 1 [(ext.xml) = "entry"];
+ int32 max_single_entry_size = 2 [(ext.xml) = "maxSingleEntrySize", (ext.default) = "1024"];
+ int32 max_total_size = 3 [(ext.xml) = "maxTotalSize", (ext.default) = "4096"];
+}
+
+message XattrFilterEntry {
+ string match = 1 [(ext.xml) = "match,attr"];
+ bool permit = 2 [(ext.xml) = "permit,attr"];
}
diff --git a/proto/lib/db/structs.proto b/proto/lib/db/structs.proto
index 9bb8300aa..7ea733c4a 100644
--- a/proto/lib/db/structs.proto
+++ b/proto/lib/db/structs.proto
@@ -39,8 +39,9 @@ message FileInfoTruncated {
protocol.PlatformData platform = 14;
// see bep.proto
- uint32 local_flags = 1000;
- bytes version_hash = 1001;
+ uint32 local_flags = 1000;
+ bytes version_hash = 1001;
+ int64 inode_change_ns = 1002;
bool deleted = 6;
bool invalid = 7 [(ext.goname) = "RawInvalid"];
diff --git a/proto/lib/protocol/bep.proto b/proto/lib/protocol/bep.proto
index 167cd22cf..4204387b7 100644
--- a/proto/lib/protocol/bep.proto
+++ b/proto/lib/protocol/bep.proto
@@ -114,10 +114,15 @@ message FileInfo {
// 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.
uint32 local_flags = 1000;
+
// The version_hash is an implementation detail and not part of the wire
// format.
bytes version_hash = 1001;
+ // The time when the inode was last changed (i.e., permissions, xattrs
+ // etc changed). This is host-local, not sent over the wire.
+ int64 inode_change_ns = 1002;
+
bool deleted = 6;
bool invalid = 7 [(ext.goname) = "RawInvalid"];
bool no_permissions = 8;
@@ -151,6 +156,10 @@ message Counter {
message PlatformData {
UnixData unix = 1 [(gogoproto.nullable) = true];
WindowsData windows = 2 [(gogoproto.nullable) = true];
+ XattrData linux = 3 [(gogoproto.nullable) = true];
+ XattrData darwin = 4 [(gogoproto.nullable) = true];
+ XattrData freebsd = 5 [(gogoproto.nullable) = true, (ext.goname) = "FreeBSD"];
+ XattrData netbsd = 6 [(gogoproto.nullable) = true, (ext.goname) = "NetBSD"];
}
message UnixData {
@@ -171,6 +180,15 @@ message WindowsData {
bool owner_is_group = 2;
}
+message XattrData {
+ repeated Xattr xattrs = 1;
+}
+
+message Xattr {
+ string name = 1;
+ bytes value = 2;
+}
+
// Request
message Request {