Compare commits

...

195 Commits

Author SHA1 Message Date
Audrius Butkevicius
2470875d14 Merge pull request #1681 from calmh/major-upgrade
Allow major upgrades [v0.10]
2015-04-22 14:11:18 +01:00
Jakob Borg
930e90289f Backport the v0.11 upgrade system 2015-04-22 21:27:13 +09:00
Jakob Borg
bf959a77e2 Allow major upgrade (fixes #1680) 2015-04-22 21:22:16 +09:00
Jakob Borg
3cc4cb0a0b Translation update 2015-03-29 09:46:44 +02:00
Jakob Borg
e6cba61740 Don't allow arbitrarily short reconnection intervals (fixes #1524) 2015-03-29 09:44:20 +02:00
Jakob Borg
cd7ce73f59 Add negative cache time to global discovery
This reduces the amount of external queries by not repeating a query for
a given address if we have failed within the last three minutes.
2015-03-26 08:43:55 +01:00
KAMADA Ken'ichi
fab4e33c58 Preserve the permission of a newly created directory
We need an explicit chmod() when creating a new directory.
Otherwise a new directory may be created with a different permission
from the one received from an originating device, because the umask
is applied to the mode given to mkdir().
The incorrect permission is later sent back to the originating device
and the original permission will be lost.
2015-03-26 08:43:16 +01:00
Audrius Butkevicius
b79b13a75b Configure location provider 2015-03-26 08:43:06 +01:00
Audrius Butkevicius
c294d5f087 Fix crash on walker error (fixes #1507) 2015-03-22 14:09:14 +00:00
Jakob Borg
10ead2e61f Send correct MIME type for SVG images (fixes #1506) 2015-03-22 12:56:50 +01:00
Jakob Borg
960b40fa89 Translation update 2015-03-22 10:34:45 +01:00
Stefan Tatschner
afad329e99 systemd: Set -logflags to 0, provide -no-browser flag
Syncthing should not try to start a browser when invoked by systemd.
Furthermore we do not need any timestamps in the journal as systemd
already handles this for us.
2015-03-22 10:26:53 +01:00
Jakob Borg
4025284fba Update integration test configs to v10 2015-03-22 10:26:53 +01:00
Jakob Borg
a595e814dd Set defaults correctly for autoNormalize
The default:"foo" struct tags aren't actually used for folder configs.
2015-03-22 10:26:51 +01:00
Alexander Graf
963d8121d9 use Lstat instead of Stat to prevent errors with symlinks 2015-03-22 08:48:37 +01:00
Audrius Butkevicius
03019988b1 Skip unspecified IPs 2015-03-22 08:48:37 +01:00
Audrius Butkevicius
97115afa32 Print LANs on startup 2015-03-22 08:48:37 +01:00
Jakob Borg
c9f5bae177 Decide once and for all to return filepath.SkipDir or nil 2015-03-22 08:47:36 +01:00
Jakob Borg
2bd11ca4e3 Automatically fix file name normalization errors (fixes #430) 2015-03-22 08:47:34 +01:00
Jakob Borg
a5de1acb46 Use SVG format logos 2015-03-22 08:46:54 +01:00
Jakob Borg
5581751e9d Rename files to match type names 2015-03-22 08:46:43 +01:00
Jakob Borg
055ae92273 Refactor state tracking (...)
Move state tracking into the puller/scanner objects. This is a first
step towards resolving #1391.

Rename Puller and Scanner to roFolder and rwFolder as they have more
duties than just pulling and scanning, and don't need to be exported.
2015-03-22 08:46:43 +01:00
Audrius Butkevicius
dea7c77055 Rebuild assets 2015-03-22 08:46:41 +01:00
Audrius Butkevicius
765dda6ad7 Fix build 2015-03-22 08:46:26 +01:00
Jakob Borg
28702a1c9d Add /rest/filestatus 2015-03-22 08:46:26 +01:00
Jakob Borg
40d1226612 MPLv2 2015-03-22 08:46:25 +01:00
Johan Vromans
effe8ce8a9 Suppress 'Last File Received' if a node is folder master (fixes #1472) 2015-03-22 08:46:24 +01:00
Jakob Borg
4c3ba24826 Add sciurius 2015-03-22 08:45:42 +01:00
Audrius Butkevicius
b2425b2a25 Silence warnings (ref #1388) 2015-03-16 10:47:59 +00:00
Jakob Borg
51c932164f bep/1.0 negotiation can't be a hard error. 2015-03-15 17:49:47 +01:00
Jakob Borg
19e82e93b1 Translation update 2015-03-15 16:42:52 +01:00
Jakob Borg
3f785eaecf Merge pull request #1466 from kamadak/win-w-bits
Do not send group/others-writable bits from Windows.
2015-03-15 16:35:13 +01:00
Jakob Borg
e59c0f38d9 Also build darwin/386 2015-03-15 16:23:45 +01:00
Jakob Borg
64004c6bc0 Alternate email for pascalj 2015-03-15 16:02:34 +01:00
Jakob Borg
422332de7e Add kamadak 2015-03-15 15:19:17 +01:00
Jakob Borg
5a15ba7451 Add pascalj 2015-03-15 15:17:35 +01:00
Jakob Borg
d3686bb1e2 Add kilburn 2015-03-15 15:17:26 +01:00
KAMADA Ken'ichi
3a6eeef580 Do not send group/others-writable bits from Windows.
There is no user/group/others in Windows' read-only attribute,
and all "w" bits are set in os.FileInfo if the file is not read-only.
Do not send these group/others-writable bits to other devices
in order to avoid unexpected world-writable files on other platforms.
2015-03-15 22:14:44 +09:00
Audrius Butkevicius
1dc5c6b8a8 Merge pull request #1457 from calmh/relverv3
Guessing version from directory name is not viable in Go (ref #1449)
2015-03-13 10:42:27 +00:00
Jakob Borg
3532a560d8 Guessing version from directory name is not viable in Go (ref #1449) 2015-03-13 10:10:13 +01:00
Audrius Butkevicius
d2d894d808 Merge pull request #1451 from calmh/relverv2
Get version from RELEASE file if it exists, or guess from directory (fixes #1449)
2015-03-12 10:38:39 +00:00
Jakob Borg
2aa38bfc4b Get version from RELEASE file if it exists, or guess from directory (fixes #1449) 2015-03-12 11:18:23 +01:00
Jakob Borg
9c3cee9ae4 Translation update 2015-03-11 21:15:55 +01:00
Jakob Borg
fc521b5f9d Protocol dep update 2015-03-11 21:13:17 +01:00
Audrius Butkevicius
5253368acc Merge pull request #1448 from calmh/xp
Fall back to %AppData% is %LocalAppData% is blank (fixes #1446)
2015-03-11 20:06:13 +00:00
Jakob Borg
51cfc3d4be Fall back to %AppData% is %LocalAppData% is blank (fixes #1446) 2015-03-11 21:04:10 +01:00
Audrius Butkevicius
80bffd93e7 Merge pull request #1447 from calmh/silencio
Don't yell about discovery listening and resolving (ref #1418)
2015-03-11 20:03:37 +00:00
Jakob Borg
df4f22e899 Don't yell about discovery listening and resolving (ref #1418) 2015-03-11 20:57:20 +01:00
Audrius Butkevicius
8cc70843a5 Merge pull request #1445 from calmh/compression
Compress only metadata by default (fixes #1374)
2015-03-11 19:35:15 +00:00
Jakob Borg
70c841f23a Compress only metadata by default (fixes #1374) 2015-03-11 19:10:57 +01:00
Jakob Borg
7b22e09805 Merge pull request #1438 from moshen/runit-reparenting
Fix syncthing process reparenting with runit
2015-03-10 08:21:41 +01:00
Jakob Borg
c5838c143c Merge pull request #1425 from AudriusButkevicius/laan
Allow not to limit bandwidth in LAN (fixes #1336)
2015-03-10 08:19:29 +01:00
Colin Kennedy
eaf71db7c9 Fix syncthing process reparenting with runit
When you: `sudo sv down /etc/service/syncthing/` the `TERM` signal
isn't propogated or trapped, so syncthing is orphaned and adopted by
init (PID 1).

- Changed call to `chpst` to `exec`
- Moved logging to `log/run` per `runsv` standard
2015-03-10 01:01:52 -05:00
Jakob Borg
b322b527b3 Add SVG versions of logo 2015-03-10 00:02:46 +01:00
Jakob Borg
cc4b231875 Merge pull request #1429 from moshen/runit-fix
Use chpst instead of djb name setuidgid
2015-03-09 23:50:08 +01:00
Jakob Borg
05642a3e17 Merge remote-tracking branch 'syncthing/pr/1436'
* syncthing/pr/1436:
  Remove red if we managed to report to atleast one discovery server (fixes #1427)

Conflicts:
	internal/auto/gui.files.go
2015-03-09 23:47:41 +01:00
Jakob Borg
7dcc6bb579 Add moshen 2015-03-09 23:45:03 +01:00
Audrius Butkevicius
f15c416e59 Remove red if we managed to report to atleast one discovery server (fixes #1427) 2015-03-09 21:55:14 +00:00
Audrius Butkevicius
6fa97eeec7 Allow not to limit bandwidth in LAN (fixes #1336) 2015-03-09 20:54:33 +00:00
Jakob Borg
03bbf273b3 Update protocol dep 2015-03-09 21:21:50 +01:00
Audrius Butkevicius
1e376cd3a6 Update assets 2015-03-09 12:13:43 +00:00
Audrius Butkevicius
49cf939c04 Add missing translation strings (fixes #1430) 2015-03-09 12:02:30 +00:00
Colin Kennedy
338394f8c3 Use chpst instead of djb name setuidgid
Some distros (Ubuntu, Debian?) don't link `chpst` to `setuidgid`, as it
could conflict with djb daemontools installation.  If daemontools isn't
going to be referenced in the README, then the example runit config
should reference the runit packaged utility.
2015-03-08 18:50:54 -05:00
Audrius Butkevicius
575b62d77b Merge pull request #1424 from AudriusButkevicius/scanner
Make sure we start scanning at an indexed location (fixes #1399)
2015-03-08 19:46:21 +00:00
Audrius Butkevicius
57fc0eb5b1 Make sure we start scanning at an indexed location (fixes #1399) 2015-03-08 19:45:47 +00:00
Jakob Borg
3a19fe3663 Merge pull request #1423 from AudriusButkevicius/warn
Silence discovery warnings when v6 not available
2015-03-08 19:50:35 +01:00
Audrius Butkevicius
0c049179b4 Silence discovery warnings when v6 not available (fixes #1418) 2015-03-08 16:49:12 +00:00
Jakob Borg
e22c873ec4 Repair integration tests 2015-03-08 08:41:43 +01:00
Jakob Borg
d644ebab09 Translation update 2015-03-08 07:52:52 +01:00
Jakob Borg
2fdc578a88 Update goleveldb (fixes #1414) 2015-03-08 07:49:02 +01:00
Jakob Borg
aeb3a3f7b5 Handle crap at the end of commit subjects 2015-03-07 22:50:54 +01:00
Audrius Butkevicius
044b7ce070 Merge pull request #1415 from calmh/announce-v6
Add global announce server on IPv6
2015-03-07 21:39:53 +00:00
Jakob Borg
815e538f10 Merge pull request #1401 from Zillode/fix-chmod-android
Fix chmod android
2015-03-07 21:42:44 +01:00
Lode Hoste
758233f001 Do not error when chmod failes when permissions are ignored (fixes #1404). 2015-03-07 21:38:16 +01:00
Jakob Borg
f4f4fda520 String slice uniquification must return a well defined order, or tests fail 2015-03-07 21:05:30 +01:00
Jakob Borg
1d77aeb69c Add global announce server on IPv6 2015-03-07 21:01:20 +01:00
Jakob Borg
29dbfc647d Add bencurthoys 2015-03-07 14:41:18 +01:00
Jakob Borg
55d9514e83 Merge pull request #1407 from bencurthoys/master
Windows Service Setup.exe
2015-03-07 14:38:43 +01:00
Jakob Borg
46bd7956a3 Merge branch 'pr-1410'
* pr-1410:
  Add test for osutil.InWritableDir
  Exit and error if the target is not a directory
2015-03-07 14:35:54 +01:00
Jakob Borg
e1ee394c26 Add test for osutil.InWritableDir 2015-03-07 14:35:29 +01:00
Lode Hoste
19884ade99 Exit and error if the target is not a directory 2015-03-06 22:02:29 +01:00
bencurthoys
f0a88061db Setup.exe for Windows
NSIS script to build setup file to install Syncthing and install as a service.
2015-03-06 15:30:50 +00:00
Audrius Butkevicius
6057138466 Merge pull request #1400 from calmh/negproto
Verify negotiated protocol bep/1.0
2015-03-05 15:16:59 +00:00
Jakob Borg
aaaa6556f3 Some commentary on the initial connection checks 2015-03-05 16:09:20 +01:00
Jakob Borg
4745431cda Verify negotiated protocol bep/1.0 2015-03-05 15:58:16 +01:00
Jakob Borg
0455a948a9 Merge pull request #1337 from AudriusButkevicius/fileslevels
Add /rest/tree API call
2015-03-05 15:24:51 +01:00
Audrius Butkevicius
bf3e249237 Add GlobalDirectoryTree benchmarks 2015-03-04 23:39:33 +00:00
Audrius Butkevicius
fb649e9525 Fix benchmarks, cleanup tests 2015-03-04 23:39:32 +00:00
Audrius Butkevicius
9d1e2d9f46 Add /rest/tree API call 2015-03-04 23:39:27 +00:00
Audrius Butkevicius
9876d93b60 Fix tests on Windows while running as a simple user 2015-03-04 22:39:33 +00:00
Jakob Borg
b3dd05580b Don't follow the prototype chain when looking for a folder name (fixes #1387) 2015-03-01 22:10:34 +01:00
Jakob Borg
32847f33fd Translation update 2015-03-01 21:51:56 +01:00
Jakob Borg
bff9723fe3 Merge branch 'fix-1373'
* fix-1373:
  fixup alterFiles
  Ensure progress when delete-by-rename fails (fixes #1373)
  Handle weird Lstat() returns for disappeared items (ref #1373)
  Alter files into directories and the other way around
2015-03-01 21:51:26 +01:00
Jakob Borg
d114648c16 fixup alterFiles 2015-03-01 21:38:04 +01:00
Jakob Borg
44d0da02d0 Ensure progress when delete-by-rename fails (fixes #1373) 2015-03-01 10:55:48 +01:00
Jakob Borg
c25107eff3 Handle weird Lstat() returns for disappeared items (ref #1373) 2015-03-01 10:55:43 +01:00
Jakob Borg
af5c36d2a8 Merge remote-tracking branch 'syncthing/pr/1373' into fix-1373
* syncthing/pr/1373:
  Alter files into directories and the other way around
2015-03-01 10:55:34 +01:00
Audrius Butkevicius
0828a67145 Merge pull request #1275 from calmh/kv-cache
Namespaced key value store and value cache
2015-02-26 13:51:43 +00:00
Jakob Borg
617fb84983 Also build Solaris, NetBSD by default 2015-02-26 12:21:20 +01:00
Jakob Borg
6f8ac2b61c Refactor: add and use db.NamespacedKV 2015-02-26 09:56:11 +01:00
Jakob Borg
6f2b4b96cf Refactor: use leveldb/util.BytesPrefix 2015-02-26 09:56:11 +01:00
Jakob Borg
3cc288a169 Build binary packages for Dragonfly 2015-02-26 08:58:58 +01:00
Jakob Borg
0bbbf3eb3b Compile on Dragonfly 2015-02-26 08:42:39 +01:00
Jakob Borg
4b1b56fee8 Reduce CPU usage (fixes #1376) 2015-02-25 23:30:24 +01:00
Jakob Borg
154fc59e93 Switch back to original kardianos/osext 2015-02-24 20:44:49 +01:00
Lode Hoste
218c4c128c Alter files into directories and the other way around 2015-02-23 12:12:31 +01:00
Audrius Butkevicius
53f1af0cab Merge pull request #1375 from calmh/fix-987
Attempt recovery of corrupted DB at startup (fixes #987)
2015-02-23 09:17:29 +00:00
Jakob Borg
f9577a38dc Attempt recovery of corrupted DB at startup (fixes #987) 2015-02-23 08:22:39 +01:00
Jakob Borg
fadc7d9ba5 Merge pull request #1366 from krozycki/master
All folder panels collapsed, fixes #1034
2015-02-20 10:18:50 +01:00
Jakob Borg
1e4b2133f6 Also handle ()| in glob patterns (fixes #1365) 2015-02-20 10:12:06 +01:00
Karol Różycki
bfefa6d016 All folder panels collapsed, fixes #1034 2015-02-19 15:48:43 +01:00
Jakob Borg
8b66472949 Fix sync benchmark for latest test changes 2015-02-19 13:15:51 +02:00
Jakob Borg
3b3aa94c4e Refactor out connection related functions to a separate file 2015-02-19 12:05:26 +02:00
Audrius Butkevicius
dc05275670 Merge pull request #1357 from calmh/truncate-v3
Simplify FileInfoTruncated
2015-02-19 10:04:53 +00:00
Jakob Borg
7921082ece Correctly handle ^ and $ in ignore patterns (fixes #1365) 2015-02-19 09:10:32 +02:00
Jakob Borg
efd6a29909 Translation update 2015-02-15 16:55:44 +01:00
Jakob Borg
88c44b303d Simplify FileInfoTruncated 2015-02-15 12:50:03 +01:00
Jakob Borg
e7dbb8ccdc Fix test for unknown flags 2015-02-15 09:51:39 +01:00
Jakob Borg
fe2a743c8d Protocol update 2015-02-15 09:41:32 +01:00
Audrius Butkevicius
1f5c124ac4 Merge pull request #1359 from krozycki/master
Typo fix. Fixes #1358
2015-02-14 15:17:45 +00:00
Karol Różycki
64a5bc038a Typo fix. Fixes #1358 2015-02-14 16:10:43 +01:00
Jakob Borg
5d9396334c Merge pull request #1311 from krozycki/master
Button to rescan all folders (fixes #1151)
2015-02-13 08:36:17 +01:00
Karol Różycki
ec160f1f0a Button to rescan all folders, fixes #1151 2015-02-12 21:03:35 +01:00
Jakob Borg
bbaeca96eb Merge pull request #1326 from rumpelsepp/systemd
Some systemd tweaks
2015-02-12 16:58:54 +01:00
Jakob Borg
3ab779895f Add tnn2 2015-02-12 12:14:56 +01:00
Jakob Borg
203c7360e7 Merge remote-tracking branch 'syncthing/pr/1332'
* syncthing/pr/1332:
  Implement memorySize() for NetBSD
2015-02-12 12:13:35 +01:00
Jakob Borg
a831f174ef Add marclaporte 2015-02-12 12:08:49 +01:00
Stefan Tatschner
153091f52f Some systemd tweaks
- Removed environment file to keep the service file minimal.
  "systemctl edit syncthing.service" does the job if somebody wants
  to customize the service.
- Changed "cmdline.target" to "default.target" as "cmdline.target"
  does not exist in systemd.special:
  http://www.freedesktop.org/software/systemd/man/systemd.special.html
- Added a missing "After=network.target".
- Added a documentation hint, thx @jaystrictor
2015-02-12 09:23:12 +01:00
Jakob Borg
35d3af5039 Use syncthing/build:latest for building 2015-02-11 10:17:15 +01:00
Jakob Borg
57e8cd6eab Regenerate assets 2015-02-11 09:35:08 +01:00
Jakob Borg
fc123a71af Merge pull request #1341 from AudriusButkevicius/configtest
Fix tests on Windows
2015-02-11 08:13:54 +01:00
Audrius Butkevicius
f14836cf02 Merge pull request #1346 from uok/match-icons
Match icons for ignore patterns
2015-02-10 21:42:53 +00:00
Ben Schulz
4178feb65f Match icons for ignore patterns 2015-02-10 21:38:56 +01:00
Audrius Butkevicius
2edaf22590 Merge pull request #1345 from calmh/smaller-batches
Reduce memory usage by writing smaller batches
2015-02-10 19:53:53 +00:00
Audrius Butkevicius
acd3dab957 Fix tests on Windows 2015-02-10 19:52:14 +00:00
Jakob Borg
6bbd74adcd Merge pull request #1321 from AudriusButkevicius/bitcheck
Refuse files with unknown bits set (fixes #1276)
2015-02-10 20:27:14 +01:00
Jakob Borg
9bb928bb38 Reduce memory usage by writing smaller batches 2015-02-10 20:24:25 +01:00
Jakob Borg
c87a6c5969 Use single filename for heap profiles 2015-02-10 19:50:27 +01:00
Jakob Borg
c482c13dcb Configurable heap profiling rate 2015-02-10 19:45:32 +01:00
Audrius Butkevicius
b87ed97402 Refuse files with unknown bits set (fixes #1276) 2015-02-09 23:32:33 +00:00
Jakob Borg
ee000dabfd Translation update 2015-02-09 23:03:31 +01:00
Jakob Borg
a73a011ee0 Merge pull request #1323 from AudriusButkevicius/finished
Add ItemFinished event (fixes #1258)
2015-02-09 15:24:10 +01:00
Jakob Borg
2a8e5e2c14 Merge pull request #1304 from AudriusButkevicius/pprof
Add STBLOCKPROFILE
2015-02-09 15:18:42 +01:00
Jakob Borg
5d9a41f712 Merge pull request #1319 from AudriusButkevicius/renames
Fix issues with renames
2015-02-09 15:14:47 +01:00
Jakob Borg
ebcf4b60f6 Merge pull request #1320 from AudriusButkevicius/cache
Remove fd cache (ref #1308)
2015-02-09 15:10:42 +01:00
Jakob Borg
f976b78917 Merge pull request #1322 from AudriusButkevicius/browser
Opening a browser happens in it's own routine (fixes #1273)
2015-02-09 15:06:56 +01:00
Tobias Nygren
078790bd0f Implement memorySize() for NetBSD 2015-02-05 20:31:25 +01:00
Audrius Butkevicius
b88c5a89a8 Add rumpelsepp 2015-02-03 00:15:57 +00:00
Audrius Butkevicius
57028e3acc Merge pull request #1325 from rumpelsepp/master
Added exit code definitions to systemd service files (fixes #1324)
2015-02-02 08:04:27 +00:00
Stefan Tatschner
c586a17926 Added exit code definitions to systemd service files (fixes #1324) 2015-02-01 23:55:54 +01:00
Audrius Butkevicius
9d078bac54 Add STBLOCKPROFILE 2015-02-01 19:00:24 +00:00
Audrius Butkevicius
38eaefcabd Add ItemFinished event (fixes #1258) 2015-02-01 18:59:29 +00:00
Audrius Butkevicius
ba8cadc2f1 Opening a browser happens in it's own routine (fixes #1273) 2015-02-01 18:59:28 +00:00
Audrius Butkevicius
380d5dfa6d Remove fd cache (ref #1308) 2015-02-01 18:59:24 +00:00
Audrius Butkevicius
32af626630 Fix issues with renames (fixes #1302)
Extra comments explain current issues.
2015-02-01 18:58:27 +00:00
Audrius Butkevicius
8358fedaf4 Fix failing integration tests 2015-02-01 18:57:46 +00:00
Audrius Butkevicius
ec82b0c648 Merge pull request #1309 from uok/fix-override
Fix button "override changes" line break (fixes #1144)
2015-01-29 10:40:14 +00:00
Ben Schulz
81a87f873f Fix button "override changes" line break 2015-01-29 11:28:59 +01:00
Audrius Butkevicius
d91b8ac444 Merge pull request #1299 from krozycki/master
Show information in folder panel if ignore patterns are active fixes #1279
2015-01-27 19:54:09 +00:00
Karol Różycki
952e51ac75 Show information in folder panel if ignore patterns are active, fixes #1279 2015-01-27 15:27:44 +01:00
Audrius Butkevicius
11267cd44f Merge pull request #1298 from uok/link-usage
Make links to usage report clickable
2015-01-26 20:59:20 +00:00
Ben Schulz
0e59e0aebd Make links to usage report clickable 2015-01-26 17:20:55 +01:00
Audrius Butkevicius
ae1d3b3dd3 Merge pull request #1293 from uok/move-panels
Move panels to top of page (ref #1270)
2015-01-25 09:53:03 +00:00
Ben Schulz
1a91dbee5f Move panels to top of page
- Move panels (new device, new folder, notice) to top of page
- Add icons to panel headers (restart, new folder, notice)
2015-01-23 16:28:30 +01:00
Jakob Borg
fd507e3e41 Merge pull request #1290 from krozycki/master
Ensuring path separator at the end of the folder path. (fixes #1262)
2015-01-22 15:36:32 -08:00
Jakob Borg
9c1a67cf47 Add krozycki 2015-01-22 15:35:58 -08:00
Jakob Borg
69e3824840 Add test for #1262 2015-01-22 15:34:22 -08:00
Karol Różycki
fcb1a98129 Ensuring path separator at the end of the folder path. (fixes #1262) 2015-01-23 00:22:30 +01:00
Audrius Butkevicius
6d942635af Merge pull request #1269 from uok/master
Small improvements for job queue
2015-01-22 22:58:33 +00:00
Audrius Butkevicius
cda2c5d459 Fix integration tests 2015-01-22 22:42:39 +00:00
Jakob Borg
969bb5a742 Fix protocol dependency hash 2015-01-22 13:29:54 -08:00
Jakob Borg
4bccc611c3 Update dependencies 2015-01-22 12:53:10 -08:00
Jakob Borg
d18c4ece0c Merge pull request #1282 from syncthing/integ
Improvements to integration tests
2015-01-22 08:22:46 -08:00
Audrius Butkevicius
25c664b13a Improvements to integration tests 2015-01-22 00:18:08 +00:00
Audrius Butkevicius
7c680c955f Merge pull request #1274 from calmh/minor-tweaks
Integer type policy
2015-01-19 20:40:36 +00:00
Ben Schulz
f037d1b6ca improve job queue 2015-01-19 20:49:19 +01:00
Jakob Borg
2c8b627008 Integer type policy
Integers are for numbers, enabling arithmetic like subtractions and for
loops without getting shot in the foot. Unsigneds are for bitfields.

- "int" for numbers that will always be laughably smaller than four
  billion, and where we don't care about the serialization format.

- "int32" for numbers that will always be laughably smaller than four
  billion, and will be serialized to four bytes.

- "int64" for numbers that may approach four billion or will be
  serialized to eight bytes.

- "uint32" and "uint64" for bitfields, depending on required number of
  bits and serialization format. Likewise "uint8" and "uint16", although
  rare in this project since they don't exist in XDR.

- "int8", "int16" and plain "uint" are almost never useful.
2015-01-19 10:34:36 -08:00
Jakob Borg
221e3eddd5 Remove leveldb panic workaround
Haven't seen this triggered for a long time...
2015-01-19 10:23:00 -08:00
Jakob Borg
74c39c677b Actually remove test file after test run 2015-01-19 10:23:00 -08:00
Jakob Borg
e6558832bf check-contrib 2015-01-19 10:18:28 -08:00
Jakob Borg
9c50625c55 Merge pull request #1267 from rumpelsepp/doc
Fix documentation link
2015-01-19 10:16:43 -08:00
Jakob Borg
d372435e92 Merge pull request #1264 from AudriusButkevicius/tempclean
Put temporary files in the OS temp directory (fixes #1239)
2015-01-19 10:12:32 -08:00
Audrius Butkevicius
a53facf709 Cleanup temporary files (fixes #1239) 2015-01-18 20:34:47 +00:00
Stefan Tatschner
ffc39dfbcb Fix documentation link 2015-01-18 18:17:55 +01:00
Audrius Butkevicius
cba38b15a9 Check for deleted files 2015-01-18 13:44:10 +00:00
Audrius Butkevicius
5ac7564bfe Merge pull request #1259 from calmh/check-folder-shared
Verify folder<->device permission in Request
2015-01-16 12:07:37 +00:00
Jakob Borg
53cd289b90 Verify folder<->device permission in Request
Requests from valid devices for valid folders should be rejected if the
folder is not shared with that device.
2015-01-16 12:50:51 +01:00
Jakob Borg
8dc13bcf1a go1.4.1 2015-01-16 10:18:54 +01:00
Audrius Butkevicius
261825a89b Merge pull request #1256 from calmh/fix-963
Adds File Versioning to folder info (fixes #963)
2015-01-15 17:25:28 +00:00
Jakob Borg
f47a5a309d Add File Versioning to folder info (fixes #963)
Could potentially use shorter value strings ("Simple" vs "Simple File
Versioning"), but this avoid introducing unnecessary strings to
translate - can always be changed in the future.
2015-01-15 15:50:49 +01:00
Jakob Borg
a40f2b9fa0 Merge pull request #1237 from syncthing/renamer
Efficient renames (fixes #1217)
2015-01-14 00:28:58 +01:00
Jakob Borg
cfcd3892f7 More concise changelog 2015-01-14 00:27:29 +01:00
Jakob Borg
703987f61c Changelog should read in chronological order from the top 2015-01-13 23:11:46 +01:00
Audrius Butkevicius
e50a8917ec Add renames to integration tests 2015-01-13 22:07:14 +00:00
Audrius Butkevicius
74d7c8e625 Efficient renames (fixes #1217) 2015-01-13 22:06:13 +00:00
257 changed files with 10312 additions and 5131 deletions

1
.gitignore vendored
View File

@@ -15,3 +15,4 @@ coverage.xml
.DS_Store
syncthing.md5
syncthing.exe.md5
RELEASE

10
AUTHORS
View File

@@ -5,6 +5,7 @@ Alexander Graf <register-github@alex-graf.de>
Andrew Dunham <andrew@du.nham.ca>
Audrius Butkevicius <audrius.butkevicius@gmail.com>
Arthur Axel fREW Schmidt <frew@afoolishmanifesto.com> <frioux@gmail.com>
Ben Curthoys <ben@bencurthoys.com>
Ben Schulz <ueomkail@gmail.com> <uok@users.noreply.github.com>
Ben Sidhom <bsidhom@gmail.com>
Brandon Philips <brandon@ifup.org>
@@ -12,6 +13,7 @@ Brendan Long <self@brendanlong.com>
Caleb Callaway <enlightened.despot@gmail.com>
Cathryne Linenweaver <cathryne.linenweaver@gmail.com> <Cathryne@users.noreply.github.com>
Chris Joel <chris@scriptolo.gy>
Colin Kennedy <moshen.colin@gmail.com>
Daniel Martí <mvdan@mvdan.cc>
Dennis Wilson <dw@risu.io>
Dominik Heidler <dominik@heidler.eu>
@@ -24,16 +26,24 @@ Jakob Borg <jakob@nym.se>
James Patterson <jamespatterson@operamail.com> <jpjp@users.noreply.github.com>
Jens Diemer <github.com@jensdiemer.de> <git@jensdiemer.de>
Jochen Voss <voss@seehuhn.de>
Johan Vromans <jvromans@squirrel.nl>
Karol Różycki <rozycki.karol@gmail.com>
Kamada Ken'ichi <kamada@nanohz.org>
Lode Hoste <zillode@zillode.be>
Marcin Dziadus <dziadus.marcin@gmail.com>
Marc Laporte <marc@marclaporte.com>
Marc Pujol <kilburn@la3.org>
Michael Jephcote <rewt0r@gmx.com> <Rewt0r@users.noreply.github.com>
Michael Tilli <pyfisch@gmail.com>
Pascal Jungblut <github@pascalj.com> <mail@pascal-jungblut.com>
Peter Hoeg <peter@speartail.com>
Philippe Schommers <philippe@schommers.be>
Phill Luby <phill.luby@newredo.com>
Piotr Bejda <piotrb10@gmail.com>
Ryan Sullivan <kayoticsully@gmail.com>
Stefan Tatschner <stefan@sevenbyte.org>
Tim Abell <tim@timwise.co.uk>
Tobias Nygren <tnn@nygren.pp.se>
Tomas Cerveny <kozec@kozec.com>
Tully Robinson <tully@tojr.org>
Veeti Paananen <veeti.paananen@rojekti.fi>

View File

@@ -33,8 +33,8 @@ latest info on Transifex.
Every contribution is welcome. If you want to contribute but are unsure
where to start, any open issues are fair game! Be prepared for a
[certain amount of review](https://discourse.syncthing.net/t/733); it's
all in the name of quality. :) Following the points below will make this
[certain amount of review](https://github.com/syncthing/syncthing/wiki/FAQ#why-are-you-being-so-hard-on-my-pull-request);
it's all in the name of quality. :) Following the points below will make this
a smoother process.
Individuals making significant and valuable contributions are given
@@ -93,8 +93,8 @@ The Syncthing core team currently consists of the following members;
## Licensing
All contributions are made under the same GPL license as the rest of the
project, except documentation, user interface text and translation
All contributions are made under the same MPLv2 license as the rest of
the project, except documentation, user interface text and translation
strings which are licensed under the Creative Commons Attribution 4.0
International License. You retain the copyright to code you have
written.
@@ -105,8 +105,8 @@ add yourself as a separate commit in your first pull request.
## Building
[See the documentation](http://discourse.syncthing.net/t/44) on how to
get started with a build environment.
[See the documentation](https://github.com/syncthing/syncthing/wiki/Building)
on how to get started with a build environment.
## Branches
@@ -133,8 +133,8 @@ Yes please!
## Documentation
[Over here!](http://discourse.syncthing.net/category/documentation)
[Over here!](https://github.com/syncthing/syncthing/wiki)
## License
GPLv3
MPLv2

26
Godeps/Godeps.json generated
View File

@@ -5,10 +5,6 @@
"./cmd/..."
],
"Deps": [
{
"ImportPath": "github.com/AudriusButkevicius/lfu-go",
"Rev": "164bcecceb92fd6037f4d18a8d97b495ec6ef669"
},
{
"ImportPath": "github.com/bkaradzic/go-lz4",
"Rev": "93a831dcee242be64a9cc9803dda84af25932de7"
@@ -21,25 +17,25 @@
"ImportPath": "github.com/calmh/luhn",
"Rev": "0c8388ff95fa92d4094011e5a04fc99dea3d1632"
},
{
"ImportPath": "github.com/calmh/osext",
"Rev": "9bf61584e5f1f172e8766ddc9022d9c401faaa5e"
},
{
"ImportPath": "github.com/calmh/xdr",
"Rev": "214788d8fedfc310c18eca9ed12be408a5054cd5"
"Rev": "ff948d7666c5e0fd18d398f6278881724d36a90b"
},
{
"ImportPath": "github.com/juju/ratelimit",
"Rev": "f9f36d11773655c0485207f0ad30dc2655f69d56"
},
{
"ImportPath": "github.com/kardianos/osext",
"Rev": "91292666f7e40f03185cdd1da7d85633c973eca7"
},
{
"ImportPath": "github.com/syncthing/protocol",
"Rev": "f76b5d800208131015b14cfc1cfd3e6dd1d5e979"
"Rev": "1a4398cc55c8fe82a964097eaf59f2475b020a49"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb",
"Rev": "63c9e642efad852f49e20a6f90194cae112fd2ac"
"Rev": "e3f32eb300aa1e514fe8ba58d008da90a062273d"
},
{
"ImportPath": "github.com/syndtr/gosnappy/snappy",
@@ -59,19 +55,19 @@
},
{
"ImportPath": "golang.org/x/crypto/bcrypt",
"Rev": "731db29863ea7213d9556d0170afb38987f401d4"
"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
},
{
"ImportPath": "golang.org/x/crypto/blowfish",
"Rev": "731db29863ea7213d9556d0170afb38987f401d4"
"Rev": "4ed45ec682102c643324fae5dff8dab085b6c300"
},
{
"ImportPath": "golang.org/x/text/transform",
"Rev": "985ee5acfaf1ff6712c7c99438752f8e09416ccb"
"Rev": "c980adc4a823548817b9c47d38c6ca6b7d7d8b6a"
},
{
"ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "985ee5acfaf1ff6712c7c99438752f8e09416ccb"
"Rev": "c980adc4a823548817b9c47d38c6ca6b7d7d8b6a"
}
]
}

View File

@@ -1,19 +0,0 @@
Copyright (C) 2012 Dave Grijalva
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,19 +0,0 @@
A simple LFU cache for golang. Based on the paper [An O(1) algorithm for implementing the LFU cache eviction scheme](http://dhruvbird.com/lfu.pdf).
Usage:
```go
import "github.com/dgrijalva/lfu-go"
// Make a new thing
c := lfu.New()
// Set some values
c.Set("myKey", myValue)
// Retrieve some values
myValue = c.Get("myKey")
// Evict some values
c.Evict(1)
```

View File

@@ -1,156 +0,0 @@
package lfu
import (
"container/list"
"sync"
)
type Eviction struct {
Key string
Value interface{}
}
type Cache struct {
// If len > UpperBound, cache will automatically evict
// down to LowerBound. If either value is 0, this behavior
// is disabled.
UpperBound int
LowerBound int
values map[string]*cacheEntry
freqs *list.List
len int
lock *sync.Mutex
EvictionChannel chan<- Eviction
}
type cacheEntry struct {
key string
value interface{}
freqNode *list.Element
}
type listEntry struct {
entries map[*cacheEntry]byte
freq int
}
func New() *Cache {
c := new(Cache)
c.values = make(map[string]*cacheEntry)
c.freqs = list.New()
c.lock = new(sync.Mutex)
return c
}
func (c *Cache) Get(key string) interface{} {
c.lock.Lock()
defer c.lock.Unlock()
if e, ok := c.values[key]; ok {
c.increment(e)
return e.value
}
return nil
}
func (c *Cache) Set(key string, value interface{}) {
c.lock.Lock()
defer c.lock.Unlock()
if e, ok := c.values[key]; ok {
// value already exists for key. overwrite
e.value = value
c.increment(e)
} else {
// value doesn't exist. insert
e := new(cacheEntry)
e.key = key
e.value = value
c.values[key] = e
c.increment(e)
c.len++
// bounds mgmt
if c.UpperBound > 0 && c.LowerBound > 0 {
if c.len > c.UpperBound {
c.evict(c.len - c.LowerBound)
}
}
}
}
func (c *Cache) Len() int {
c.lock.Lock()
defer c.lock.Unlock()
return c.len
}
func (c *Cache) Evict(count int) int {
c.lock.Lock()
defer c.lock.Unlock()
return c.evict(count)
}
func (c *Cache) evict(count int) int {
// No lock here so it can be called
// from within the lock (during Set)
var evicted int
for i := 0; i < count; {
if place := c.freqs.Front(); place != nil {
for entry, _ := range place.Value.(*listEntry).entries {
if i < count {
if c.EvictionChannel != nil {
c.EvictionChannel <- Eviction{
Key: entry.key,
Value: entry.value,
}
}
delete(c.values, entry.key)
c.remEntry(place, entry)
evicted++
c.len--
i++
}
}
}
}
return evicted
}
func (c *Cache) increment(e *cacheEntry) {
currentPlace := e.freqNode
var nextFreq int
var nextPlace *list.Element
if currentPlace == nil {
// new entry
nextFreq = 1
nextPlace = c.freqs.Front()
} else {
// move up
nextFreq = currentPlace.Value.(*listEntry).freq + 1
nextPlace = currentPlace.Next()
}
if nextPlace == nil || nextPlace.Value.(*listEntry).freq != nextFreq {
// create a new list entry
li := new(listEntry)
li.freq = nextFreq
li.entries = make(map[*cacheEntry]byte)
if currentPlace != nil {
nextPlace = c.freqs.InsertAfter(li, currentPlace)
} else {
nextPlace = c.freqs.PushFront(li)
}
}
e.freqNode = nextPlace
nextPlace.Value.(*listEntry).entries[e] = 1
if currentPlace != nil {
// remove from current position
c.remEntry(currentPlace, e)
}
}
func (c *Cache) remEntry(place *list.Element, entry *cacheEntry) {
entries := place.Value.(*listEntry).entries
delete(entries, entry)
if len(entries) == 0 {
c.freqs.Remove(place)
}
}

View File

@@ -1,68 +0,0 @@
package lfu
import (
"fmt"
"testing"
)
func TestLFU(t *testing.T) {
c := New()
c.Set("a", "a")
if v := c.Get("a"); v != "a" {
t.Errorf("Value was not saved: %v != 'a'", v)
}
if l := c.Len(); l != 1 {
t.Errorf("Length was not updated: %v != 1", l)
}
c.Set("b", "b")
if v := c.Get("b"); v != "b" {
t.Errorf("Value was not saved: %v != 'b'", v)
}
if l := c.Len(); l != 2 {
t.Errorf("Length was not updated: %v != 2", l)
}
c.Get("a")
evicted := c.Evict(1)
if v := c.Get("a"); v != "a" {
t.Errorf("Value was improperly evicted: %v != 'a'", v)
}
if v := c.Get("b"); v != nil {
t.Errorf("Value was not evicted: %v", v)
}
if l := c.Len(); l != 1 {
t.Errorf("Length was not updated: %v != 1", l)
}
if evicted != 1 {
t.Errorf("Number of evicted items is wrong: %v != 1", evicted)
}
}
func TestBoundsMgmt(t *testing.T) {
c := New()
c.UpperBound = 10
c.LowerBound = 5
for i := 0; i < 100; i++ {
c.Set(fmt.Sprintf("%v", i), i)
}
if c.Len() > 10 {
t.Errorf("Bounds management failed to evict properly: %v", c.Len())
}
}
func TestEviction(t *testing.T) {
ch := make(chan Eviction, 1)
c := New()
c.EvictionChannel = ch
c.Set("a", "b")
c.Evict(1)
ev := <-ch
if ev.Key != "a" || ev.Value.(string) != "b" {
t.Error("Incorrect item")
}
}

View File

@@ -1,194 +1,194 @@
/*
* Copyright 2011-2012 Branimir Karadzic. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package lz4
import (
"encoding/binary"
"errors"
"io"
)
var (
// ErrCorrupt indicates the input was corrupt
ErrCorrupt = errors.New("corrupt input")
)
const (
mlBits = 4
mlMask = (1 << mlBits) - 1
runBits = 8 - mlBits
runMask = (1 << runBits) - 1
)
type decoder struct {
src []byte
dst []byte
spos uint32
dpos uint32
ref uint32
}
func (d *decoder) readByte() (uint8, error) {
if int(d.spos) == len(d.src) {
return 0, io.EOF
}
b := d.src[d.spos]
d.spos++
return b, nil
}
func (d *decoder) getLen() (uint32, error) {
length := uint32(0)
ln, err := d.readByte()
if err != nil {
return 0, ErrCorrupt
}
for ln == 255 {
length += 255
ln, err = d.readByte()
if err != nil {
return 0, ErrCorrupt
}
}
length += uint32(ln)
return length, nil
}
func (d *decoder) cp(length, decr uint32) {
if int(d.ref+length) < int(d.dpos) {
copy(d.dst[d.dpos:], d.dst[d.ref:d.ref+length])
} else {
for ii := uint32(0); ii < length; ii++ {
d.dst[d.dpos+ii] = d.dst[d.ref+ii]
}
}
d.dpos += length
d.ref += length - decr
}
func (d *decoder) finish(err error) error {
if err == io.EOF {
return nil
}
return err
}
// Decode returns the decoded form of src. The returned slice may be a
// subslice of dst if it was large enough to hold the entire decoded block.
func Decode(dst, src []byte) ([]byte, error) {
if len(src) < 4 {
return nil, ErrCorrupt
}
uncompressedLen := binary.LittleEndian.Uint32(src)
if uncompressedLen == 0 {
return nil, nil
}
if uncompressedLen > MaxInputSize {
return nil, ErrTooLarge
}
if dst == nil || len(dst) < int(uncompressedLen) {
dst = make([]byte, uncompressedLen)
}
d := decoder{src: src, dst: dst[:uncompressedLen], spos: 4}
decr := []uint32{0, 3, 2, 3}
for {
code, err := d.readByte()
if err != nil {
return d.dst, d.finish(err)
}
length := uint32(code >> mlBits)
if length == runMask {
ln, err := d.getLen()
if err != nil {
return nil, ErrCorrupt
}
length += ln
}
if int(d.spos+length) > len(d.src) {
return nil, ErrCorrupt
}
for ii := uint32(0); ii < length; ii++ {
d.dst[d.dpos+ii] = d.src[d.spos+ii]
}
d.spos += length
d.dpos += length
if int(d.spos) == len(d.src) {
return d.dst, nil
}
if int(d.spos+2) >= len(d.src) {
return nil, ErrCorrupt
}
back := uint32(d.src[d.spos]) | uint32(d.src[d.spos+1])<<8
if back > d.dpos {
return nil, ErrCorrupt
}
d.spos += 2
d.ref = d.dpos - back
length = uint32(code & mlMask)
if length == mlMask {
ln, err := d.getLen()
if err != nil {
return nil, ErrCorrupt
}
length += ln
}
literal := d.dpos - d.ref
if literal < 4 {
d.cp(4, decr[literal])
} else {
length += 4
}
if d.dpos+length > uncompressedLen {
return nil, ErrCorrupt
}
d.cp(length, 0)
}
}
/*
* Copyright 2011-2012 Branimir Karadzic. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package lz4
import (
"encoding/binary"
"errors"
"io"
)
var (
// ErrCorrupt indicates the input was corrupt
ErrCorrupt = errors.New("corrupt input")
)
const (
mlBits = 4
mlMask = (1 << mlBits) - 1
runBits = 8 - mlBits
runMask = (1 << runBits) - 1
)
type decoder struct {
src []byte
dst []byte
spos uint32
dpos uint32
ref uint32
}
func (d *decoder) readByte() (uint8, error) {
if int(d.spos) == len(d.src) {
return 0, io.EOF
}
b := d.src[d.spos]
d.spos++
return b, nil
}
func (d *decoder) getLen() (uint32, error) {
length := uint32(0)
ln, err := d.readByte()
if err != nil {
return 0, ErrCorrupt
}
for ln == 255 {
length += 255
ln, err = d.readByte()
if err != nil {
return 0, ErrCorrupt
}
}
length += uint32(ln)
return length, nil
}
func (d *decoder) cp(length, decr uint32) {
if int(d.ref+length) < int(d.dpos) {
copy(d.dst[d.dpos:], d.dst[d.ref:d.ref+length])
} else {
for ii := uint32(0); ii < length; ii++ {
d.dst[d.dpos+ii] = d.dst[d.ref+ii]
}
}
d.dpos += length
d.ref += length - decr
}
func (d *decoder) finish(err error) error {
if err == io.EOF {
return nil
}
return err
}
// Decode returns the decoded form of src. The returned slice may be a
// subslice of dst if it was large enough to hold the entire decoded block.
func Decode(dst, src []byte) ([]byte, error) {
if len(src) < 4 {
return nil, ErrCorrupt
}
uncompressedLen := binary.LittleEndian.Uint32(src)
if uncompressedLen == 0 {
return nil, nil
}
if uncompressedLen > MaxInputSize {
return nil, ErrTooLarge
}
if dst == nil || len(dst) < int(uncompressedLen) {
dst = make([]byte, uncompressedLen)
}
d := decoder{src: src, dst: dst[:uncompressedLen], spos: 4}
decr := []uint32{0, 3, 2, 3}
for {
code, err := d.readByte()
if err != nil {
return d.dst, d.finish(err)
}
length := uint32(code >> mlBits)
if length == runMask {
ln, err := d.getLen()
if err != nil {
return nil, ErrCorrupt
}
length += ln
}
if int(d.spos+length) > len(d.src) {
return nil, ErrCorrupt
}
for ii := uint32(0); ii < length; ii++ {
d.dst[d.dpos+ii] = d.src[d.spos+ii]
}
d.spos += length
d.dpos += length
if int(d.spos) == len(d.src) {
return d.dst, nil
}
if int(d.spos+2) >= len(d.src) {
return nil, ErrCorrupt
}
back := uint32(d.src[d.spos]) | uint32(d.src[d.spos+1])<<8
if back > d.dpos {
return nil, ErrCorrupt
}
d.spos += 2
d.ref = d.dpos - back
length = uint32(code & mlMask)
if length == mlMask {
ln, err := d.getLen()
if err != nil {
return nil, ErrCorrupt
}
length += ln
}
literal := d.dpos - d.ref
if literal < 4 {
d.cp(4, decr[literal])
} else {
length += 4
}
if d.dpos+length > uncompressedLen {
return nil, ErrCorrupt
}
d.cp(length, 0)
}
}

View File

@@ -1,188 +1,188 @@
/*
* Copyright 2011-2012 Branimir Karadzic. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package lz4
import "encoding/binary"
import "errors"
const (
minMatch = 4
hashLog = 17
hashTableSize = 1 << hashLog
hashShift = (minMatch * 8) - hashLog
incompressible uint32 = 128
uninitHash = 0x88888888
// MaxInputSize is the largest buffer than can be compressed in a single block
MaxInputSize = 0x7E000000
)
var (
// ErrTooLarge indicates the input buffer was too large
ErrTooLarge = errors.New("input too large")
)
type encoder struct {
src []byte
dst []byte
hashTable []uint32
pos uint32
anchor uint32
dpos uint32
}
// CompressBound returns the maximum length of a lz4 block, given it's uncompressed length
func CompressBound(isize int) int {
if isize > MaxInputSize {
return 0
}
return isize + ((isize) / 255) + 16 + 4
}
func (e *encoder) writeLiterals(length, mlLen, pos uint32) {
ln := length
var code byte
if ln > runMask-1 {
code = runMask
} else {
code = byte(ln)
}
if mlLen > mlMask-1 {
e.dst[e.dpos] = (code << mlBits) + byte(mlMask)
} else {
e.dst[e.dpos] = (code << mlBits) + byte(mlLen)
}
e.dpos++
if code == runMask {
ln -= runMask
for ; ln > 254; ln -= 255 {
e.dst[e.dpos] = 255
e.dpos++
}
e.dst[e.dpos] = byte(ln)
e.dpos++
}
for ii := uint32(0); ii < length; ii++ {
e.dst[e.dpos+ii] = e.src[pos+ii]
}
e.dpos += length
}
// Encode returns the encoded form of src. The returned array may be a
// sub-slice of dst if it was large enough to hold the entire output.
func Encode(dst, src []byte) ([]byte, error) {
if len(src) >= MaxInputSize {
return nil, ErrTooLarge
}
if n := CompressBound(len(src)); len(dst) < n {
dst = make([]byte, n)
}
e := encoder{src: src, dst: dst, hashTable: make([]uint32, hashTableSize)}
binary.LittleEndian.PutUint32(dst, uint32(len(src)))
e.dpos = 4
var (
step uint32 = 1
limit = incompressible
)
for {
if int(e.pos)+12 >= len(e.src) {
e.writeLiterals(uint32(len(e.src))-e.anchor, 0, e.anchor)
return e.dst[:e.dpos], nil
}
sequence := uint32(e.src[e.pos+3])<<24 | uint32(e.src[e.pos+2])<<16 | uint32(e.src[e.pos+1])<<8 | uint32(e.src[e.pos+0])
hash := (sequence * 2654435761) >> hashShift
ref := e.hashTable[hash] + uninitHash
e.hashTable[hash] = e.pos - uninitHash
if ((e.pos-ref)>>16) != 0 || uint32(e.src[ref+3])<<24|uint32(e.src[ref+2])<<16|uint32(e.src[ref+1])<<8|uint32(e.src[ref+0]) != sequence {
if e.pos-e.anchor > limit {
limit <<= 1
step += 1 + (step >> 2)
}
e.pos += step
continue
}
if step > 1 {
e.hashTable[hash] = ref - uninitHash
e.pos -= step - 1
step = 1
continue
}
limit = incompressible
ln := e.pos - e.anchor
back := e.pos - ref
anchor := e.anchor
e.pos += minMatch
ref += minMatch
e.anchor = e.pos
for int(e.pos) < len(e.src)-5 && e.src[e.pos] == e.src[ref] {
e.pos++
ref++
}
mlLen := e.pos - e.anchor
e.writeLiterals(ln, mlLen, anchor)
e.dst[e.dpos] = uint8(back)
e.dst[e.dpos+1] = uint8(back >> 8)
e.dpos += 2
if mlLen > mlMask-1 {
mlLen -= mlMask
for mlLen > 254 {
mlLen -= 255
e.dst[e.dpos] = 255
e.dpos++
}
e.dst[e.dpos] = byte(mlLen)
e.dpos++
}
e.anchor = e.pos
}
}
/*
* Copyright 2011-2012 Branimir Karadzic. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package lz4
import "encoding/binary"
import "errors"
const (
minMatch = 4
hashLog = 17
hashTableSize = 1 << hashLog
hashShift = (minMatch * 8) - hashLog
incompressible uint32 = 128
uninitHash = 0x88888888
// MaxInputSize is the largest buffer than can be compressed in a single block
MaxInputSize = 0x7E000000
)
var (
// ErrTooLarge indicates the input buffer was too large
ErrTooLarge = errors.New("input too large")
)
type encoder struct {
src []byte
dst []byte
hashTable []uint32
pos uint32
anchor uint32
dpos uint32
}
// CompressBound returns the maximum length of a lz4 block, given it's uncompressed length
func CompressBound(isize int) int {
if isize > MaxInputSize {
return 0
}
return isize + ((isize) / 255) + 16 + 4
}
func (e *encoder) writeLiterals(length, mlLen, pos uint32) {
ln := length
var code byte
if ln > runMask-1 {
code = runMask
} else {
code = byte(ln)
}
if mlLen > mlMask-1 {
e.dst[e.dpos] = (code << mlBits) + byte(mlMask)
} else {
e.dst[e.dpos] = (code << mlBits) + byte(mlLen)
}
e.dpos++
if code == runMask {
ln -= runMask
for ; ln > 254; ln -= 255 {
e.dst[e.dpos] = 255
e.dpos++
}
e.dst[e.dpos] = byte(ln)
e.dpos++
}
for ii := uint32(0); ii < length; ii++ {
e.dst[e.dpos+ii] = e.src[pos+ii]
}
e.dpos += length
}
// Encode returns the encoded form of src. The returned array may be a
// sub-slice of dst if it was large enough to hold the entire output.
func Encode(dst, src []byte) ([]byte, error) {
if len(src) >= MaxInputSize {
return nil, ErrTooLarge
}
if n := CompressBound(len(src)); len(dst) < n {
dst = make([]byte, n)
}
e := encoder{src: src, dst: dst, hashTable: make([]uint32, hashTableSize)}
binary.LittleEndian.PutUint32(dst, uint32(len(src)))
e.dpos = 4
var (
step uint32 = 1
limit = incompressible
)
for {
if int(e.pos)+12 >= len(e.src) {
e.writeLiterals(uint32(len(e.src))-e.anchor, 0, e.anchor)
return e.dst[:e.dpos], nil
}
sequence := uint32(e.src[e.pos+3])<<24 | uint32(e.src[e.pos+2])<<16 | uint32(e.src[e.pos+1])<<8 | uint32(e.src[e.pos+0])
hash := (sequence * 2654435761) >> hashShift
ref := e.hashTable[hash] + uninitHash
e.hashTable[hash] = e.pos - uninitHash
if ((e.pos-ref)>>16) != 0 || uint32(e.src[ref+3])<<24|uint32(e.src[ref+2])<<16|uint32(e.src[ref+1])<<8|uint32(e.src[ref+0]) != sequence {
if e.pos-e.anchor > limit {
limit <<= 1
step += 1 + (step >> 2)
}
e.pos += step
continue
}
if step > 1 {
e.hashTable[hash] = ref - uninitHash
e.pos -= step - 1
step = 1
continue
}
limit = incompressible
ln := e.pos - e.anchor
back := e.pos - ref
anchor := e.anchor
e.pos += minMatch
ref += minMatch
e.anchor = e.pos
for int(e.pos) < len(e.src)-5 && e.src[e.pos] == e.src[ref] {
e.pos++
ref++
}
mlLen := e.pos - e.anchor
e.writeLiterals(ln, mlLen, anchor)
e.dst[e.dpos] = uint8(back)
e.dst[e.dpos+1] = uint8(back >> 8)
e.dpos += 2
if mlLen > mlMask-1 {
mlLen -= mlMask
for mlLen > 254 {
mlLen -= 255
e.dst[e.dpos] = 255
e.dpos++
}
e.dst[e.dpos] = byte(mlLen)
e.dpos++
}
e.anchor = e.pos
}
}

View File

@@ -1,20 +0,0 @@
Copyright (c) 2012 Daniel Theophanes
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.

View File

@@ -321,10 +321,10 @@ func generateDiagram(output io.Writer, s structInfo) {
case "bool":
fmt.Fprintf(output, "| %s |V|\n", center(name+" (V=0 or 1)", 59))
fmt.Fprintln(output, line)
case "uint16":
case "int16", "uint16":
fmt.Fprintf(output, "| %s | %s |\n", center("0x0000", 29), center(name, 29))
fmt.Fprintln(output, line)
case "uint32":
case "int32", "uint32":
fmt.Fprintf(output, "| %s |\n", center(name, 61))
fmt.Fprintln(output, line)
case "int64", "uint64":
@@ -374,6 +374,8 @@ func generateXdr(output io.Writer, s structInfo) {
}
switch tn {
case "int16", "int32":
fmt.Fprintf(output, "\tint %s%s;\n", fn, suf)
case "uint16", "uint32":
fmt.Fprintf(output, "\tunsigned int %s%s;\n", fn, suf)
case "int64":

View File

@@ -0,0 +1,27 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,14 @@
### Extensions to the "os" package.
## Find the current Executable and ExecutableFolder.
There is sometimes utility in finding the current executable file
that is running. This can be used for upgrading the current executable
or finding resources located relative to the executable file.
Multi-platform and supports:
* Linux
* OS X
* Windows
* Plan 9
* BSDs.

View File

@@ -25,8 +25,3 @@ func ExecutableFolder() (string, error) {
folder, _ := filepath.Split(p)
return folder, nil
}
// Depricated. Same as Executable().
func GetExePath() (exePath string, err error) {
return Executable()
}

View File

@@ -5,16 +5,16 @@
package osext
import (
"syscall"
"os"
"strconv"
"os"
"strconv"
"syscall"
)
func executable() (string, error) {
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
if err != nil {
return "", err
}
defer f.Close()
return syscall.Fd2path(int(f.Fd()))
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
if err != nil {
return "", err
}
defer f.Close()
return syscall.Fd2path(int(f.Fd()))
}

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux netbsd openbsd solaris
// +build linux netbsd openbsd solaris dragonfly
package osext
@@ -19,7 +19,7 @@ func executable() (string, error) {
return os.Readlink("/proc/self/exe")
case "netbsd":
return os.Readlink("/proc/curproc/exe")
case "openbsd":
case "openbsd", "dragonfly":
return os.Readlink("/proc/curproc/file")
case "solaris":
return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))

View File

@@ -0,0 +1,53 @@
// Copyright (C) 2015 The Protocol Authors.
package protocol
import "fmt"
type Compression int
const (
CompressMetadata Compression = iota // zero value is the default, default should be "metadata"
CompressNever
CompressAlways
compressionThreshold = 128 // don't bother compressing messages smaller than this many bytes
)
var compressionMarshal = map[Compression]string{
CompressNever: "never",
CompressMetadata: "metadata",
CompressAlways: "always",
}
var compressionUnmarshal = map[string]Compression{
// Legacy
"false": CompressNever,
"true": CompressMetadata,
// Current
"never": CompressNever,
"metadata": CompressMetadata,
"always": CompressAlways,
}
func (c Compression) String() string {
s, ok := compressionMarshal[c]
if !ok {
return fmt.Sprintf("unknown:%d", c)
}
return s
}
func (c Compression) GoString() string {
return fmt.Sprintf("%q", c.String())
}
func (c Compression) MarshalText() ([]byte, error) {
return []byte(compressionMarshal[c]), nil
}
func (c *Compression) UnmarshalText(bs []byte) error {
*c = compressionUnmarshal[string(bs)]
return nil
}

View File

@@ -0,0 +1,49 @@
// Copyright (C) 2015 The Protocol Authors.
package protocol
import "testing"
func TestCompressionMarshal(t *testing.T) {
uTestcases := []struct {
s string
c Compression
}{
{"true", CompressMetadata},
{"false", CompressNever},
{"never", CompressNever},
{"metadata", CompressMetadata},
{"always", CompressAlways},
{"whatever", CompressMetadata},
}
mTestcases := []struct {
s string
c Compression
}{
{"never", CompressNever},
{"metadata", CompressMetadata},
{"always", CompressAlways},
}
var c Compression
for _, tc := range uTestcases {
err := c.UnmarshalText([]byte(tc.s))
if err != nil {
t.Error(err)
}
if c != tc.c {
t.Errorf("%s unmarshalled to %d, not %d", tc.s, c, tc.c)
}
}
for _, tc := range mTestcases {
bs, err := tc.c.MarshalText()
if err != nil {
t.Error(err)
}
if s := string(bs); s != tc.s {
t.Errorf("%d marshalled to %q, not %q", tc.c, s, tc.s)
}
}
}

View File

@@ -10,25 +10,25 @@ import (
type countingReader struct {
io.Reader
tot uint64 // bytes
last int64 // unix nanos
tot int64 // bytes
last int64 // unix nanos
}
var (
totalIncoming uint64
totalOutgoing uint64
totalIncoming int64
totalOutgoing int64
)
func (c *countingReader) Read(bs []byte) (int, error) {
n, err := c.Reader.Read(bs)
atomic.AddUint64(&c.tot, uint64(n))
atomic.AddUint64(&totalIncoming, uint64(n))
atomic.AddInt64(&c.tot, int64(n))
atomic.AddInt64(&totalIncoming, int64(n))
atomic.StoreInt64(&c.last, time.Now().UnixNano())
return n, err
}
func (c *countingReader) Tot() uint64 {
return atomic.LoadUint64(&c.tot)
func (c *countingReader) Tot() int64 {
return atomic.LoadInt64(&c.tot)
}
func (c *countingReader) Last() time.Time {
@@ -37,26 +37,26 @@ func (c *countingReader) Last() time.Time {
type countingWriter struct {
io.Writer
tot uint64 // bytes
last int64 // unix nanos
tot int64 // bytes
last int64 // unix nanos
}
func (c *countingWriter) Write(bs []byte) (int, error) {
n, err := c.Writer.Write(bs)
atomic.AddUint64(&c.tot, uint64(n))
atomic.AddUint64(&totalOutgoing, uint64(n))
atomic.AddInt64(&c.tot, int64(n))
atomic.AddInt64(&totalOutgoing, int64(n))
atomic.StoreInt64(&c.last, time.Now().UnixNano())
return n, err
}
func (c *countingWriter) Tot() uint64 {
return atomic.LoadUint64(&c.tot)
func (c *countingWriter) Tot() int64 {
return atomic.LoadInt64(&c.tot)
}
func (c *countingWriter) Last() time.Time {
return time.Unix(0, atomic.LoadInt64(&c.last))
}
func TotalInOut() (uint64, uint64) {
return atomic.LoadUint64(&totalIncoming), atomic.LoadUint64(&totalOutgoing)
func TotalInOut() (int64, int64) {
return atomic.LoadInt64(&totalIncoming), atomic.LoadInt64(&totalOutgoing)
}

View File

@@ -1,6 +1,5 @@
// Copyright (C) 2014 The Protocol Authors.
//go:generate -command genxdr go run ../../Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go
//go:generate genxdr -o message_xdr.go message.go
package protocol
@@ -8,7 +7,7 @@ package protocol
import "fmt"
type IndexMessage struct {
Folder string // max:64
Folder string
Files []FileInfo
Flags uint32
Options []Option // max:64
@@ -18,8 +17,8 @@ type FileInfo struct {
Name string // max:8192
Flags uint32
Modified int64
Version uint64
LocalVersion uint64
Version int64
LocalVersion int64
Blocks []BlockInfo
}
@@ -60,7 +59,7 @@ func (f FileInfo) HasPermissionBits() bool {
type BlockInfo struct {
Offset int64 // noencode (cache only)
Size uint32
Size int32
Hash []byte // max:64
}
@@ -71,8 +70,8 @@ func (b BlockInfo) String() string {
type RequestMessage struct {
Folder string // max:64
Name string // max:8192
Offset uint64
Size uint32
Offset int64
Size int32
Hash []byte // max:64
Flags uint32
Options []Option // max:64
@@ -80,13 +79,13 @@ type RequestMessage struct {
type ResponseMessage struct {
Data []byte
Error uint32
Error int32
}
type ClusterConfigMessage struct {
ClientName string // max:64
ClientVersion string // max:64
Folders []Folder // max:64
ClientName string // max:64
ClientVersion string // max:64
Folders []Folder
Options []Option // max:64
}
@@ -107,7 +106,7 @@ type Folder struct {
type Device struct {
ID []byte // max:32
Flags uint32
MaxLocalVersion uint64
MaxLocalVersion int64
}
type Option struct {
@@ -117,7 +116,7 @@ type Option struct {
type CloseMessage struct {
Reason string // max:1024
Code uint32
Code int32
}
type EmptyMessage struct{}

View File

@@ -41,7 +41,7 @@ IndexMessage Structure:
struct IndexMessage {
string Folder<64>;
string Folder<>;
FileInfo Files<>;
unsigned int Flags;
Option Options<64>;
@@ -74,9 +74,6 @@ func (o IndexMessage) AppendXDR(bs []byte) ([]byte, error) {
}
func (o IndexMessage) encodeXDR(xw *xdr.Writer) (int, error) {
if l := len(o.Folder); l > 64 {
return xw.Tot(), xdr.ElementSizeExceeded("Folder", l, 64)
}
xw.WriteString(o.Folder)
xw.WriteUint32(uint32(len(o.Files)))
for i := range o.Files {
@@ -111,7 +108,7 @@ func (o *IndexMessage) UnmarshalXDR(bs []byte) error {
}
func (o *IndexMessage) decodeXDR(xr *xdr.Reader) error {
o.Folder = xr.ReadStringMax(64)
o.Folder = xr.ReadString()
_FilesSize := int(xr.ReadUint32())
o.Files = make([]FileInfo, _FilesSize)
for i := range o.Files {
@@ -168,8 +165,8 @@ struct FileInfo {
string Name<8192>;
unsigned int Flags;
hyper Modified;
unsigned hyper Version;
unsigned hyper LocalVersion;
hyper Version;
hyper LocalVersion;
BlockInfo Blocks<>;
}
@@ -206,8 +203,8 @@ func (o FileInfo) encodeXDR(xw *xdr.Writer) (int, error) {
xw.WriteString(o.Name)
xw.WriteUint32(o.Flags)
xw.WriteUint64(uint64(o.Modified))
xw.WriteUint64(o.Version)
xw.WriteUint64(o.LocalVersion)
xw.WriteUint64(uint64(o.Version))
xw.WriteUint64(uint64(o.LocalVersion))
xw.WriteUint32(uint32(len(o.Blocks)))
for i := range o.Blocks {
_, err := o.Blocks[i].encodeXDR(xw)
@@ -233,8 +230,8 @@ func (o *FileInfo) decodeXDR(xr *xdr.Reader) error {
o.Name = xr.ReadStringMax(8192)
o.Flags = xr.ReadUint32()
o.Modified = int64(xr.ReadUint64())
o.Version = xr.ReadUint64()
o.LocalVersion = xr.ReadUint64()
o.Version = int64(xr.ReadUint64())
o.LocalVersion = int64(xr.ReadUint64())
_BlocksSize := int(xr.ReadUint32())
o.Blocks = make([]BlockInfo, _BlocksSize)
for i := range o.Blocks {
@@ -261,7 +258,7 @@ BlockInfo Structure:
struct BlockInfo {
unsigned int Size;
int Size;
opaque Hash<64>;
}
@@ -292,7 +289,7 @@ func (o BlockInfo) AppendXDR(bs []byte) ([]byte, error) {
}
func (o BlockInfo) encodeXDR(xw *xdr.Writer) (int, error) {
xw.WriteUint32(o.Size)
xw.WriteUint32(uint32(o.Size))
if l := len(o.Hash); l > 64 {
return xw.Tot(), xdr.ElementSizeExceeded("Hash", l, 64)
}
@@ -312,7 +309,7 @@ func (o *BlockInfo) UnmarshalXDR(bs []byte) error {
}
func (o *BlockInfo) decodeXDR(xr *xdr.Reader) error {
o.Size = xr.ReadUint32()
o.Size = int32(xr.ReadUint32())
o.Hash = xr.ReadBytesMax(64)
return xr.Error()
}
@@ -361,8 +358,8 @@ RequestMessage Structure:
struct RequestMessage {
string Folder<64>;
string Name<8192>;
unsigned hyper Offset;
unsigned int Size;
hyper Offset;
int Size;
opaque Hash<64>;
unsigned int Flags;
Option Options<64>;
@@ -403,8 +400,8 @@ func (o RequestMessage) encodeXDR(xw *xdr.Writer) (int, error) {
return xw.Tot(), xdr.ElementSizeExceeded("Name", l, 8192)
}
xw.WriteString(o.Name)
xw.WriteUint64(o.Offset)
xw.WriteUint32(o.Size)
xw.WriteUint64(uint64(o.Offset))
xw.WriteUint32(uint32(o.Size))
if l := len(o.Hash); l > 64 {
return xw.Tot(), xdr.ElementSizeExceeded("Hash", l, 64)
}
@@ -437,8 +434,8 @@ func (o *RequestMessage) UnmarshalXDR(bs []byte) error {
func (o *RequestMessage) decodeXDR(xr *xdr.Reader) error {
o.Folder = xr.ReadStringMax(64)
o.Name = xr.ReadStringMax(8192)
o.Offset = xr.ReadUint64()
o.Size = xr.ReadUint32()
o.Offset = int64(xr.ReadUint64())
o.Size = int32(xr.ReadUint32())
o.Hash = xr.ReadBytesMax(64)
o.Flags = xr.ReadUint32()
_OptionsSize := int(xr.ReadUint32())
@@ -471,7 +468,7 @@ ResponseMessage Structure:
struct ResponseMessage {
opaque Data<>;
unsigned int Error;
int Error;
}
*/
@@ -502,7 +499,7 @@ func (o ResponseMessage) AppendXDR(bs []byte) ([]byte, error) {
func (o ResponseMessage) encodeXDR(xw *xdr.Writer) (int, error) {
xw.WriteBytes(o.Data)
xw.WriteUint32(o.Error)
xw.WriteUint32(uint32(o.Error))
return xw.Tot(), xw.Error()
}
@@ -519,7 +516,7 @@ func (o *ResponseMessage) UnmarshalXDR(bs []byte) error {
func (o *ResponseMessage) decodeXDR(xr *xdr.Reader) error {
o.Data = xr.ReadBytes()
o.Error = xr.ReadUint32()
o.Error = int32(xr.ReadUint32())
return xr.Error()
}
@@ -559,7 +556,7 @@ ClusterConfigMessage Structure:
struct ClusterConfigMessage {
string ClientName<64>;
string ClientVersion<64>;
Folder Folders<64>;
Folder Folders<>;
Option Options<64>;
}
@@ -598,9 +595,6 @@ func (o ClusterConfigMessage) encodeXDR(xw *xdr.Writer) (int, error) {
return xw.Tot(), xdr.ElementSizeExceeded("ClientVersion", l, 64)
}
xw.WriteString(o.ClientVersion)
if l := len(o.Folders); l > 64 {
return xw.Tot(), xdr.ElementSizeExceeded("Folders", l, 64)
}
xw.WriteUint32(uint32(len(o.Folders)))
for i := range o.Folders {
_, err := o.Folders[i].encodeXDR(xw)
@@ -636,9 +630,6 @@ func (o *ClusterConfigMessage) decodeXDR(xr *xdr.Reader) error {
o.ClientName = xr.ReadStringMax(64)
o.ClientVersion = xr.ReadStringMax(64)
_FoldersSize := int(xr.ReadUint32())
if _FoldersSize > 64 {
return xdr.ElementSizeExceeded("Folders", _FoldersSize, 64)
}
o.Folders = make([]Folder, _FoldersSize)
for i := range o.Folders {
(&o.Folders[i]).decodeXDR(xr)
@@ -766,7 +757,7 @@ Device Structure:
struct Device {
opaque ID<32>;
unsigned int Flags;
unsigned hyper MaxLocalVersion;
hyper MaxLocalVersion;
}
*/
@@ -801,7 +792,7 @@ func (o Device) encodeXDR(xw *xdr.Writer) (int, error) {
}
xw.WriteBytes(o.ID)
xw.WriteUint32(o.Flags)
xw.WriteUint64(o.MaxLocalVersion)
xw.WriteUint64(uint64(o.MaxLocalVersion))
return xw.Tot(), xw.Error()
}
@@ -819,7 +810,7 @@ func (o *Device) UnmarshalXDR(bs []byte) error {
func (o *Device) decodeXDR(xr *xdr.Reader) error {
o.ID = xr.ReadBytesMax(32)
o.Flags = xr.ReadUint32()
o.MaxLocalVersion = xr.ReadUint64()
o.MaxLocalVersion = int64(xr.ReadUint64())
return xr.Error()
}
@@ -923,7 +914,7 @@ CloseMessage Structure:
struct CloseMessage {
string Reason<1024>;
unsigned int Code;
int Code;
}
*/
@@ -957,7 +948,7 @@ func (o CloseMessage) encodeXDR(xw *xdr.Writer) (int, error) {
return xw.Tot(), xdr.ElementSizeExceeded("Reason", l, 1024)
}
xw.WriteString(o.Reason)
xw.WriteUint32(o.Code)
xw.WriteUint32(uint32(o.Code))
return xw.Tot(), xw.Error()
}
@@ -974,7 +965,7 @@ func (o *CloseMessage) UnmarshalXDR(bs []byte) error {
func (o *CloseMessage) decodeXDR(xr *xdr.Reader) error {
o.Reason = xr.ReadStringMax(1024)
o.Code = xr.ReadUint32()
o.Code = int32(xr.ReadUint32())
return xr.Error()
}

View File

@@ -43,6 +43,8 @@ const (
FlagSymlink = 1 << 16
FlagSymlinkMissingTarget = 1 << 17
FlagsAll = (1 << 18) - 1
SymlinkTypeMask = FlagDirectory | FlagSymlinkMissingTarget
)
@@ -104,7 +106,7 @@ type rawConnection struct {
closed chan struct{}
once sync.Once
compressionThreshold int // compress messages larger than this many bytes
compression Compression
rdbuf0 []byte // used & reused by readMessage
rdbuf1 []byte // used & reused by readMessage
@@ -133,25 +135,21 @@ const (
pingIdleTime = 60 * time.Second
)
func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, receiver Model, name string, compress bool) Connection {
func NewConnection(deviceID DeviceID, reader io.Reader, writer io.Writer, receiver Model, name string, compress Compression) Connection {
cr := &countingReader{Reader: reader}
cw := &countingWriter{Writer: writer}
compThres := 1<<31 - 1 // compression disabled
if compress {
compThres = 128 // compress messages that are 128 bytes long or larger
}
c := rawConnection{
id: deviceID,
name: name,
receiver: nativeModel{receiver},
state: stateInitial,
cr: cr,
cw: cw,
outbox: make(chan hdrMsg),
nextID: make(chan int),
closed: make(chan struct{}),
compressionThreshold: compThres,
id: deviceID,
name: name,
receiver: nativeModel{receiver},
state: stateInitial,
cr: cr,
cw: cw,
outbox: make(chan hdrMsg),
nextID: make(chan int),
closed: make(chan struct{}),
compression: compress,
}
go c.readerLoop()
@@ -222,8 +220,8 @@ func (c *rawConnection) Request(folder string, name string, offset int64, size i
ok := c.send(id, messageTypeRequest, RequestMessage{
Folder: folder,
Name: name,
Offset: uint64(offset),
Size: uint32(size),
Offset: offset,
Size: int32(size),
})
if !ok {
return nil, ErrClosed
@@ -569,7 +567,15 @@ func (c *rawConnection) writerLoop() {
return
}
if len(uncBuf) >= c.compressionThreshold {
compress := false
switch c.compression {
case CompressAlways:
compress = true
case CompressMetadata:
compress = hm.hdr.msgType != messageTypeResponse
}
if compress && len(uncBuf) >= compressionThreshold {
// Use compression for large messages
hm.hdr.compression = true
@@ -706,8 +712,8 @@ func (c *rawConnection) pingerLoop() {
type Statistics struct {
At time.Time
InBytesTotal uint64
OutBytesTotal uint64
InBytesTotal int64
OutBytesTotal int64
}
func (c *rawConnection) Statistics() Statistics {

View File

@@ -67,8 +67,8 @@ func TestPing(t *testing.T) {
ar, aw := io.Pipe()
br, bw := io.Pipe()
c0 := NewConnection(c0ID, ar, bw, nil, "name", true).(wireFormatConnection).next.(*rawConnection)
c1 := NewConnection(c1ID, br, aw, nil, "name", true).(wireFormatConnection).next.(*rawConnection)
c0 := NewConnection(c0ID, ar, bw, nil, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
c1 := NewConnection(c1ID, br, aw, nil, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
if ok := c0.ping(); !ok {
t.Error("c0 ping failed")
@@ -91,8 +91,8 @@ func TestPingErr(t *testing.T) {
eaw := &ErrPipe{PipeWriter: *aw, max: i, err: e}
ebw := &ErrPipe{PipeWriter: *bw, max: j, err: e}
c0 := NewConnection(c0ID, ar, ebw, m0, "name", true).(wireFormatConnection).next.(*rawConnection)
NewConnection(c1ID, br, eaw, m1, "name", true)
c0 := NewConnection(c0ID, ar, ebw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
NewConnection(c1ID, br, eaw, m1, "name", CompressAlways)
res := c0.ping()
if (i < 8 || j < 8) && res {
@@ -167,8 +167,8 @@ func TestVersionErr(t *testing.T) {
ar, aw := io.Pipe()
br, bw := io.Pipe()
c0 := NewConnection(c0ID, ar, bw, m0, "name", true).(wireFormatConnection).next.(*rawConnection)
NewConnection(c1ID, br, aw, m1, "name", true)
c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
w := xdr.NewWriter(c0.cw)
w.WriteUint32(encodeHeader(header{
@@ -190,8 +190,8 @@ func TestTypeErr(t *testing.T) {
ar, aw := io.Pipe()
br, bw := io.Pipe()
c0 := NewConnection(c0ID, ar, bw, m0, "name", true).(wireFormatConnection).next.(*rawConnection)
NewConnection(c1ID, br, aw, m1, "name", true)
c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
w := xdr.NewWriter(c0.cw)
w.WriteUint32(encodeHeader(header{
@@ -213,8 +213,8 @@ func TestClose(t *testing.T) {
ar, aw := io.Pipe()
br, bw := io.Pipe()
c0 := NewConnection(c0ID, ar, bw, m0, "name", true).(wireFormatConnection).next.(*rawConnection)
NewConnection(c1ID, br, aw, m1, "name", true)
c0 := NewConnection(c0ID, ar, bw, m0, "name", CompressAlways).(wireFormatConnection).next.(*rawConnection)
NewConnection(c1ID, br, aw, m1, "name", CompressAlways)
c0.close(nil)

View File

@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// +build go1.3
// +build !go1.2
package leveldb

View File

@@ -0,0 +1,30 @@
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// +build !go1.2
package cache
import (
"math/rand"
"testing"
)
func BenchmarkLRUCache(b *testing.B) {
c := NewCache(NewLRU(10000))
b.SetParallelism(10)
b.RunParallel(func(pb *testing.PB) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for pb.Next() {
key := uint64(r.Intn(1000000))
c.Get(0, key, func() (int, Value) {
return 1, key
}).Release()
}
})
}

View File

@@ -552,19 +552,3 @@ func TestLRUCache_Close(t *testing.T) {
t.Errorf("delFunc isn't called 1 times: got=%d", delFuncCalled)
}
}
func BenchmarkLRUCache(b *testing.B) {
c := NewCache(NewLRU(10000))
b.SetParallelism(10)
b.RunParallel(func(pb *testing.PB) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for pb.Next() {
key := uint64(r.Intn(1000000))
c.Get(0, key, func() (int, Value) {
return 1, key
}).Release()
}
})
}

View File

@@ -347,12 +347,14 @@ func recoverTable(s *session, o *opt.Options) error {
return err
}
iter := tr.NewIterator(nil, nil)
iter.(iterator.ErrorCallbackSetter).SetErrorCallback(func(err error) {
if errors.IsCorrupted(err) {
s.logf("table@recovery block corruption @%d %q", file.Num(), err)
tcorruptedBlock++
}
})
if itererr, ok := iter.(iterator.ErrorCallbackSetter); ok {
itererr.SetErrorCallback(func(err error) {
if errors.IsCorrupted(err) {
s.logf("table@recovery block corruption @%d %q", file.Num(), err)
tcorruptedBlock++
}
})
}
// Scan the table.
for iter.Next() {

1047
LICENSE
View File

File diff suppressed because it is too large Load Diff

10
NICKS
View File

@@ -10,6 +10,7 @@ Zillode <zillode@zillode.be>
alex2108 <register-github@alex-graf.de>
andrew-d <andrew@du.nham.ca>
asdil12 <dominik@heidler.eu>
bencurthoys <ben@bencurthoys.com>
bigbear2nd <bigbear2nd@gmail.com>
brendanlong <self@brendanlong.com>
bsidhom <bsidhom@gmail.com>
@@ -23,18 +24,27 @@ frioux <frew@afoolishmanifesto.com> <frioux@gmail.com>
gillisig <gilli@vx.is>
jedie <github.com@jensdiemer.de> <git@jensdiemer.de>
jpjp <jamespatterson@operamail.com> <jpjp@users.noreply.github.com>
kamadak <kamada@nanohz.org>
kilburn <kilburn@la3.org>
kozec <kozec@kozec.com>
krozycki <rozycki.karol@gmail.com>
marcindziadus <dziadus.marcin@gmail.com>
marclaporte <marc@marclaporte.com>
moshen <moshen.colin@gmail.com>
mvdan <mvdan@mvdan.cc>
pascalj <github@pascalj.com> <mail@pascal-jungblut.com>
peterhoeg <peter@speartail.com>
philips <brandon@ifup.org>
piobpl <piotrb10@gmail.com>
pluby <phill.luby@newredo.com>
pyfisch <pyfisch@gmail.com>
rumpelsepp <stefan@sevenbyte.org>
qbit <qbit@deftly.net>
sciurius <jvromans@squirrel.nl>
seehuhn <voss@seehuhn.de>
snnd <dw@risu.io>
timabell <tim@timwise.co.uk>
tnn2 <tnn@nygren.pp.se>
tojrobinson <tully@tojr.org>
uok <ueomkail@gmail.com> <uok@users.noreply.github.com>
veeti <veeti.paananen@rojekti.fi>

View File

@@ -3,7 +3,7 @@ syncthing
[![Latest Build](http://img.shields.io/jenkins/s/http/build.syncthing.net/syncthing.svg?style=flat-square)](http://build.syncthing.net/job/syncthing/lastBuild/)
[![API Documentation](http://img.shields.io/badge/api-Godoc-blue.svg?style=flat-square)](http://godoc.org/github.com/syncthing/syncthing)
[![GPL License](http://img.shields.io/badge/license-GPL-blue.svg?style=flat-square)](http://opensource.org/licenses/GPL-3.0)
[![MPLv2 License](http://img.shields.io/badge/license-MPLv2-blue.svg?style=flat-square)](https://www.mozilla.org/MPL/2.0/)
This is the `syncthing` project. The following are the project goals:
@@ -57,5 +57,4 @@ documentation](https://github.com/syncthing/syncthing/wiki/) is on the
Github wiki.
All code is licensed under the
[GPL](https://github.com/syncthing/syncthing/blob/master/LICENSE), v3 or
later.
[MPLv2](https://github.com/syncthing/syncthing/blob/master/LICENSE).

BIN
assets/logo-horizontal.svg Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
assets/logo-only.svg Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/logo-vertical.svg Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build ignore
@@ -301,7 +292,7 @@ func assets() {
}
func xdr() {
runPrint("go", "generate", "./internal/discover", "./internal/db", "./internal/protocol")
runPrint("go", "generate", "./internal/discover", "./internal/db")
}
func translate() {
@@ -350,16 +341,43 @@ func rmr(paths ...string) {
}
}
func getVersion() string {
func getReleaseVersion() (string, error) {
fd, err := os.Open("RELEASE")
if err != nil {
return "", err
}
defer fd.Close()
bs, err := ioutil.ReadAll(fd)
if err != nil {
return "", err
}
return string(bytes.TrimSpace(bs)), nil
}
func getGitVersion() (string, error) {
v, err := runError("git", "describe", "--always", "--dirty")
if err != nil {
return "unknown-dev"
return "", err
}
v = versionRe.ReplaceAllFunc(v, func(s []byte) []byte {
s[0] = '+'
return s
})
return string(v)
return string(v), nil
}
func getVersion() string {
// First try for a RELEASE file,
if ver, err := getReleaseVersion(); err == nil {
return ver
}
// ... then see if we have a Git tag.
if ver, err := getGitVersion(); err == nil {
return ver
}
// This seems to be a dev build.
return "unknown-dev"
}
func buildStamp() int64 {

View File

@@ -2,7 +2,7 @@
set -euo pipefail
IFS=$'\n\t'
DOCKERIMGV=1.4-5
STTRACE=${STTRACE:-}
case "${1:-default}" in
default)
@@ -50,20 +50,29 @@ case "${1:-default}" in
;;
all)
go run build.go -goos linux -goarch amd64 tar
go run build.go -goos darwin -goarch amd64 tar
go run build.go -goos darwin -goarch 386 tar
go run build.go -goos dragonfly -goarch 386 tar
go run build.go -goos dragonfly -goarch amd64 tar
go run build.go -goos freebsd -goarch 386 tar
go run build.go -goos freebsd -goarch amd64 tar
go run build.go -goos linux -goarch 386 tar
go run build.go -goos linux -goarch amd64 tar
go run build.go -goos linux -goarch arm tar
go run build.go -goos freebsd -goarch amd64 tar
go run build.go -goos freebsd -goarch 386 tar
go run build.go -goos netbsd -goarch 386 tar
go run build.go -goos netbsd -goarch amd64 tar
go run build.go -goos openbsd -goarch amd64 tar
go run build.go -goos openbsd -goarch 386 tar
go run build.go -goos openbsd -goarch amd64 tar
go run build.go -goos darwin -goarch amd64 tar
go run build.go -goos solaris -goarch amd64 tar
go run build.go -goos windows -goarch amd64 zip
go run build.go -goos windows -goarch 386 zip
go run build.go -goos windows -goarch amd64 zip
;;
setup)
@@ -102,15 +111,12 @@ case "${1:-default}" in
fi
;;
docker-init)
docker build -q -t syncthing/build:$DOCKERIMGV docker
;;
docker-all)
docker run --rm -h syncthing-builder -u $(id -u) -t \
-v $(pwd):/go/src/github.com/syncthing/syncthing \
-w /go/src/github.com/syncthing/syncthing \
syncthing/build:$DOCKERIMGV \
-e "STTRACE=$STTRACE" \
syncthing/build:latest \
sh -c './build.sh clean \
&& go vet ./cmd/... ./internal/... \
&& ( golint ./cmd/... ; golint ./internal/... ) | egrep -v "comment on exported|should have comment" \
@@ -122,7 +128,8 @@ case "${1:-default}" in
docker run --rm -h syncthing-builder -u $(id -u) -t \
-v $(pwd):/go/src/github.com/syncthing/syncthing \
-w /go/src/github.com/syncthing/syncthing \
syncthing/build:$DOCKERIMGV \
-e "STTRACE=$STTRACE" \
syncthing/build:latest \
sh -euxc './build.sh clean \
&& go run build.go -race \
&& export GOPATH=$(pwd)/Godeps/_workspace:$GOPATH \

View File

@@ -5,5 +5,7 @@ if [[ -z $since ]] ; then
since="$(git describe --abbrev=0 HEAD^).."
fi
git log --pretty=format:'* %s \n (%h, @%aN)' "$since" | egrep 'fixes #\d|ref #\d' | sed s/\\\\n/\\$'\n'/
git log --reverse --pretty=format:'* %s, @%aN)' "$since" | egrep 'fixes #\d|ref #\d' | sed 's/)[,. ]*,/,/' | sed 's/fixes #/#/g' | sed 's/ref #/#/g'
git diff "$since" -- AUTHORS

View File

@@ -16,7 +16,8 @@ no-docs-typos() {
grep -v f1120d7aa936c0658429edef0037792520b46334 |\
grep -v a9339d0627fff439879d157c75077f02c9fac61b |\
grep -v 254c63763a3ad42fd82259f1767db526cff94a14 |\
grep -v 4b76ec40c07078beaa2c5e250ed7d9bd6276a718
grep -v 4b76ec40c07078beaa2c5e250ed7d9bd6276a718 |\
grep -v ffc39dfbcb34eacc3ea12327a02b6e7741a2c207
}
print-missing-authors() {

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build ignore

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -0,0 +1,50 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
import (
"fmt"
"os"
"runtime"
"runtime/pprof"
"syscall"
"time"
)
func init() {
if innerProcess && os.Getenv("STBLOCKPROFILE") != "" {
profiler := pprof.Lookup("block")
if profiler == nil {
panic("Couldn't find block profiler")
}
l.Debugln("Starting block profiling")
go saveBlockingProfiles(profiler)
}
}
func saveBlockingProfiles(profiler *pprof.Profile) {
runtime.SetBlockProfileRate(1)
t0 := time.Now()
for t := range time.NewTicker(20 * time.Second).C {
startms := int(t.Sub(t0).Seconds() * 1000)
fd, err := os.Create(fmt.Sprintf("block-%05d-%07d.pprof", syscall.Getpid(), startms))
if err != nil {
panic(err)
}
err = profiler.WriteTo(fd, 0)
if err != nil {
panic(err)
}
err = fd.Close()
if err != nil {
panic(err)
}
}
}

View File

@@ -0,0 +1,295 @@
// Copyright (C) 2015 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
import (
"crypto/tls"
"fmt"
"io"
"net"
"strings"
"time"
"github.com/syncthing/protocol"
"github.com/syncthing/syncthing/internal/events"
"github.com/syncthing/syncthing/internal/model"
)
func listenConnect(myID protocol.DeviceID, m *model.Model, tlsCfg *tls.Config) {
var conns = make(chan *tls.Conn)
// Listen
for _, addr := range cfg.Options().ListenAddress {
go listenTLS(conns, addr, tlsCfg)
}
// Connect
go dialTLS(m, conns, tlsCfg)
next:
for conn := range conns {
cs := conn.ConnectionState()
// We should have negotiated the next level protocol "bep/1.0" as part
// of the TLS handshake. Unfortunately this can't be a hard error,
// because there are implementations out there that don't support
// protocol negotiation (iOS for one...).
if !cs.NegotiatedProtocolIsMutual || cs.NegotiatedProtocol != bepProtocolName {
l.Infof("Peer %s did not negotiate bep/1.0", conn.RemoteAddr())
}
// We should have received exactly one certificate from the other
// side. If we didn't, they don't have a device ID and we drop the
// connection.
certs := cs.PeerCertificates
if cl := len(certs); cl != 1 {
l.Infof("Got peer certificate list of length %d != 1 from %s; protocol error", cl, conn.RemoteAddr())
conn.Close()
continue
}
remoteCert := certs[0]
remoteID := protocol.NewDeviceID(remoteCert.Raw)
// The device ID should not be that of ourselves. It can happen
// though, especially in the presense of NAT hairpinning, multiple
// clients between the same NAT gateway, and global discovery.
if remoteID == myID {
l.Infof("Connected to myself (%s) - should not happen", remoteID)
conn.Close()
continue
}
// We should not already be connected to the other party. TODO: This
// could use some better handling. If the old connection is dead but
// hasn't timed out yet we may want to drop *that* connection and keep
// this one. But in case we are two devices connecting to each other
// in parallell we don't want to do that or we end up with no
// connections still established...
if m.ConnectedTo(remoteID) {
l.Infof("Connected to already connected device (%s)", remoteID)
conn.Close()
continue
}
for deviceID, deviceCfg := range cfg.Devices() {
if deviceID == remoteID {
// Verify the name on the certificate. By default we set it to
// "syncthing" when generating, but the user may have replaced
// the certificate and used another name.
certName := deviceCfg.CertName
if certName == "" {
certName = tlsDefaultCommonName
}
err := remoteCert.VerifyHostname(certName)
if err != nil {
// Incorrect certificate name is something the user most
// likely wants to know about, since it's an advanced
// config. Warn instead of Info.
l.Warnf("Bad certificate from %s (%v): %v", remoteID, conn.RemoteAddr(), err)
conn.Close()
continue next
}
// If rate limiting is set, and based on the address we should
// limit the connection, then we wrap it in a limiter.
limit := shouldLimit(conn.RemoteAddr())
wr := io.Writer(conn)
if limit && writeRateLimit != nil {
wr = &limitedWriter{conn, writeRateLimit}
}
rd := io.Reader(conn)
if limit && readRateLimit != nil {
rd = &limitedReader{conn, readRateLimit}
}
name := fmt.Sprintf("%s-%s", conn.LocalAddr(), conn.RemoteAddr())
protoConn := protocol.NewConnection(remoteID, rd, wr, m, name, deviceCfg.Compression)
l.Infof("Established secure connection to %s at %s", remoteID, name)
if debugNet {
l.Debugf("cipher suite: %04X in lan: %t", conn.ConnectionState().CipherSuite, !limit)
}
events.Default.Log(events.DeviceConnected, map[string]string{
"id": remoteID.String(),
"addr": conn.RemoteAddr().String(),
})
m.AddConnection(conn, protoConn)
continue next
}
}
if !cfg.IgnoredDevice(remoteID) {
events.Default.Log(events.DeviceRejected, map[string]string{
"device": remoteID.String(),
"address": conn.RemoteAddr().String(),
})
l.Infof("Connection from %s with unknown device ID %s", conn.RemoteAddr(), remoteID)
} else {
l.Infof("Connection from %s with ignored device ID %s", conn.RemoteAddr(), remoteID)
}
conn.Close()
}
}
func listenTLS(conns chan *tls.Conn, addr string, tlsCfg *tls.Config) {
if debugNet {
l.Debugln("listening on", addr)
}
tcaddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
l.Fatalln("listen (BEP):", err)
}
listener, err := net.ListenTCP("tcp", tcaddr)
if err != nil {
l.Fatalln("listen (BEP):", err)
}
for {
conn, err := listener.Accept()
if err != nil {
l.Warnln("Accepting connection:", err)
continue
}
if debugNet {
l.Debugln("connect from", conn.RemoteAddr())
}
tcpConn := conn.(*net.TCPConn)
setTCPOptions(tcpConn)
tc := tls.Server(conn, tlsCfg)
err = tc.Handshake()
if err != nil {
l.Infoln("TLS handshake:", err)
tc.Close()
continue
}
conns <- tc
}
}
func dialTLS(m *model.Model, conns chan *tls.Conn, tlsCfg *tls.Config) {
delay := time.Second
for {
nextDevice:
for deviceID, deviceCfg := range cfg.Devices() {
if deviceID == myID {
continue
}
if m.ConnectedTo(deviceID) {
continue
}
var addrs []string
for _, addr := range deviceCfg.Addresses {
if addr == "dynamic" {
if discoverer != nil {
t := discoverer.Lookup(deviceID)
if len(t) == 0 {
continue
}
addrs = append(addrs, t...)
}
} else {
addrs = append(addrs, addr)
}
}
for _, addr := range addrs {
host, port, err := net.SplitHostPort(addr)
if err != nil && strings.HasPrefix(err.Error(), "missing port") {
// addr is on the form "1.2.3.4"
addr = net.JoinHostPort(addr, "22000")
} else if err == nil && port == "" {
// addr is on the form "1.2.3.4:"
addr = net.JoinHostPort(host, "22000")
}
if debugNet {
l.Debugln("dial", deviceCfg.DeviceID, addr)
}
raddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
if debugNet {
l.Debugln(err)
}
continue
}
conn, err := net.DialTCP("tcp", nil, raddr)
if err != nil {
if debugNet {
l.Debugln(err)
}
continue
}
setTCPOptions(conn)
tc := tls.Client(conn, tlsCfg)
err = tc.Handshake()
if err != nil {
l.Infoln("TLS handshake:", err)
tc.Close()
continue
}
conns <- tc
continue nextDevice
}
}
time.Sleep(delay)
delay *= 2
if maxD := time.Duration(cfg.Options().ReconnectIntervalS) * time.Second; delay > maxD {
delay = maxD
}
}
}
func setTCPOptions(conn *net.TCPConn) {
var err error
if err = conn.SetLinger(0); err != nil {
l.Infoln(err)
}
if err = conn.SetNoDelay(false); err != nil {
l.Infoln(err)
}
if err = conn.SetKeepAlivePeriod(60 * time.Second); err != nil {
l.Infoln(err)
}
if err = conn.SetKeepAlive(true); err != nil {
l.Infoln(err)
}
}
func shouldLimit(addr net.Addr) bool {
if cfg.Options().LimitBandwidthInLan {
return true
}
tcpaddr, ok := addr.(*net.TCPAddr)
if !ok {
return true
}
for _, lan := range lans {
if lan.Contains(tcpaddr.IP) {
return false
}
}
return !tcpaddr.IP.IsLoopback()
}

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
@@ -130,8 +121,10 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
getRestMux.HandleFunc("/rest/system", restGetSystem)
getRestMux.HandleFunc("/rest/upgrade", restGetUpgrade)
getRestMux.HandleFunc("/rest/version", restGetVersion)
getRestMux.HandleFunc("/rest/tree", withModel(m, restGetTree))
getRestMux.HandleFunc("/rest/stats/device", withModel(m, restGetDeviceStats))
getRestMux.HandleFunc("/rest/stats/folder", withModel(m, restGetFolderStats))
getRestMux.HandleFunc("/rest/filestatus", withModel(m, restGetFileStatus))
// Debug endpoints, not for general use
getRestMux.HandleFunc("/rest/debug/peerCompletion", withModel(m, restGetPeerCompletion))
@@ -262,6 +255,24 @@ func restGetVersion(w http.ResponseWriter, r *http.Request) {
})
}
func restGetTree(m *model.Model, w http.ResponseWriter, r *http.Request) {
qs := r.URL.Query()
folder := qs.Get("folder")
prefix := qs.Get("prefix")
dirsonly := qs.Get("dirsonly") != ""
levels, err := strconv.Atoi(qs.Get("levels"))
if err != nil {
levels = -1
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
tree := m.GlobalDirectoryTree(folder, prefix, levels, dirsonly)
json.NewEncoder(w).Encode(tree)
}
func restGetCompletion(m *model.Model, w http.ResponseWriter, r *http.Request) {
var qs = r.URL.Query()
var folder = qs.Get("folder")
@@ -302,6 +313,15 @@ func restGetModel(m *model.Model, w http.ResponseWriter, r *http.Request) {
res["state"], res["stateChanged"] = m.State(folder)
res["version"] = m.CurrentLocalVersion(folder) + m.RemoteLocalVersion(folder)
ignorePatterns, _, _ := m.GetIgnores(folder)
res["ignorePatterns"] = false
for _, line := range ignorePatterns {
if len(line) > 0 && !strings.HasPrefix(line, "//") {
res["ignorePatterns"] = true
break
}
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(res)
}
@@ -346,6 +366,27 @@ func restGetFolderStats(m *model.Model, w http.ResponseWriter, r *http.Request)
json.NewEncoder(w).Encode(res)
}
func restGetFileStatus(m *model.Model, w http.ResponseWriter, r *http.Request) {
qs := r.URL.Query()
folder := qs.Get("folder")
file := qs.Get("file")
withBlocks := qs.Get("blocks") != ""
gf, _ := m.CurrentGlobalFile(folder, file)
lf, _ := m.CurrentFolderFile(folder, file)
if !withBlocks {
gf.Blocks = nil
lf.Blocks = nil
}
av := m.Availability(folder, file)
json.NewEncoder(w).Encode(map[string]interface{}{
"global": gf,
"local": lf,
"availability": av,
})
}
func restGetConfig(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(cfg.Raw())
@@ -448,7 +489,7 @@ func restGetSystem(w http.ResponseWriter, r *http.Request) {
cpusum += p
}
cpuUsageLock.RUnlock()
res["cpuPercent"] = cpusum / 10
res["cpuPercent"] = cpusum / float64(len(cpuUsagePercent)) / float64(runtime.NumCPU())
res["pathSeparator"] = string(filepath.Separator)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
@@ -577,7 +618,7 @@ func restGetUpgrade(w http.ResponseWriter, r *http.Request) {
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), 500)
return
}
rel, err := upgrade.LatestRelease(strings.Contains(Version, "-beta"))
rel, err := upgrade.LatestRelease(Version)
if err != nil {
http.Error(w, err.Error(), 500)
return
@@ -585,7 +626,8 @@ func restGetUpgrade(w http.ResponseWriter, r *http.Request) {
res := make(map[string]interface{})
res["running"] = Version
res["latest"] = rel.Tag
res["newer"] = upgrade.CompareVersions(rel.Tag, Version) == 1
res["newer"] = upgrade.CompareVersions(rel.Tag, Version) == upgrade.Newer
res["majorNewer"] = upgrade.CompareVersions(rel.Tag, Version) == upgrade.MajorNewer
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(res)
@@ -619,14 +661,14 @@ func restGetLang(w http.ResponseWriter, r *http.Request) {
}
func restPostUpgrade(w http.ResponseWriter, r *http.Request) {
rel, err := upgrade.LatestRelease(strings.Contains(Version, "-beta"))
rel, err := upgrade.LatestRelease(Version)
if err != nil {
l.Warnln("getting latest release:", err)
http.Error(w, err.Error(), 500)
return
}
if upgrade.CompareVersions(rel.Tag, Version) == 1 {
if upgrade.CompareVersions(rel.Tag, Version) > upgrade.Equal {
err = upgrade.To(rel)
if err != nil {
l.Warnln("upgrading:", err)
@@ -643,10 +685,18 @@ func restPostUpgrade(w http.ResponseWriter, r *http.Request) {
func restPostScan(m *model.Model, w http.ResponseWriter, r *http.Request) {
qs := r.URL.Query()
folder := qs.Get("folder")
sub := qs.Get("sub")
err := m.ScanFolderSub(folder, sub)
if err != nil {
http.Error(w, err.Error(), 500)
if folder != "" {
sub := qs.Get("sub")
err := m.ScanFolderSub(folder, sub)
if err != nil {
http.Error(w, err.Error(), 500)
}
} else {
errors := m.ScanFolders()
if len(errors) > 0 {
http.Error(w, "Error scanning folders", 500)
json.NewEncoder(w).Encode(errors)
}
}
}
@@ -779,6 +829,8 @@ func mimeTypeForFile(file string) string {
return "application/x-font-ttf"
case ".woff":
return "application/x-font-woff"
case ".svg":
return "image/svg+xml"
default:
return mime.TypeByExtension(ext)
}
@@ -793,8 +845,7 @@ func toNeedSlice(fs []db.FileInfoTruncated) []map[string]interface{} {
"Modified": file.Modified,
"Version": file.Version,
"LocalVersion": file.LocalVersion,
"NumBlocks": file.NumBlocks,
"Size": db.BlocksToSize(file.NumBlocks),
"Size": file.Size(),
}
}
return output

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
//+build solaris

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
//+build !windows,!solaris

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
//+build windows

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
@@ -20,27 +11,32 @@ import (
"os"
"runtime"
"runtime/pprof"
"strconv"
"syscall"
"time"
)
func init() {
if innerProcess && os.Getenv("STHEAPPROFILE") != "" {
rate := 1
if i, err := strconv.Atoi(os.Getenv("STHEAPPROFILE")); err == nil {
rate = i
}
l.Debugln("Starting heap profiling")
go saveHeapProfiles()
go saveHeapProfiles(rate)
}
}
func saveHeapProfiles() {
runtime.MemProfileRate = 1
func saveHeapProfiles(rate int) {
runtime.MemProfileRate = rate
var memstats, prevMemstats runtime.MemStats
t0 := time.Now()
for t := range time.NewTicker(250 * time.Millisecond).C {
startms := int(t.Sub(t0).Seconds() * 1000)
name := fmt.Sprintf("heap-%05d.pprof", syscall.Getpid())
for {
runtime.ReadMemStats(&memstats)
if memstats.HeapInuse > prevMemstats.HeapInuse {
fd, err := os.Create(fmt.Sprintf("heap-%05d-%07d.pprof", syscall.Getpid(), startms))
fd, err := os.Create(name + ".tmp")
if err != nil {
panic(err)
}
@@ -52,7 +48,16 @@ func saveHeapProfiles() {
if err != nil {
panic(err)
}
_ = os.Remove(name) // Error deliberately ignored
err = os.Rename(name+".tmp", name)
if err != nil {
panic(err)
}
prevMemstats = memstats
}
time.Sleep(250 * time.Millisecond)
}
}

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
@@ -19,7 +10,6 @@ import (
"crypto/tls"
"flag"
"fmt"
"io"
"log"
"net"
"net/http"
@@ -48,6 +38,7 @@ import (
"github.com/syncthing/syncthing/internal/upgrade"
"github.com/syncthing/syncthing/internal/upnp"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/errors"
"github.com/syndtr/goleveldb/leveldb/opt"
"golang.org/x/crypto/bcrypt"
)
@@ -72,6 +63,8 @@ const (
exitUpgrading = 4
)
const bepProtocolName = "bep/1.0"
var l = logger.DefaultLogger
func init() {
@@ -113,6 +106,7 @@ var (
externalPort int
igd *upnp.IGD
cert tls.Certificate
lans []*net.IPNet
)
const (
@@ -142,38 +136,41 @@ Development Settings
The following environment variables modify syncthing's behavior in ways that
are mostly useful for developers. Use with care.
STGUIASSETS Directory to load GUI assets from. Overrides compiled in assets.
STGUIASSETS Directory to load GUI assets from. Overrides compiled in assets.
STTRACE A comma separated string of facilities to trace. The valid
facility strings are:
STTRACE A comma separated string of facilities to trace. The valid
facility strings are:
- "beacon" (the beacon package)
- "discover" (the discover package)
- "events" (the events package)
- "files" (the files package)
- "net" (the main package; connections & network messages)
- "model" (the model package)
- "scanner" (the scanner package)
- "stats" (the stats package)
- "upnp" (the upnp package)
- "xdr" (the xdr package)
- "all" (all of the above)
- "beacon" (the beacon package)
- "discover" (the discover package)
- "events" (the events package)
- "files" (the files package)
- "net" (the main package; connections & network messages)
- "model" (the model package)
- "scanner" (the scanner package)
- "stats" (the stats package)
- "upnp" (the upnp package)
- "xdr" (the xdr package)
- "all" (all of the above)
STPROFILER Set to a listen address such as "127.0.0.1:9090" to start the
profiler with HTTP access.
STPROFILER Set to a listen address such as "127.0.0.1:9090" to start the
profiler with HTTP access.
STCPUPROFILE Write a CPU profile to cpu-$pid.pprof on exit.
STCPUPROFILE Write a CPU profile to cpu-$pid.pprof on exit.
STHEAPPROFILE Write heap profiles to heap-$pid-$timestamp.pprof each time
heap usage increases.
STHEAPPROFILE Write heap profiles to heap-$pid-$timestamp.pprof each time
heap usage increases.
STPERFSTATS Write running performance statistics to perf-$pid.csv. Not
supported on Windows.
STBLOCKPROFILE Write block profiles to block-$pid-$timestamp.pprof every 20
seconds.
STNOUPGRADE Disable automatic upgrades.
STPERFSTATS Write running performance statistics to perf-$pid.csv. Not
supported on Windows.
GOMAXPROCS Set the maximum number of CPU cores to use. Defaults to all
available CPU cores.`
STNOUPGRADE Disable automatic upgrades.
GOMAXPROCS Set the maximum number of CPU cores to use. Defaults to all
available CPU cores.`
)
// Command line and environment options
@@ -327,7 +324,7 @@ func main() {
}
if doUpgrade || doUpgradeCheck {
rel, err := upgrade.LatestRelease(IsBeta)
rel, err := upgrade.LatestRelease(Version)
if err != nil {
l.Fatalln("Upgrade:", err) // exits 1
}
@@ -458,7 +455,7 @@ func syncthingMain() {
tlsCfg := &tls.Config{
Certificates: []tls.Certificate{cert},
NextProtos: []string{"bep/1.0"},
NextProtos: []string{bepProtocolName},
ClientAuth: tls.RequestClientCert,
SessionTicketsDisabled: true,
InsecureSkipVerify: true,
@@ -489,7 +486,21 @@ func syncthingMain() {
readRateLimit = ratelimit.NewBucketWithRate(float64(1000*opts.MaxRecvKbps), int64(5*1000*opts.MaxRecvKbps))
}
ldb, err := leveldb.OpenFile(filepath.Join(confDir, "index"), &opt.Options{OpenFilesCacheCapacity: 100})
if (opts.MaxRecvKbps > 0 || opts.MaxSendKbps > 0) && !opts.LimitBandwidthInLan {
lans, _ = osutil.GetLans()
networks := make([]string, 0, len(lans))
for _, lan := range lans {
networks = append(networks, lan.String())
}
l.Infoln("Local networks:", strings.Join(networks, ", "))
}
dbFile := filepath.Join(confDir, "index")
dbOpts := &opt.Options{OpenFilesCacheCapacity: 100}
ldb, err := leveldb.OpenFile(dbFile, dbOpts)
if err != nil && errors.IsCorrupted(err) {
ldb, err = leveldb.RecoverFile(dbFile, dbOpts)
}
if err != nil {
l.Fatalln("Cannot open database:", err, "- Is another copy of Syncthing already running?")
}
@@ -610,7 +621,7 @@ func syncthingMain() {
} else if IsRelease {
go autoUpgrade()
} else {
l.Infof("No automatic upgrades; %s is not a relase version.", Version)
l.Infof("No automatic upgrades; %s is not a release version.", Version)
}
}
@@ -658,7 +669,9 @@ func setupGUI(cfg *config.Wrapper, m *model.Model) {
}
if opts.StartBrowser && !noBrowser && !stRestarting {
urlOpen := fmt.Sprintf("%s://%s/", proto, net.JoinHostPort(hostOpen, strconv.Itoa(addr.Port)))
openURL(urlOpen)
// Can potentially block if the utility we are invoking doesn't
// fork, and just execs, hence keep it in it's own routine.
go openURL(urlOpen)
}
}
}
@@ -874,8 +887,10 @@ func resetFolders() {
suffix := fmt.Sprintf(".syncthing-reset-%d", time.Now().UnixNano())
for _, folder := range cfg.Folders() {
if _, err := os.Stat(folder.Path); err == nil {
l.Infof("Reset: Moving %s -> %s", folder.Path, folder.Path+suffix)
os.Rename(folder.Path, folder.Path+suffix)
base := filepath.Base(folder.Path)
dir := filepath.Dir(filepath.Join(folder.Path, ".."))
l.Infof("Reset: Moving %s -> %s", folder.Path, filepath.Join(dir, base+suffix))
os.Rename(folder.Path, filepath.Join(dir, base+suffix))
}
}
@@ -893,239 +908,6 @@ func shutdown() {
stop <- exitSuccess
}
func listenConnect(myID protocol.DeviceID, m *model.Model, tlsCfg *tls.Config) {
var conns = make(chan *tls.Conn)
// Listen
for _, addr := range cfg.Options().ListenAddress {
go listenTLS(conns, addr, tlsCfg)
}
// Connect
go dialTLS(m, conns, tlsCfg)
next:
for conn := range conns {
certs := conn.ConnectionState().PeerCertificates
if cl := len(certs); cl != 1 {
l.Infof("Got peer certificate list of length %d != 1 from %s; protocol error", cl, conn.RemoteAddr())
conn.Close()
continue
}
remoteCert := certs[0]
remoteID := protocol.NewDeviceID(remoteCert.Raw)
if remoteID == myID {
l.Infof("Connected to myself (%s) - should not happen", remoteID)
conn.Close()
continue
}
if m.ConnectedTo(remoteID) {
l.Infof("Connected to already connected device (%s)", remoteID)
conn.Close()
continue
}
for deviceID, deviceCfg := range cfg.Devices() {
if deviceID == remoteID {
// Verify the name on the certificate. By default we set it to
// "syncthing" when generating, but the user may have replaced
// the certificate and used another name.
certName := deviceCfg.CertName
if certName == "" {
certName = tlsDefaultCommonName
}
err := remoteCert.VerifyHostname(certName)
if err != nil {
// Incorrect certificate name is something the user most
// likely wants to know about, since it's an advanced
// config. Warn instead of Info.
l.Warnf("Bad certificate from %s (%v): %v", remoteID, conn.RemoteAddr(), err)
conn.Close()
continue next
}
// If rate limiting is set, we wrap the connection in a
// limiter.
wr := io.Writer(conn)
if writeRateLimit != nil {
wr = &limitedWriter{conn, writeRateLimit}
}
rd := io.Reader(conn)
if readRateLimit != nil {
rd = &limitedReader{conn, readRateLimit}
}
name := fmt.Sprintf("%s-%s", conn.LocalAddr(), conn.RemoteAddr())
protoConn := protocol.NewConnection(remoteID, rd, wr, m, name, deviceCfg.Compression)
l.Infof("Established secure connection to %s at %s", remoteID, name)
if debugNet {
l.Debugf("cipher suite %04X", conn.ConnectionState().CipherSuite)
}
events.Default.Log(events.DeviceConnected, map[string]string{
"id": remoteID.String(),
"addr": conn.RemoteAddr().String(),
})
m.AddConnection(conn, protoConn)
continue next
}
}
if !cfg.IgnoredDevice(remoteID) {
events.Default.Log(events.DeviceRejected, map[string]string{
"device": remoteID.String(),
"address": conn.RemoteAddr().String(),
})
l.Infof("Connection from %s with unknown device ID %s", conn.RemoteAddr(), remoteID)
} else {
l.Infof("Connection from %s with ignored device ID %s", conn.RemoteAddr(), remoteID)
}
conn.Close()
}
}
func listenTLS(conns chan *tls.Conn, addr string, tlsCfg *tls.Config) {
if debugNet {
l.Debugln("listening on", addr)
}
tcaddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
l.Fatalln("listen (BEP):", err)
}
listener, err := net.ListenTCP("tcp", tcaddr)
if err != nil {
l.Fatalln("listen (BEP):", err)
}
for {
conn, err := listener.Accept()
if err != nil {
l.Warnln("Accepting connection:", err)
continue
}
if debugNet {
l.Debugln("connect from", conn.RemoteAddr())
}
tcpConn := conn.(*net.TCPConn)
setTCPOptions(tcpConn)
tc := tls.Server(conn, tlsCfg)
err = tc.Handshake()
if err != nil {
l.Infoln("TLS handshake:", err)
tc.Close()
continue
}
conns <- tc
}
}
func dialTLS(m *model.Model, conns chan *tls.Conn, tlsCfg *tls.Config) {
delay := time.Second
for {
nextDevice:
for deviceID, deviceCfg := range cfg.Devices() {
if deviceID == myID {
continue
}
if m.ConnectedTo(deviceID) {
continue
}
var addrs []string
for _, addr := range deviceCfg.Addresses {
if addr == "dynamic" {
if discoverer != nil {
t := discoverer.Lookup(deviceID)
if len(t) == 0 {
continue
}
addrs = append(addrs, t...)
}
} else {
addrs = append(addrs, addr)
}
}
for _, addr := range addrs {
host, port, err := net.SplitHostPort(addr)
if err != nil && strings.HasPrefix(err.Error(), "missing port") {
// addr is on the form "1.2.3.4"
addr = net.JoinHostPort(addr, "22000")
} else if err == nil && port == "" {
// addr is on the form "1.2.3.4:"
addr = net.JoinHostPort(host, "22000")
}
if debugNet {
l.Debugln("dial", deviceCfg.DeviceID, addr)
}
raddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
if debugNet {
l.Debugln(err)
}
continue
}
conn, err := net.DialTCP("tcp", nil, raddr)
if err != nil {
if debugNet {
l.Debugln(err)
}
continue
}
setTCPOptions(conn)
tc := tls.Client(conn, tlsCfg)
err = tc.Handshake()
if err != nil {
l.Infoln("TLS handshake:", err)
tc.Close()
continue
}
conns <- tc
continue nextDevice
}
}
time.Sleep(delay)
delay *= 2
if maxD := time.Duration(cfg.Options().ReconnectIntervalS) * time.Second; delay > maxD {
delay = maxD
}
}
}
func setTCPOptions(conn *net.TCPConn) {
var err error
if err = conn.SetLinger(0); err != nil {
l.Infoln(err)
}
if err = conn.SetNoDelay(false); err != nil {
l.Infoln(err)
}
if err = conn.SetKeepAlivePeriod(60 * time.Second); err != nil {
l.Infoln(err)
}
if err = conn.SetKeepAlive(true); err != nil {
l.Infoln(err)
}
}
func discovery(extPort int) *discover.Discoverer {
opts := cfg.Options()
disc := discover.NewDiscoverer(myID, opts.ListenAddress)
@@ -1162,7 +944,10 @@ func ensureDir(dir string, mode int) {
func getDefaultConfDir() (string, error) {
switch runtime.GOOS {
case "windows":
return filepath.Join(os.Getenv("LocalAppData"), "Syncthing"), nil
if p := os.Getenv("LocalAppData"); p != "" {
return filepath.Join(p, "Syncthing"), nil
}
return filepath.Join(os.Getenv("AppData"), "Syncthing"), nil
case "darwin":
return osutil.ExpandTilde("~/Library/Application Support/Syncthing")
@@ -1272,7 +1057,7 @@ func autoUpgrade() {
case <-timer.C:
}
rel, err := upgrade.LatestRelease(IsBeta)
rel, err := upgrade.LatestRelease(Version)
if err == upgrade.ErrUpgradeUnsupported {
events.Default.Unsubscribe(sub)
return

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
@@ -22,7 +13,7 @@ import (
"strings"
)
func memorySize() (uint64, error) {
func memorySize() (int64, error) {
cmd := exec.Command("sysctl", "hw.memsize")
out, err := cmd.Output()
if err != nil {
@@ -32,7 +23,7 @@ func memorySize() (uint64, error) {
if len(fs) != 2 {
return 0, errors.New("sysctl parse error")
}
bytes, err := strconv.ParseUint(fs[1], 10, 64)
bytes, err := strconv.ParseInt(fs[1], 10, 64)
if err != nil {
return 0, err
}

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
@@ -23,7 +14,7 @@ import (
"strings"
)
func memorySize() (uint64, error) {
func memorySize() (int64, error) {
f, err := os.Open("/proc/meminfo")
if err != nil {
return 0, err
@@ -40,7 +31,7 @@ func memorySize() (uint64, error) {
return 0, errors.New("/proc/meminfo parse error 2")
}
kb, err := strconv.ParseUint(fs[1], 10, 64)
kb, err := strconv.ParseInt(fs[1], 10, 64)
if err != nil {
return 0, err
}

View File

@@ -0,0 +1,31 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
import (
"errors"
"os/exec"
"strconv"
"strings"
)
func memorySize() (int64, error) {
cmd := exec.Command("/sbin/sysctl", "hw.physmem64")
out, err := cmd.Output()
if err != nil {
return 0, err
}
fs := strings.Fields(string(out))
if len(fs) != 3 {
return 0, errors.New("sysctl parse error")
}
bytes, err := strconv.ParseInt(fs[2], 10, 64)
if err != nil {
return 0, err
}
return bytes, nil
}

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build solaris
@@ -22,14 +13,14 @@ import (
"strconv"
)
func memorySize() (uint64, error) {
func memorySize() (int64, error) {
cmd := exec.Command("prtconf", "-m")
out, err := cmd.CombinedOutput()
if err != nil {
return 0, err
}
mb, err := strconv.ParseUint(string(out), 10, 64)
mb, err := strconv.ParseInt(string(out), 10, 64)
if err != nil {
return 0, err
}

View File

@@ -1,24 +1,15 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build freebsd openbsd
// +build freebsd openbsd dragonfly
package main
import "errors"
func memorySize() (uint64, error) {
func memorySize() (int64, error) {
return 0, errors.New("not implemented")
}

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main
@@ -26,7 +17,7 @@ var (
globalMemoryStatusEx, _ = syscall.GetProcAddress(kernel32, "GlobalMemoryStatusEx")
)
func memorySize() (uint64, error) {
func memorySize() (int64, error) {
var memoryStatusEx [64]byte
binary.LittleEndian.PutUint32(memoryStatusEx[:], 64)
p := uintptr(unsafe.Pointer(&memoryStatusEx[0]))
@@ -36,5 +27,5 @@ func memorySize() (uint64, error) {
return 0, callErr
}
return binary.LittleEndian.Uint64(memoryStatusEx[8:]), nil
return int64(binary.LittleEndian.Uint64(memoryStatusEx[8:])), nil
}

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build !windows

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build windows

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build !solaris,!windows
@@ -43,7 +34,7 @@ func savePerfStats(file string) {
var prevTime int64
var rusage syscall.Rusage
var memstats runtime.MemStats
var prevIn, prevOut uint64
var prevIn, prevOut int64
t0 := time.Now()
for t := range time.NewTicker(250 * time.Millisecond).C {

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package main

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build ignore

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build ignore

View File

@@ -1,17 +1,8 @@
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build ignore

View File

@@ -1,75 +0,0 @@
FROM debian:squeeze
MAINTAINER Jakob Borg <jakob@nym.se>
ENV GOLANG_VERSION 1.4
# SCMs for "go get", gcc for cgo
RUN apt-get update && apt-get install -y \
ca-certificates curl gcc libc6-dev make \
bzr git mercurial unzip patch \
--no-install-recommends \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Get the binary dist of Go to be able to bootstrap gonative.
RUN curl -sSL https://golang.org/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz \
| tar -v -C /usr/local -xz
ENV PATH /usr/local/go/bin:$PATH
ENV GOPATH /go
ENV GO386 387
ENV GOARM 5
ENV PATH /go/bin:$PATH
RUN mkdir /go
WORKDIR /go
# Use gonative to install native Go for most arch/OS combos
RUN go get github.com/calmh/gonative \
&& cd /usr/local \
&& rm -rf go \
&& gonative -version $GOLANG_VERSION
# Rebuild the special and missing versions, using patches as appropriate
RUN mkdir /tmp/patches
ADD *.patch /tmp/patches/
RUN bash -xec '\
cd /usr/local/go ; \
for patch in /tmp/patches/*.patch ; do \
patch -p0 < "$patch" ; \
done \
'
RUN bash -xec '\
cd /usr/local/go/src; \
for platform in linux/386 freebsd/386 windows/386 linux/arm openbsd/amd64 openbsd/386; do \
GOOS=${platform%/*} \
GOARCH=${platform##*/} \
CGO_ENABLED=0 \
./make.bash --no-clean 2>&1; \
done \
&& ./make.bash --no-clean \
'
# Install packages needed for test coverage
RUN go get github.com/tools/godep \
&& go get golang.org/x/tools/cmd/cover \
&& go get github.com/axw/gocov/gocov \
&& go get github.com/AlekSi/gocov-xml
# Install tools "go vet" and "golint"
RUN go get golang.org/x/tools/cmd/vet \
&& go get github.com/golang/lint/golint
# Build standard library for race
RUN go install -race std
# Random build users needs to be able to create stuff in /go
RUN chmod -R 777 /go/bin /go/pkg /go/src

View File

@@ -1,29 +0,0 @@
Docker Build
============
Official builds are produced using a Docker image specified by the
Dockerfile in this directory. The following commands exactly reproduce
the official build process.
Create an image called `syncthing/build` with the build environment.
```
./build.sh docker-init
```
> This is a Debian based image containing the latest stable version of
> Go set up for cross compilation. The cross compilation uses the
> dynamically linked standard libraries and SSE instructions for amd64
> builds, but static linking and minimal instruction set for the 386 and
> arm builds. The command should be run in the main repo directory, as a
> user with permission to perform Docker operations.
Build the full set of supported binaries.
```
./build.sh docker-all
```
> This uses a temporary container with the image from above and a volume
> mapped to the directory containing the source. Tests are run and
> binary packages created.

View File

@@ -1,22 +0,0 @@
--- src/syscall/route_openbsd.go.orig Fri Jul 25 23:38:47 2014
+++ src/syscall/route_openbsd.go Fri Jul 25 23:39:20 2014
@@ -12,16 +12,16 @@ func (any *anyMessage) toRoutingMessage(b []byte) Rout
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
- return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
+ return &RouteMessage{Header: p.Header, Data: b[p.Header.Hdrlen:any.Msglen]}
case RTM_IFINFO:
p := (*InterfaceMessage)(unsafe.Pointer(any))
- return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+ return &InterfaceMessage{Header: p.Header, Data: b[p.Header.Hdrlen:any.Msglen]}
case RTM_IFANNOUNCE:
p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
return &InterfaceAnnounceMessage{Header: p.Header}
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
- return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
+ return &InterfaceAddrMessage{Header: p.Header, Data: b[p.Header.Hdrlen:any.Msglen]}
}
return nil
}

View File

@@ -9,7 +9,8 @@ other platforms also using runit.
recommended to place it in a directory writeable by the running user
so that automatic upgrades work.
3. Copy the edited `run` file to `/etc/service/syncthing/run`.
3. Copy this directory (containing the edited `run` file and `log` folder) to
`/etc/service/syncthing`.
Log output is sent to syslogd.

4
etc/linux-runit/log/run Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
exec logger -t syncthing

View File

@@ -4,5 +4,6 @@ export USERNAME=jb
export HOME="/home/$USERNAME"
export SYNCTHING="$HOME/bin/syncthing"
setuidgid "$USERNAME" "$SYNCTHING" -logflags 0 2>&1 | logger -t syncthing
exec 2>&1
exec chpst -u "$USERNAME" "$SYNCTHING" -logflags 0

View File

@@ -1,14 +1,16 @@
[Unit]
Description=Syncthing service for %i
Description=Syncthing - Open Source Continuous File Synchronization for %I
Documentation=https://github.com/syncthing/syncthing/wiki
After=network.target
[Service]
User=%i
Environment=STARGS=
EnvironmentFile=-/etc/default/syncthing
Environment=STNORESTART=yes
ExecStart=/usr/bin/syncthing ${STARGS}
ExecStart=/usr/bin/syncthing -no-browser -logflags=0
Restart=on-failure
RestartPreventExitStatus=1
SuccessExitStatus=2
RestartForceExitStatus=3 4
[Install]
WantedBy=multi-user.target

View File

@@ -1,12 +1,15 @@
[Unit]
Description=Syncthing service
Description=Syncthing - Open Source Continuous File Synchronization
Documentation=https://github.com/syncthing/syncthing/wiki
After=network.target
[Service]
Environment=STARGS=
EnvironmentFile=-%h/.config/syncthing/environment
Environment=STNORESTART=yes
ExecStart=/usr/bin/syncthing ${STARGS}
ExecStart=/usr/bin/syncthing -no-browser -logflags=0
Restart=on-failure
RestartPreventExitStatus=1
SuccessExitStatus=2
RestartForceExitStatus=3 4
[Install]
WantedBy=cmdline.target
WantedBy=default.target

13
etc/windows/ReadMe.txt Normal file
View File

@@ -0,0 +1,13 @@
A first pass at an install script for SyncThing as a Windows Service
Script uses NSIS http://nsis.sourceforge.net/Download
Requires the NSIS Simple Service Plugin http://nsis.sourceforge.net/NSIS_Simple_Service_Plugin
And uses the Windows Service Wrapper https://github.com/kohsuke/winsw
To build the setup file:
1. Install NSIS, download the Simple Service Plugin DLL into the NSIS plugin folder
2. Create a folder (referenced by the $SOURCEPATH variable in the .nsi file) with all the syncthing output in it (exe file, licences, etc)
3. Download winsw.exe from https://github.com/kohsuke/winsw/releases, rename it to syncthingservice.exe and save that in $SOURCEPATH
4. Put syncthingservice.xml in there too
5. Compile SyncthingSetup.nsi using NSIS

View File

@@ -0,0 +1,116 @@
;--------------------------------
;Include Modern UI
!include "MUI2.nsh"
;--------------------------------
;General
;Name and file
!define SOURCEPATH "C:\SourceCode\SyncThing\Binaries"
Name "SyncThing Windows Service Install"
OutFile "SyncThingSetup.exe"
;Default installation folder
InstallDir "$PROGRAMFILES\SyncThing"
;Get installation folder from registry if available
InstallDirRegKey HKCU "Software\SyncThing" ""
;Request application privileges for Windows Vista
RequestExecutionLevel admin
;--------------------------------
;Interface Settings
!define MUI_ABORTWARNING
;--------------------------------
;Pages
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
;--------------------------------
;Languages
!insertmacro MUI_LANGUAGE "English"
;--------------------------------
;Installer Sections
Section "SyncThing" SecSyncThing
SectionIn RO
SetOutPath "$INSTDIR"
IfFileExists syncthingservice.exe 0 +2
SimpleSC::StopService "SyncThing" 1 30
File /r "${SOURCEPATH}\syncthing.exe"
File /r "${SOURCEPATH}\syncthing.exe.md5"
File /r "${SOURCEPATH}\AUTHORS.txt"
File /r "${SOURCEPATH}\LICENSE.txt"
File /r "${SOURCEPATH}\README.txt"
File /r "${SOURCEPATH}\FAQ.pdf"
File /r "${SOURCEPATH}\Getting-Started.pdf"
;Store installation folder
WriteRegStr HKCU "Software\SyncThing" "" $INSTDIR
;Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
SectionEnd
Section "Command Line Interface" SecSyncThingCLI
SetOutPath "$INSTDIR"
File /r "${SOURCEPATH}\syncthing-cli.exe"
SectionEnd
Section "Windows Service" SecSyncThingService
SetOutPath "$INSTDIR"
File /r "${SOURCEPATH}\syncthingservice.exe"
File /r "${SOURCEPATH}\syncthingservice.xml"
ExecWait 'syncthingservice.exe install'
ExecWait 'syncthingservice.exe start'
SectionEnd
;--------------------------------
;Descriptions
;Language strings
LangString DESC_SecSyncThing ${LANG_ENGLISH} "SyncThing"
LangString DESC_SecSyncThingCLI ${LANG_ENGLISH} "Command Line Interface"
LangString DESC_SecSyncThingService ${LANG_ENGLISH} "Windows Service"
;Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SecSyncThing} $(DESC_SecSyncThing)
!insertmacro MUI_DESCRIPTION_TEXT ${SecSyncThingCLI} $(DESC_SecSyncThingCLI)
!insertmacro MUI_DESCRIPTION_TEXT ${SecSyncThingService} $(DESC_SecSyncThingService)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
;--------------------------------
;Uninstaller Section
Section "Uninstall"
Delete "$INSTDIR\Uninstall.exe"
RMDir "$INSTDIR"
DeleteRegKey /ifempty HKCU "Software\SyncThing"
SectionEnd

View File

@@ -0,0 +1,8 @@
<service>
<id>Syncthing</id>
<name>Syncthing</name>
<description>This service runs Syncthing</description>
<executable>syncthing.exe</executable>
<arguments>-home .\ServiceHome -no-console -no-browser</arguments>
<logmode>rotate</logmode>
</service>

View File

@@ -1,18 +1,10 @@
/*
// Copyright (C) 2014 The Syncthing Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
*/
body {
@@ -216,4 +208,4 @@ ul.three-columns li, ul.two-columns li {
.navbar-fixed-bottom {
position: static;
}
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,88 +1,93 @@
{
"API Key": "Ключ API",
"About": "Аб праграме",
"Add": "Add",
"Add": "Дадаць",
"Add Device": "Дадаць прыладу",
"Add Folder": "Дадаць каталёг",
"Add new folder?": "Add new folder?",
"Add new folder?": "Дадаць новы каталёг ?",
"Address": "Адрас",
"Addresses": "Адрасы",
"All Data": "All Data",
"Allow Anonymous Usage Reporting?": "Allow Anonymous Usage Reporting?",
"Anonymous Usage Reporting": "Anonymous Usage Reporting",
"Any devices configured on an introducer device will be added to this device as well.": "Any devices configured on an introducer device will be added to this device as well.",
"Automatic upgrades": "Automatic upgrades",
"Bugs": "Bugs",
"CPU Utilization": "CPU Utilization",
"Changelog": "Changelog",
"Close": "Close",
"Bugs": "Памылкі",
"CPU Utilization": "Выкарыстаньне працэсара",
"Changelog": "Сьпіс зьменаў",
"Close": "Зачыніць",
"Comment, when used at the start of a line": "Comment, when used at the start of a line",
"Compression is recommended in most setups.": "Compression is recommended in most setups.",
"Compression": "Compression",
"Compression is recommended in most setups.": "Сьцісканьне рэкамэндавана ў большасьці выпадкаў.",
"Connection Error": "Connection Error",
"Copied from elsewhere": "Copied from elsewhere",
"Copied from original": "Copied from original",
"Copyright © 2014 Jakob Borg and the following Contributors:": "Copyright © 2014 Jakob Borg and the following Contributors:",
"Delete": "Delete",
"Device ID": "Device ID",
"Device Identification": "Device Identification",
"Device Name": "Device Name",
"Delete": "Выдаліць",
"Device ID": "ID прылады",
"Device Identification": "Ідэнтыфікацыя прылады",
"Device Name": "Назва прылады",
"Device {%device%} ({%address%}) wants to connect. Add new device?": "Device {{device}} ({{address}}) wants to connect. Add new device?",
"Devices": "Devices",
"Disconnected": "Disconnected",
"Documentation": "Documentation",
"Download Rate": "Download Rate",
"Devices": "Прылады",
"Disconnected": "Адлучана",
"Documentation": "Дакумэнтацыя",
"Download Rate": "Хуткасьць спампоўваньня",
"Downloaded": "Downloaded",
"Downloading": "Downloading",
"Edit": "Edit",
"Edit Device": "Edit Device",
"Edit Folder": "Edit Folder",
"Edit": "Зьмяніць",
"Edit Device": "Зьмяніць прыладу",
"Edit Folder": "Зьмяніць каталёг",
"Editing": "Editing",
"Enable UPnP": "Enable UPnP",
"Enter comma separated \"ip:port\" addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated \"ip:port\" addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Enter ignore patterns, one per line.",
"Error": "Error",
"File Versioning": "File Versioning",
"File Versioning": "Вэрсіі файлаў",
"File permission bits are ignored when looking for changes. Use on FAT filesystems.": "File permission bits are ignored when looking for changes. Use on FAT filesystems.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by syncthing.": "Files are moved to date stamped versions in a .stversions folder when replaced or deleted by 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.": "Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.",
"Folder ID": "Folder ID",
"Folder ID": "ID каталёгу",
"Folder Master": "Folder Master",
"Folder Path": "Folder Path",
"Folders": "Folders",
"Folder Path": "Шлях каталёгу",
"Folders": "Каталёгі",
"GUI Authentication Password": "GUI Authentication Password",
"GUI Authentication User": "GUI Authentication User",
"GUI Listen Addresses": "GUI Listen Addresses",
"Generate": "Generate",
"Global Discovery": "Global Discovery",
"Global Discovery Server": "Global Discovery Server",
"Global State": "Global State",
"Generate": "Сгенераваць",
"Global Discovery": "Глябальнае вызначэньне",
"Global Discovery Server": "Сэрвер глябальнага вызначэньня",
"Global State": "Глябальны стан",
"Idle": "Idle",
"Ignore": "Ignore",
"Ignore Patterns": "Ignore Patterns",
"Ignore Permissions": "Ignore Permissions",
"Ignore Patterns": "Ігнараваць шаблёны",
"Ignore Permissions": "Ігнараваць правы",
"Incoming Rate Limit (KiB/s)": "Incoming Rate Limit (KiB/s)",
"Introducer": "Introducer",
"Inversion of the given condition (i.e. do not exclude)": "Inversion of the given condition (i.e. do not exclude)",
"Keep Versions": "Keep Versions",
"Last File Received": "Last File Received",
"Last File Synced": "Last File Synced",
"Last seen": "Last seen",
"Keep Versions": "Трымаць вэрсій",
"Last File Received": "Апошні атрыманы файл",
"Last File Synced": "Апошні сынхранізаваны файл",
"Last seen": "Апошні раз бачылі",
"Later": "Later",
"Latest Release": "Latest Release",
"Local Discovery": "Local Discovery",
"Local State": "Local State",
"Local Discovery": "Лякальнае вызначэньне",
"Local State": "Лякальны стан",
"Maximum Age": "Maximum Age",
"Metadata Only": "Metadata Only",
"Move to top of queue": "Move to top of queue",
"Multi level wildcard (matches multiple directory levels)": "Multi level wildcard (matches multiple directory levels)",
"Never": "Never",
"Never": "Ніколі",
"New Device": "New Device",
"New Folder": "New Folder",
"No": "No",
"No File Versioning": "No File Versioning",
"No": "Не",
"No File Versioning": "Не захоўваць вэрсіі",
"Notice": "Notice",
"OK": "OK",
"OK": "Добра",
"Off": "Off",
"Offline": "Offline",
"Online": "Online",
"Out Of Sync": "Out Of Sync",
"Out of Sync Items": "Out of Sync Items",
"Out Of Sync": "Несынхранізавана",
"Out of Sync Items": "Несынхранізаваныя складнікі",
"Outgoing Rate Limit (KiB/s)": "Outgoing Rate Limit (KiB/s)",
"Override Changes": "Override Changes",
"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 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",
@@ -91,44 +96,45 @@
"Preview": "Preview",
"Preview Usage Report": "Preview Usage Report",
"Quick guide to supported patterns": "Quick guide to supported patterns",
"RAM Utilization": "RAM Utilization",
"Rescan": "Rescan",
"Rescan Interval": "Rescan Interval",
"Restart": "Restart",
"Restart Needed": "Restart Needed",
"Restarting": "Restarting",
"RAM Utilization": "Выкарыстаньне памяці",
"Rescan": "Перачытаць",
"Rescan All": "Rescan All",
"Rescan Interval": "Інтэрвал перачытваньня",
"Restart": "Перастартаваць",
"Restart Needed": "Патрэбна перастартоўваньне",
"Restarting": "Перастартоўваньне",
"Reused": "Reused",
"Save": "Save",
"Scanning": "Scanning",
"Select the devices to share this folder with.": "Select the devices to share this folder with.",
"Select the folders to share with this device.": "Select the folders to share with this device.",
"Settings": "Settings",
"Share": "Share",
"Save": "Захаваць",
"Scanning": "Скануецца",
"Select the devices to share this folder with.": "Пазначце прылады зь якімі трэба абагуліць гэты каталёг.",
"Select the folders to share with this device.": "Пазначце каталёгі якія трэба абагуліць з гэтай прыладай.",
"Settings": "Налады",
"Share": "Абагуліць",
"Share Folder": "Share Folder",
"Share Folders With Device": "Share Folders With Device",
"Share With Devices": "Share With Devices",
"Share this folder?": "Share this folder?",
"Shared With": "Shared With",
"Share With Devices": "Абагуліць з прыладамі",
"Share this folder?": "Абагуліць гэты каталёг ?",
"Shared With": "Абагульны з",
"Short identifier for the folder. Must be the same on all cluster devices.": "Short identifier for the folder. Must be the same on all cluster devices.",
"Show ID": "Show ID",
"Show ID": "Паказаць ID",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
"Shutdown": "Shutdown",
"Shutdown Complete": "Shutdown Complete",
"Simple File Versioning": "Simple File Versioning",
"Shutdown": "Выключыць",
"Shutdown Complete": "Выключэньне завершанае",
"Simple File Versioning": "Простае захоўваньне вэрсій",
"Single level wildcard (matches within a directory only)": "Single level wildcard (matches within a directory only)",
"Source Code": "Source Code",
"Staggered File Versioning": "Staggered File Versioning",
"Source Code": "Зыходнікі",
"Staggered File Versioning": "Адаптыўнае захоўваньне вэрсій",
"Start Browser": "Start Browser",
"Stopped": "Stopped",
"Support": "Support",
"Support / Forum": "Support / Forum",
"Support": "Падтрымка",
"Support / Forum": "Падтрымка / Форум",
"Sync Protocol Listen Addresses": "Sync Protocol Listen Addresses",
"Synchronization": "Synchronization",
"Syncing": "Syncing",
"Synchronization": "Сынхранізацыя",
"Syncing": "Сынхранізуецца",
"Syncthing has been shut down.": "Syncthing has been shut down.",
"Syncthing includes the following software or portions thereof:": "Syncthing includes the following software or portions thereof:",
"Syncthing is restarting.": "Syncthing is restarting.",
"Syncthing is restarting.": "Syncthing перастартоўвае.",
"Syncthing is upgrading.": "Syncthing is upgrading.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing seems to be experiencing a problem processing your request. Please reload your browser or restart Syncthing if the problem persists.",
@@ -145,27 +151,27 @@
"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.": "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.",
"The maximum age must be a number and cannot be blank.": "The maximum age must be a number and cannot be blank.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "The maximum time to keep a version (in days, set to 0 to keep versions forever).",
"The number of old versions to keep, per file.": "The number of old versions to keep, per file.",
"The number of old versions to keep, per file.": "Колькі старых вэрсій трымаць, для кожнага файлу.",
"The number of versions must be a number and cannot be blank.": "The number of versions must be a number and cannot be blank.",
"The rescan interval must be a non-negative number of seconds.": "The rescan interval must be a non-negative number of seconds.",
"The rescan interval must be at least 5 seconds.": "The rescan interval must be at least 5 seconds.",
"Unknown": "Unknown",
"Unshared": "Unshared",
"Unused": "Unused",
"Up to Date": "Up to Date",
"Up to Date": "Найноўшае",
"Upgrade To {%version%}": "Upgrade To {{version}}",
"Upgrading": "Upgrading",
"Upload Rate": "Upload Rate",
"Use Compression": "Use Compression",
"Upgrading": "Абнаўленьне",
"Upload Rate": "Хуткасьць запампоўваньня",
"Use Compression": "Выкарыстоўваць сьцісканьне",
"Use HTTPS for GUI": "Use HTTPS for GUI",
"Version": "Version",
"Version": "Вэрсія",
"Versions Path": "Versions Path",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "When adding a new device, keep in mind that this device must be added on the other side too.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.",
"Yes": "Yes",
"Yes": "Так",
"You must keep at least one version.": "You must keep at least one version.",
"full documentation": "full documentation",
"items": "items",
"items": "складнікаў",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} wants to share folder \"{{folder}}\"."
}

View File

@@ -1,21 +1,23 @@
{
"API Key": "API Ключ",
"About": "За Програмата",
"Add": "Add",
"Add": "Добави",
"Add Device": "Добави устройство",
"Add Folder": "Добави папка",
"Add new folder?": "Add new folder?",
"Add new folder?": "Добави нова папка?",
"Address": "Адрес",
"Addresses": "Адреси",
"All Data": "Всички данни",
"Allow Anonymous Usage Reporting?": "Разреши анонимен доклад за ползване на програмата?",
"Anonymous Usage Reporting": "Анонимен Доклад",
"Any devices configured on an introducer device will be added to this device as well.": "Устройства настроени на introducer компютъра също ще бъдат добавени към този компютър.",
"Automatic upgrades": "Автоматични ъпдейти",
"Bugs": "Бъгове",
"CPU Utilization": "Натоварване на Процесора",
"Changelog": "Changelog",
"Changelog": "Сипъск с промени",
"Close": "Затвори",
"Comment, when used at the start of a line": "Коментар, използван в началото на реда",
"Compression": "Компресия",
"Compression is recommended in most setups.": "Компресията е препоръчителна в повечето конфигурации.",
"Connection Error": "Грешка при Свързването",
"Copied from elsewhere": "Копиране от някъде другаде",
@@ -25,8 +27,8 @@
"Device ID": "Идентификатор на устройство",
"Device Identification": "Идентификация на устройство",
"Device Name": "Име на устройство",
"Device {%device%} ({%address%}) wants to connect. Add new device?": "Device {{device}} ({{address}}) wants to connect. Add new device?",
"Devices": "Devices",
"Device {%device%} ({%address%}) wants to connect. Add new device?": "Устройство {{device}} ({{address}}) желае да се свърже. Добави ново устройство?",
"Devices": "Устройства",
"Disconnected": "Прекрати Връзката",
"Documentation": "Документация",
"Download Rate": "Скорост на Теглене",
@@ -56,33 +58,36 @@
"Global Discovery Server": "Сървър за Глобално Откриване",
"Global State": "Глобално състояние",
"Idle": "Без Работа",
"Ignore": "Ignore",
"Ignore": "Игнорирай",
"Ignore Patterns": "Шаблони за Игнориране",
"Ignore Permissions": "Игнорирай Права за Достъп",
"Incoming Rate Limit (KiB/s)": "Входящ Лимит на Скоростта (KiB/s)",
"Introducer": "Introducer",
"Inversion of the given condition (i.e. do not exclude)": "Обратното на даденото условие (пр. не изключвай)",
"Keep Versions": "Пази Версии",
"Last File Received": "Last File Received",
"Last File Received": "Последния получен файл",
"Last File Synced": "Последния синхронизиран файл",
"Last seen": "Последно видян",
"Later": "Later",
"Later": "По-късно",
"Latest Release": "Най-новата Версия",
"Local Discovery": "Локално Откриване",
"Local State": "Локално състояние",
"Maximum Age": "Максимална Възраст",
"Metadata Only": "Само мета информация",
"Move to top of queue": "Премести в началото на опашката",
"Multi level wildcard (matches multiple directory levels)": "Маска на много нива (покрива папки с много нива)",
"Never": "Никога",
"New Device": "New Device",
"New Folder": "New Folder",
"New Device": "Ново устройство",
"New Folder": "Нова папка",
"No": "Не",
"No File Versioning": "Няма Файлови Версии",
"Notice": "Известие",
"OK": "ОК",
"Off": "Изключено",
"Offline": "Не е на линия",
"Online": "На линия",
"Out Of Sync": "Не Синхронизиран",
"Out of Sync Items": "Out of Sync Items",
"Out of Sync Items": "Несинхронизирани елементи",
"Outgoing Rate Limit (KiB/s)": "Лимит на Изходящата Скорост (KiB/s)",
"Override Changes": "Замени Промените",
"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": "Пътят до папката на този компютър. Ще бъде създадена ако не съществува. Символът тилда (~) може да бъде използван като заместител на",
@@ -93,6 +98,7 @@
"Quick guide to supported patterns": "Бърз наръчник към поддържаните шаблони",
"RAM Utilization": "RAM Натоварване",
"Rescan": "Повторно Сканиране",
"Rescan All": "Пълно повторно сканиране",
"Rescan Interval": "Интервал за Повторно Сканиране",
"Restart": "Рестартирай",
"Restart Needed": "Изискава се Рестартиране",
@@ -103,35 +109,35 @@
"Select the devices to share this folder with.": "Избери устройствата, с които да споделиш тази папка.",
"Select the folders to share with this device.": "Изберете папките за споделяне с това устройство.",
"Settings": "Настройки",
"Share": "Share",
"Share Folder": "Share Folder",
"Share": "Сподели",
"Share Folder": "Сподели папка",
"Share Folders With Device": "Сподели папки с това устройство",
"Share With Devices": "Сподели с устройства",
"Share this folder?": "Share this folder?",
"Share this folder?": "Сподели тази папка?",
"Shared With": "Споделена със",
"Short identifier for the folder. Must be the same on all cluster devices.": "Кратък идентификатор на папката. Трябва да бъде същият на всички компютри.",
"Show ID": "Покажи Идентификатора",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Покажи вместо идентификатор на устройството в статус на клъстъра. Ще бъде предлагано на други комютри като име по подразбиране.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Покажи вместо идентификатор на устройството в статус на клъстъра. Ще бъде обновено с името по подразбиране изпратено от другия компютър.",
"Shutdown": "Спри Програмата",
"Shutdown Complete": "Shutdown Complete",
"Shutdown Complete": "Спирането завършено",
"Simple File Versioning": "Опростени Файлови Версии",
"Single level wildcard (matches within a directory only)": "Маска на едно ниво (покрива само в папка)",
"Source Code": "Сорс Код",
"Staggered File Versioning": "Наслагващи се Файлови Версии",
"Start Browser": "Стартирай Браузъра",
"Stopped": "Спряна",
"Support": "Support",
"Support": "Помощ",
"Support / Forum": "Помощ / Форум",
"Sync Protocol Listen Addresses": "Адрес за слушане на синхронизиращия протокол",
"Synchronization": "Синхронизация",
"Syncing": "Синхронизиране",
"Syncthing has been shut down.": "Syncthing е спрян.",
"Syncthing includes the following software or portions thereof:": "Syncthing включва следният софтуер пълно или частично:",
"Syncthing is restarting.": "Syncthing се рестартирва",
"Syncthing is restarting.": "Syncthing се рестартира",
"Syncthing is upgrading.": "Syncthing се обновява.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing изглежда не е включен, или има проблем с интерент връзката. Повторен опит...",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing seems to be experiencing a problem processing your request. Please reload your browser or restart Syncthing if the problem persists.",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing има проблем при обработването на заявката. Моля, презаредете браузъра или рестартирайте Syncthing ако проблемът продължи.",
"The aggregated statistics are publicly available at {%url%}.": "Сумарната статистика е публично достъпна на {{url}}.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Конфигурацията е запазена, но не е активирана. Syncthing трябва да рестартира, за да се активира новата конфигурация.",
"The device ID cannot be blank.": "Полето идентификатор на устройство не може да бъде празно.",
@@ -167,5 +173,5 @@
"You must keep at least one version.": "Трябва да пазиш поне една версия.",
"full documentation": "пълна документация",
"items": "артикула",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} wants to share folder \"{{folder}}\"."
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} желае да сподели папка \"{{folder}}\"."
}

View File

@@ -7,6 +7,7 @@
"Add new folder?": "Afegir nova carpeta?",
"Address": "Adreça",
"Addresses": "Adreces",
"All Data": "All Data",
"Allow Anonymous Usage Reporting?": "Permetre l'enviament anònim d'informes d'ús?",
"Anonymous Usage Reporting": "Informe anònim d'ús",
"Any devices configured on an introducer device will be added to this device as well.": "Qualsevol dispositiu configurat com a dispositiu introductor s'afegirà a aquest dispositiu tambè.",
@@ -16,6 +17,7 @@
"Changelog": "Historial de canvis",
"Close": "Tancar",
"Comment, when used at the start of a line": "Comentari quan és usat al principi d'una línia",
"Compression": "Compression",
"Compression is recommended in most setups.": "Generalment, la compressió és recomanada.",
"Connection Error": "Error de connexió",
"Copied from elsewhere": "Copiat d'un altre lloc",
@@ -71,6 +73,8 @@
"Local Discovery": "Descobriment Local",
"Local State": "Estat local",
"Maximum Age": "Antiguitat Màxima",
"Metadata Only": "Metadata Only",
"Move to top of queue": "Move to top of queue",
"Multi level wildcard (matches multiple directory levels)": "Caràcter comodí de nivell múltiple (aparella en carpetes de nivells múltiples)",
"Never": "Mai",
"New Device": "Nou dispositiu",
@@ -79,6 +83,7 @@
"No File Versioning": "Sense Versionat de Fitxer",
"Notice": "Avís",
"OK": "OK",
"Off": "Off",
"Offline": "Desconnectat",
"Online": "Connectat",
"Out Of Sync": "Fora de la Sincronització",
@@ -93,6 +98,7 @@
"Quick guide to supported patterns": "Guia ràpida per als possibles patrons",
"RAM Utilization": "Utilització de la RAM",
"Rescan": "Re-escanejar",
"Rescan All": "Rescan All",
"Rescan Interval": "Interval de re-escaneig",
"Restart": "Reiniciar",
"Restart Needed": "És Necessari Reiniciar",

View File

@@ -7,15 +7,17 @@
"Add new folder?": "Přidat nový adresář?",
"Address": "Adresa",
"Addresses": "Adresy",
"All Data": "Všechna data",
"Allow Anonymous Usage Reporting?": "Povolit anonymní hlášení o používání?",
"Anonymous Usage Reporting": "Anonymní hlášení o používání",
"Any devices configured on an introducer device will be added to this device as well.": "Jakékoliv přístroje nakonfigurované na zavaděči budou přidány na tento přístroj také.",
"Any devices configured on an introducer device will be added to this device as well.": "Jakékoliv přístroje nakonfigurované na zavaděči budou přidány také na tento přístroj.",
"Automatic upgrades": "Automatický upgrade",
"Bugs": "Chyby",
"CPU Utilization": "Využití CPU",
"Changelog": "Changelog",
"Close": "Zavřít",
"Comment, when used at the start of a line": "Komentář, pokud použito na začátku řádku",
"Compression": "Komprese",
"Compression is recommended in most setups.": "Komprese je doporučena pro většinu nastavení.",
"Connection Error": "Chyba připojení",
"Copied from elsewhere": "Zkopírováno odjinud",
@@ -27,7 +29,7 @@
"Device Name": "Jméno přístroje",
"Device {%device%} ({%address%}) wants to connect. Add new device?": "Přístroj {{device}} ({{address}}) žádá o připojení. Chcete ho přidat?",
"Devices": "Přístroje",
"Disconnected": "Odpojeno",
"Disconnected": "Odpojen",
"Documentation": "Dokumentace",
"Download Rate": "Rychlost stahování",
"Downloaded": "Staženo",
@@ -37,13 +39,13 @@
"Edit Folder": "Upravit adresář",
"Editing": "Upravuje se",
"Enable UPnP": "Povolit UPnP",
"Enter comma separated \"ip:port\" addresses or \"dynamic\" to perform automatic discovery of the address.": "Vlož čárkou oddělené adresy \"ip:port\" nebo \"dynamic\" pro automatické zjišní adres. ",
"Enter comma separated \"ip:port\" addresses or \"dynamic\" to perform automatic discovery of the address.": "Vlož čárkou oddělené adresy \"ip:port\" nebo \"dynamic\" (pro automatické zjišťování adres). ",
"Enter ignore patterns, one per line.": "Vložit ignorované vzory, jeden na řádek.",
"Error": "Chyba",
"File Versioning": "Verze souborů",
"File permission bits are ignored when looking for changes. Use on FAT filesystems.": "Bity označující práva souborů jsou ignorovány při hledání změn. Použít pro souborové systémy FAT.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by syncthing.": "Soubory jsou přesunuty do verzí označených daty v adresáři .stversions po nahrazení nebo smazání aplikací 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.": "Soubory jsou chráněny před změnami na ostatních přístrojích, ale změny provedené z tohoto umístění budou rozeslány na zbytek clusteru.",
"File permission bits are ignored when looking for changes. Use on FAT filesystems.": "Bity označující práva souborů jsou při hledání změn ignorovány. Použít pro souborové systémy FAT.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by syncthing.": "Po nahrazení nebo smazání aplikací Syncthing jsou soubory přesunuty do verzí označených daty v adresáři .stversions.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Soubory jsou chráněny před změnami na ostatních přístrojích, ale změny provedené z tohoto ístroje budou rozeslány na zbytek clusteru.",
"Folder ID": "ID adresáře",
"Folder Master": "Master adresář",
"Folder Path": "Cesta k adresáři",
@@ -63,14 +65,16 @@
"Introducer": "Zavaděč",
"Inversion of the given condition (i.e. do not exclude)": "Prohození zadané podmínky (např. nevynechat)",
"Keep Versions": "Ponechat verze",
"Last File Received": "Poslední soubor přijat",
"Last File Synced": "Poslední soubor synchronizován",
"Last File Received": "Poslední přijatý soubor",
"Last File Synced": "Poslední synchronizovaný soubor",
"Last seen": "Naposledy spatřen",
"Later": "Později",
"Latest Release": "Poslední vydání",
"Local Discovery": "Místní oznamování",
"Local State": "Místní status",
"Maximum Age": "Maximální časový limit",
"Metadata Only": "Pouze metadata",
"Move to top of queue": "Přesunout na začátek fronty",
"Multi level wildcard (matches multiple directory levels)": "Víceúrovňový zástupný znak (shoda skrz více úrovní adresářů)",
"Never": "Nikdy",
"New Device": "Nový přístroj",
@@ -79,6 +83,7 @@
"No File Versioning": "Bez verzí souborů",
"Notice": "Oznámení",
"OK": "OK",
"Off": "Vypnuta",
"Offline": "Offline",
"Online": "Online",
"Out Of Sync": "Nesesynchronizováno",
@@ -93,6 +98,7 @@
"Quick guide to supported patterns": "Rychlá nápověda k podporovaným vzorům",
"RAM Utilization": "Využití RAM",
"Rescan": "Opakovat skenování",
"Rescan All": "Opakovat skenování všech",
"Rescan Interval": "Interval opakování skenování",
"Restart": "Restart",
"Restart Needed": "Je nutný restart",
@@ -100,21 +106,21 @@
"Reused": "Opakovaně použité",
"Save": "Uložit",
"Scanning": "Skenování",
"Select the devices to share this folder with.": "Vybrat přístroje se kterými sdílet tento adresář.",
"Select the folders to share with this device.": "Vybrat adresáře sdílené tomuto přístroji.",
"Select the devices to share this folder with.": "Vybrat přístroje, se kterými sdílet tento adresář.",
"Select the folders to share with this device.": "Vybrat adresáře sdílené s tímto přístrojem.",
"Settings": "Nastavení",
"Share": "Sdílet",
"Share Folder": "Sdílet adresář",
"Share Folders With Device": "Sdílet adresáře tomuto přístroji",
"Share Folders With Device": "Sdílet adresáře s tímto přístrojem",
"Share With Devices": "Sdílet s přístroji",
"Share this folder?": "Sdílet tento adresář?",
"Shared With": "Sdíleno s",
"Short identifier for the folder. Must be the same on all cluster devices.": "Krátký identifikátor tohoto adresáře. Musí být stejný na všech přístrojích v clusteru.",
"Show ID": "Zobrazit ID",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Zobrazeno místo ID přístroje na náhledu stavu clusteru. Bude odesíláno ostatním přístrojům jako dodatečné výchozí jméno.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Zobrazeno místo ID přístroje na náhledu stavu clusteru. Bude aktualizováno na jméno které přístroj odesílá pokud nebylo vyplněno.",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Zobrazeno místo ID přístroje na náhledu stavu clusteru. Bude odesíláno ostatním přístrojům jako výchozí jméno přístroje.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Zobrazeno místo ID přístroje na náhledu stavu clusteru. Pokud nebude vyplněno, bude nastaveno na jméno, které přístroj odesílá.",
"Shutdown": "Vypnout",
"Shutdown Complete": "Vypnutí ukončeno",
"Shutdown Complete": "Vypnutí dokončeno",
"Simple File Versioning": "Jednoduché verze souborů",
"Single level wildcard (matches within a directory only)": "Jednoúrovňový zástupný znak (shody pouze uvnitř adresáře)",
"Source Code": "Zdrojový kód",
@@ -135,9 +141,9 @@
"The aggregated statistics are publicly available at {%url%}.": "Souhrnné statistiky jsou veřejně dostupné na {{url}}.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfigurace byla uložena, ale není aktivována. Pro aktivaci nové konfigurace je třeba restartovat Syncthing.",
"The device ID cannot be blank.": "ID přístroje nemůže být prázdné.",
"The device ID to enter here can be found in the \"Edit > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "ID přístroje, které je třeba vložit, lze nalézt v dialogu \"Upravit > Zobrazit ID\" na druhém přístroji. Mezery a pomlčky nejsou nutné (ignorovány).",
"The device ID to enter here can be found in the \"Edit > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "ID přístroje, které je třeba vložit, lze nalézt v dialogu \"Upravit > Zobrazit ID\" na druhém přístroji. Mezery a pomlčky nejsou nutné (budou ignorovány).",
"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.": "Šifrovaná data o využití jsou zasílána denně. Jsou používána pro zjištění nejobvyklejších platforem, velikosti adresářů a verzí aplikace. Pokud se hlášená data změní, budete opět upozorněni tímto dialogem.",
"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.": "Zadané ID přístroje není platné. Mělo by mít 52 nebo 56 znaků, být složeno z písmen a čísel s nepovinnými mezerami a pomlčkami.",
"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.": "Zadané ID přístroje není platné. Mělo by mít 52 nebo 56 znaků a mělo by obsahovat písmena a čísla. Mezery a pomlčky jsou nepovinné.",
"The folder ID cannot be blank.": "ID adresáře nemůže být prázdné.",
"The folder ID must be a short identifier (64 characters or less) consisting of letters, numbers and the dot (.), dash (-) and underscode (_) characters only.": "ID adresáře musí být stručný popisek (64 znaků nebo méně) obsahující pouze písmena, čísla, tečku (.), pomlčku (-) a nebo podtržítko (_).",
"The folder ID must be unique.": "ID adresáře musí být unikátní.",
@@ -147,11 +153,11 @@
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Maximální doba pro zachování verze (dny, zapsáním hodnoty 0 bude ponecháno navždy).",
"The number of old versions to keep, per file.": "Počet starších verzí k zachování pro každý soubor.",
"The number of versions must be a number and cannot be blank.": "Počet verzí musí být číslo a nemůže být prázdné.",
"The rescan interval must be a non-negative number of seconds.": "Interval pro opakování skenování musí být pozitivní číslo.",
"The rescan interval must be a non-negative number of seconds.": "Interval opakování skenování musí být pozitivní číslo.",
"The rescan interval must be at least 5 seconds.": "Interval opakování skenování musí být delší než 5 sekund.",
"Unknown": "Neznámý",
"Unshared": "Nesdílené",
"Unused": "Nepoužité",
"Unshared": "Nesdílený",
"Unused": "Nepoužitý",
"Up to Date": "Aktuální",
"Upgrade To {%version%}": "Aktualizovat na {{version}}",
"Upgrading": "Aktualizuji",
@@ -160,9 +166,9 @@
"Use HTTPS for GUI": "Použít HTTPS pro grafické rozhraní",
"Version": "Verze",
"Versions Path": "Cesta verzí",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Verze jsou automaticky smazány pokud jsou starší než maximální časový limit nebo překročí počet souborů povolených pro interval.",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Verze jsou automaticky smazány, pokud jsou starší než maximální časový limit nebo překročí počet souborů povolených pro interval.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "Při přidávání nového přístroje mějte na paměti, že je ho třeba také zadat na druhé straně.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "Při přidávání nového adresáře mějte na paměti, že jeho ID je použito ke svázání adresářů napříč přístoji. Rozlišují malá a velká písmena a musí přesně souhlasit mezi všemi přístroji.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "Při přidávání nového adresáře mějte na paměti, že jeho ID je použito ke svázání adresářů napříč přístoji. Rozlišují se malá a velká písmena a musí přesně souhlasit mezi všemi přístroji.",
"Yes": "Ano",
"You must keep at least one version.": "Je třeba ponechat alespoň jednu verzi.",
"full documentation": "plná dokumentace",

View File

@@ -7,15 +7,17 @@
"Add new folder?": "Neues Verzeichnis hinzufügen?",
"Address": "Adresse",
"Addresses": "Adressen",
"All Data": "Alle Daten",
"Allow Anonymous Usage Reporting?": "Übertragung von anonymen Nutzungsberichten erlauben?",
"Anonymous Usage Reporting": "Anonymer Nutzungsbericht",
"Any devices configured on an introducer device will be added to this device as well.": "Alle Geräte, die beim Verteiler eingetragen sind, werden auch bei diesem Gerät eingetragen",
"Automatic upgrades": "Automat. Updates",
"Automatic upgrades": "automatische Updates",
"Bugs": "Fehler",
"CPU Utilization": "Prozessorauslastung",
"Changelog": "Versionsinfo",
"Close": "Schließen",
"Comment, when used at the start of a line": "Kommentar, wenn am Anfang der Zeile benutzt.",
"Compression": "Komprimierung",
"Compression is recommended in most setups.": "Datenkomprimierung ist für die meisten Anwendungen empfohlen",
"Connection Error": "Verbindungsfehler",
"Copied from elsewhere": "Von woanders kopiert",
@@ -29,7 +31,7 @@
"Devices": "Geräte",
"Disconnected": "Getrennt",
"Documentation": "Dokumentation",
"Download Rate": "Download",
"Download Rate": "Download-Rate",
"Downloaded": "Heruntergeladen",
"Downloading": "Lädt herunter",
"Edit": "Bearbeiten",
@@ -71,6 +73,8 @@
"Local Discovery": "Lokale Auffindung",
"Local State": "Lokaler Status",
"Maximum Age": "Höchstalter",
"Metadata Only": "Nur Metadaten",
"Move to top of queue": "An den Anfang der Warteschlange setzen",
"Multi level wildcard (matches multiple directory levels)": "Verschachteltes Maskenzeichen (wird für verschachtelte Verzeichnisse verwendet)",
"Never": "Nie",
"New Device": "Neues Gerät",
@@ -79,6 +83,7 @@
"No File Versioning": "Keine Dateiversionierung",
"Notice": "Hinweis",
"OK": "OK",
"Off": "Aus",
"Offline": "Offline",
"Online": "Online",
"Out Of Sync": "Nicht synchronisiert",
@@ -93,9 +98,10 @@
"Quick guide to supported patterns": "Schnellanleitung zu den unterstützten Suchstrukturen",
"RAM Utilization": "RAM Auslastung",
"Rescan": "Überprüfen",
"Rescan All": "Alle überprüfen",
"Rescan Interval": "Suchintervall",
"Restart": "Neustart",
"Restart Needed": "Neustart notwendig",
"Restart Needed": "Neustart benötigt",
"Restarting": "Wird neu gestartet",
"Reused": "Erneut benutzt",
"Save": "Speichern",

View File

@@ -0,0 +1,177 @@
{
"API Key": "Κλειδί API",
"About": "Σχετικά με το Syncthing",
"Add": "Προσθήκη",
"Add Device": "Προσθήκη συσκευής",
"Add Folder": "Προσθήκη φακέλου",
"Add new folder?": "Προσθήκη νέου φακέλου;",
"Address": "Διεύθυνση",
"Addresses": "Διευθύνσεις",
"All Data": "Όλα τα δεδομένα",
"Allow Anonymous Usage Reporting?": "Να επιτρέπεται η αποστολή ανώνυμων στοιχείων χρήσης;",
"Anonymous Usage Reporting": "Ανώνυμα στοιχεία χρήσης",
"Any devices configured on an introducer device will be added to this device as well.": "Αν δηλωθεί σαν «βασικός κόμβος», τότε όλες οι συσκευές που είναι δηλωμένες εκεί θα υπάρχουν και στον τοπικό κόμβο.",
"Automatic upgrades": "Αυτόματη αναβάθμιση",
"Bugs": "Bugs",
"CPU Utilization": "Επιβάρυνση του επεξεργαστή",
"Changelog": "Πληροφορίες εκδόσεων",
"Close": "Τέλος",
"Comment, when used at the start of a line": "Σχόλιο, όταν χρησιμοποιείται στην αρχή μιας γραμμής",
"Compression": "Συμπίεση",
"Compression is recommended in most setups.": "Η συμπίεση προτείνεται στις περισσότερες εγκαταστάσεις",
"Connection Error": "Σφάλμα σύνδεσης",
"Copied from elsewhere": "Έχει αντιγραφεί από κάπου αλλού",
"Copied from original": "Έχει αντιγραφεί από το πρωτότυπο",
"Copyright © 2014 Jakob Borg and the following Contributors:": "Copyright © 2014 από τον Jakob Borg και τους παρακάτω συνεισφορείς:",
"Delete": "Διαγραφή",
"Device ID": "Ταυτότητα συσκευής",
"Device Identification": "Ταυτότητα συσκευής",
"Device Name": "Όνομα συσκευής",
"Device {%device%} ({%address%}) wants to connect. Add new device?": "Η συσκευή {{device}} ({{address}}) επιθυμεί να συνδεθεί. Προσθήκη της νέας συσκευής1",
"Devices": "Συσκευές",
"Disconnected": "Αποσυνδεδεμένος",
"Documentation": "Τεκμηρίωση",
"Download Rate": "Ταχύτητα λήψης",
"Downloaded": "Έχει ληφθεί",
"Downloading": "Λήψη",
"Edit": "Επεξεργασία",
"Edit Device": "Επεξεργασία συσκευής",
"Edit Folder": "Επεξεργασία φακέλου",
"Editing": "Επεξεργασία σε εξέλιξη",
"Enable UPnP": "Ενεργοποίηση UPnP",
"Enter comma separated \"ip:port\" addresses or \"dynamic\" to perform automatic discovery of the address.": "Γράψε τις διευθύνσεις IP με τη μορφή «ip:θύρα», διαχωρισμένες με κόμμα. Αλλιώς γράψε «dynamic» για να πραγματοποιηθεί η αυτόματη εύρεση διευθύνσεων.",
"Enter ignore patterns, one per line.": "Δώσε τα πρότυπα που θα αγνοηθούν, ένα σε κάθε γραμμή.",
"Error": "Σφάλμα",
"File Versioning": "Τήρηση εκδόσεων",
"File permission bits are ignored when looking for changes. Use on FAT filesystems.": "Να αγνοούνται τα δικαιώματα των αρχείων όταν γίνεται αναζήτηση για αλλαγές. Χρησιμοποιείται σε συστήματα αρχείων τύπου FAT.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by syncthing.": "Όταν τα αρχεία αντικατασταθούν ή διαγραφούν από το syncthing, τότε να μεταφέρονται χρονοσημασμένα σε φάκελο με το όνομα .stversions.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Τα αρχεία προστατεύονται από αλλαγές που γίνονται σε άλλες συσκευές, αλλά όποιες αλλαγές γίνουν σε αυτή τη συσκευή θα αποσταλούν σε όλη τη συστάδα συσκευών.",
"Folder ID": "Ταυτότητα φακέλου",
"Folder Master": "Να μην επιτρέπονται αλλαγές",
"Folder Path": "Μονοπάτι φακέλου",
"Folders": "Φάκελοι",
"GUI Authentication Password": "Κωδικός για την πρόσβαση στη διεπαφή",
"GUI Authentication User": "Χρηστώνυμο για την πρόσβαση στη διεπαφή",
"GUI Listen Addresses": "Διευθύνσεις από τις οποίες θα είναι προσβάσιμη η διεπαφή",
"Generate": "Δημιουργία",
"Global Discovery": "Να μπορεί να ανευρεθεί καθολικά (από παντού)",
"Global Discovery Server": "Διακομιστής καθολικής ανεύρεσης κόμβου",
"Global State": "Καθολική κατάσταση",
"Idle": "Ανενεργό",
"Ignore": "Αγνόησε",
"Ignore Patterns": "Πρότυπο για αγνόηση",
"Ignore Permissions": "Αγνόησε τα δικαιώματα",
"Incoming Rate Limit (KiB/s)": "Περιορισμός ταχύτητας λήψης (KiB/s)",
"Introducer": "Βασικός κόμβος",
"Inversion of the given condition (i.e. do not exclude)": "Αντιστροφή της δοσμένης συνθήκης (π.χ. να μην εξαιρείς) ",
"Keep Versions": "Διατήρηση εκδόσεων",
"Last File Received": "Πιο πρόσφατο αρχείο",
"Last File Synced": "Τελευταία αλλαγή",
"Last seen": "Τελευταία φορά συνδεδεμένος",
"Later": "Αργότερα",
"Latest Release": "Τελευταία έκδοση",
"Local Discovery": "Τοπική ανεύρεση",
"Local State": "Τοπική κατάσταση",
"Maximum Age": "Μέγιστη ηλικία",
"Metadata Only": "Μόνο μεταδεδομένα",
"Move to top of queue": "Μεταφορά στην αρχή της λίστας",
"Multi level wildcard (matches multiple directory levels)": "Τελεστής μπαλαντέρ (*) για πολλά επίπεδα (χρησιμοποιείται για εμφωλευμένους φακέλους)",
"Never": "Ποτέ",
"New Device": "Νέα συσκευή",
"New Folder": "Νέος φάκελος",
"No": "Όχι",
"No File Versioning": "Να μην τηρούνται εκδόσεις",
"Notice": "Σημείωση",
"OK": "OK",
"Off": "Απενεργοποιημένο",
"Offline": "Εκτός σύνδεσης",
"Online": "Συνδεδεμένο",
"Out Of Sync": "Μη συγχρονισμένα",
"Out of Sync Items": "Μη συγχρονισμένα αντικείμενα",
"Outgoing Rate Limit (KiB/s)": "Ρυθμός αποστολής (KiB/s)",
"Override Changes": "Να αντικατασταθούν οι αλλαγές",
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Μονοπάτι του φακέλου σε αυτόν τον υπολογιστή. Αν δεν υπάρχει θα δημιουργηθεί. Η περισπωμένη (~) μπορεί να μπει σαν συντόμευση για το",
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Ο φάκελος στον οποίο θα αποθηκεύονται οι εκδόσεις των αρχείων (αν δεν οριστεί θα αποθηκεύονται στον υποφάκελο .stversions)",
"Please wait": "Παρακαλώ περιμένετε",
"Preview": "Προεπισκόπηση",
"Preview Usage Report": "Προεπισκόπηση αναφοράς χρήσης",
"Quick guide to supported patterns": "Σύντομη βοήθεια σχετικά με τα πρότυπα αναζήτησης που υποστηρίζονται",
"RAM Utilization": "Επιβάρυνση RAM",
"Rescan": "Έλεγξε για αλλαγές",
"Rescan All": "Έλεγξέ τα όλα για αλλαγές",
"Rescan Interval": "Κάθε πότε θα ελέγχεται για αλλαγές ",
"Restart": "Επανεκκίνηση",
"Restart Needed": "Απαιτείται επανεκκίνηση",
"Restarting": "Επανεκκίνηση",
"Reused": "Χρησιμοποιήθηκε ξανά",
"Save": "Αποθήκευση",
"Scanning": "Έλεγχος για αλλαγές",
"Select the devices to share this folder with.": "Διάλεξε τις συσκευές προς τις οποίες θα διαμοιράζεται αυτός ο φάκελος.",
"Select the folders to share with this device.": "Διάλεξε ποιοι φάκελοι θα διαμοιράζονται προς αυτή τη συσκευή.",
"Settings": "Ρυθμίσεις",
"Share": "Διαμοίραση",
"Share Folder": "Διαμοίραση φακέλου",
"Share Folders With Device": "Διαμοίρασε τους φακέλους προς αυτή τη συσκευή",
"Share With Devices": "Διαμοίρασε με αυτές τις συσκευές",
"Share this folder?": "Να διαμοιραστεί αυτός ο φάκελος;",
"Shared With": "Διαμοιράζεται με",
"Short identifier for the folder. Must be the same on all cluster devices.": "Σύντομη ταυτότητα για το φάκελο. Θα πρέπει να είναι η ίδια σε όλες τις συσκευές με τις οποίες διαμοιράζεται ο φάκελος αυτός.",
"Show ID": "Εμφάνιση ταυτότητας",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Θα φαίνεται αντί για την ταυτότητα της συσκευής στην προβολή της κατάστασης ολόκληρης της συστάδας. Θα γνωστοποιείται σαν το προαιρετικό όνομα της συσκευής.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Θα φαίνεται αντί για την ταυτότητα της συσκευής στην προβολή της κατάστασης ολόκληρης της συστάδας. Θα ενημερώνεται αυτόματα αν αλλάξει το όνομα της συσκευής.",
"Shutdown": "Απενεργοποίηση",
"Shutdown Complete": "Πλήρης απενεργοποίηση",
"Simple File Versioning": "Απλή τήρηση εκδόσεων",
"Single level wildcard (matches within a directory only)": "Τελεστής μπαλαντέρ (*) για ένα επίπεδο (χρησιμοποιείται για έναν φάκελο μόνο)",
"Source Code": "Πηγαίος κώδικας",
"Staggered File Versioning": "Να τηρούνται κλιμακούμενες εκδόσεις",
"Start Browser": "Εκκίνηση προγράμματος περιήγησης",
"Stopped": "Απενεργοποιημένο",
"Support": "Υποστήριξη",
"Support / Forum": "Υποστήριξη / Φόρουμ",
"Sync Protocol Listen Addresses": "Διευθύνσεις για το πρωτόκολλο συγχρονισμού",
"Synchronization": "Συγχρονισμός",
"Syncing": "Συγχρονίζω",
"Syncthing has been shut down.": "Το Syncthing έχει απενεργοποιηθεί.",
"Syncthing includes the following software or portions thereof:": "Το Syncthing περιλαμβάνει τα παρακάτω λογισμικά ή μέρη αυτών:",
"Syncthing is restarting.": "Το Syncthing επανεκκινείται.",
"Syncthing is upgrading.": "Το Syncthing αναβαθμίζεται.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Το Syncthing φαίνεται πως είναι απενεργοποιημένο ή υπάρχει πρόβλημα στη σύνδεσή σου στο διαδίκτυο. Προσπαθώ πάλι…",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Φαίνεται πως το Syncthing έχει κάποιο πρόβλημα με αυτό που ζήτησες. Αν το πρόβλημα επιμείνει φόρτωσε ξανά τη σελίδα ή επανεκκίνησε το Syncthing.",
"The aggregated statistics are publicly available at {%url%}.": "Τα στατιστικά που έχουν συλλεγεί είναι δημόσια διαθέσιμα στο {{url}}.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Οι ρυθμίσεις έχουν αποθηκευτεί αλλά δεν έχουν ενεργοποιηθεί. Πρέπει να επανεκκινήσεις το Syncthing για να ισχύσουν οι νέες ρυθμίσεις.",
"The device ID cannot be blank.": "Η ταυτότητα της συσκευής δεν μπορεί να είναι κενή",
"The device ID to enter here can be found in the \"Edit > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Η ταυτότητα της συσκευής που θα μπει εδώ βρίσκεται στο μενού «Επεξεργασία > Εμφάνιση ταυτότητας» στην άλλη συσκευή. Κενοί χαρακτήρες και παύλες είναι προαιρετικοί (απλά θα αγνοηθούν).",
"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.": "Η κρυπτογραφημένη αναφορά χρήσης στέλνεται καθημερινά. Χρησιμοποιείται για να παραχθούν στατιστικές για τα λειτουργικά συστήματα που χρησιμοποιούνται, τα μεγέθη των φακέλων και τις εκδόσεις των προγραμμάτων. Αν στο μέλλον συμπεριληφθούν και άλλα δεδομένα στην αναφορά χρήσης, τότε αυτό το παράθυρο θα εμφανιστεί ξανά.",
"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.": "Η ταυτότητα συσκευής που έδωσες δε φαίνεται έγκυρη. Θα πρέπει να είναι μια σειρά από 52 ή 56 χαρακτήρες (γράμματα και αριθμοί). Τα κενά και οι παύλες είναι προαιρετικά (αδιάφορα).",
"The folder ID cannot be blank.": "Η ταυτότητα του φακέλου δεν μπορεί να είναι κενή.",
"The folder ID must be a short identifier (64 characters or less) consisting of letters, numbers and the dot (.), dash (-) and underscode (_) characters only.": "Η ταυτότητα του φακέλου πρέπει να είναι ένα σύντομο αναγνωριστικό (το πολύ 64 χαρακτήρες). Μπορεί να αποτελείται από γράμματα, αριθμούς, την τελεία (.), την παύλα (-) και την κάτω παύλα (_).",
"The folder ID must be unique.": "Η ταυτότητα του φακέλου πρέπει να είναι μοναδική.",
"The folder path cannot be blank.": "Το μονοπάτι του φακέλου δεν μπορεί να είναι κενό.",
"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.": "Θα χρησιμοποιούνται τα εξής διαστήματα: Την πρώτη ώρα θα τηρείται μια έκδοση κάθε 30 δευτερόλεπτα. Την πρώτη ημέρα, μια έκδοση κάθε μια ώρα. Τις πρώτες 30 ημέρες, μία έκδοση κάθε ημέρα. Από εκεί και έπειτα μέχρι τη μέγιστη ηλικία, θα τηρείται μια έκδοση κάθε εβδομάδα.",
"The maximum age must be a number and cannot be blank.": "Η μέγιστη ηλικία πρέπει να είναι αριθμός και σίγουρα όχι κενό.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Η μέγιστη ηλικία παλιότερων εκδόσεων (σε ημέρες, αν δώσεις 0 οι παλιότερες εκδόσεις θα διατηρούνται για πάντα).",
"The number of old versions to keep, per file.": "Πόσες παλιότερες εκδόσεις θα διατηρούνται, ανά αρχείο.",
"The number of versions must be a number and cannot be blank.": "Ο αριθμός εκδόσεων πρέπει να είναι αριθμός και σίγουρα όχι κενό.",
"The rescan interval must be a non-negative number of seconds.": "Ο χρόνος επανελέγχου για αλλαγές είναι σε δευτερόλεπτα (δηλ. θετικός αριθμός).",
"The rescan interval must be at least 5 seconds.": "Ο χρόνος επανελέγχου πρέπει να είναι πάνω από 5 δευτερόλεπτα.",
"Unknown": "Άγνωστο",
"Unshared": "Δε μοιράζεται",
"Unused": "Δε χρησιμοποιείται",
"Up to Date": "Ενημερωμένος",
"Upgrade To {%version%}": "Αναβάθμιση στην έκδοση {{version}}",
"Upgrading": "Αναβάθμιση",
"Upload Rate": "Ταχύτητα ανεβάσματος",
"Use Compression": "Χρήση συμπίεσης",
"Use HTTPS for GUI": "Χρήση HTTPS για τη διεπαφή",
"Version": "Έκδοση",
"Versions Path": "Φάκελος τήρησης εκδόσεων",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Οι παλιές εκδόσεις θα σβήνονται αυτόματα όταν ξεπεράσουν τη μέγιστη ηλικία ή όταν ξεπεραστεί ο μέγιστος αριθμός αρχείων ανά περίοδο.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "Θυμήσου πως όταν προσθέτεις μια νέα συσκευή, ετούτη η συσκευή θα πρέπει να προστεθεί και στην άλλη πλευρά.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "Όταν προσθέτεις έναν νέο φάκελο, θυμήσου πως η ταυτότητα ενός φακέλου χρησιμοποιείται για να να συσχετίσει φακέλους μεταξύ συσκευών. Η ταυτότητα του φακέλου θα πρέπει να είναι η ίδια σε όλες τις συσκευές και έχουν σημασία τα πεζά ή κεφαλαία γράμματα.",
"Yes": "Ναι",
"You must keep at least one version.": "Πρέπει να τηρήσεις τουλάχιστον μια έκδοση.",
"full documentation": "πλήρης τεκμηρίωση",
"items": "εγγραφές",
"{%device%} wants to share folder \"{%folder%}\".": "Η συσκευή {{device}} θέλει να μοιράσει τον φάκελο «{{folder}}»."
}

Some files were not shown because too many files have changed in this diff Show More