Commit Graph

582 Commits (206e706d85032bdeae0df1d6418c58f8c4d2406b)

Author SHA1 Message Date
Axel Burri e879620195 change version to 0.27.1 2018-12-05 22:18:19 +01:00
Axel Burri 0e6c1f9025 btrbk: fix regression: call "sudo readlink" for backend=btrfs-progs-sudo
It is possible that the subvolume path is not accessible by the user
calling btrbk. When resolving mount points, "readlink" is used on the
path, which also needs to be wrapped with "sudo".
2018-12-05 22:01:07 +01:00
Axel Burri ff011d55af btrbk: fix "config print" command (undefined value in format_preserve_matrix())
regression: 5791d72171 btrbk: add "preserve_hour_of_day" configuration option
2018-12-05 21:43:54 +01:00
Axel Burri de851955b6 btrbk: print_formatted: no blank lines for format: raw,tlog,syslog 2018-10-31 14:33:07 +01:00
Axel Burri ebaaee2139 btrbk: print_formatted: omit title for format: raw,tlog,syslog 2018-10-31 14:06:14 +01:00
Axel Burri 74873081c3 btrbk: bump version to 0.27.1-dev 2018-10-31 13:57:06 +01:00
Axel Burri c59488f405 change version to 0.27.0 2018-10-16 12:19:44 +02:00
Axel Burri 56ee8acf3b btrbk: add "-S" command line option (shortcut for --print-schedule) 2018-10-15 16:25:07 +02:00
Axel Burri 7a8df85f2e btrbk: fix regression: add node to return value of vinfo_resolved()
The FORCE_PRESERVE information is set on the node, and was lost for
"latest common target" as get_receive_targets() returned vinfo without
node information.

fixes regression: 6c502cb btrbk: search complete target tree for correlated subvolumes
2018-10-15 16:19:52 +02:00
Axel Burri 3528927ea6 btrbk: bugfix: do not keep latest common snapshot for "incremental no"
There is no reason to keep the latest common source snapshot if
"incremental no" is configured (see #252).
2018-10-02 17:28:46 +02:00
Axel Burri 069304f3bb btrbk: use system_list_mountinfo(), remove system_list_mounts(); rename fs_spec -> mount_source
Reasons for changing to `cat /proc/self/mountinfo`:
 - `/proc/self/mounts` (or `/proc/mounts`) lacks extra info
   (namespaces) and is not documented in kernel (deprecated?).
 - findmnt(8) also uses /proc/self/mountinfo

Refs:
 - https://www.kernel.org/doc/Documentation/filesystems/proc.txt
 - https://bugzilla.redhat.com/show_bug.cgi?id=491924
 - https://git.kernel.org/pub/scm/linux/kernel/git/bwh/linux-stable.git/commit/?id=2d4d4864ac08caff5c204a752bd004eed4f08760
2018-08-27 14:54:32 +02:00
Axel Burri e02c2cf249 btrbk: add system_list_mountinfo: parse /proc/self/mountinfo
preparatory patch for removing system_list_mounts().
2018-08-27 14:52:28 +02:00
Axel Burri 37c0e840e9 btrbk: bugfix: use latest longest match for resolving mount point (e.g. for autofs) 2018-08-27 14:49:04 +02:00
Axel Burri 0d124a4373 btrbk: fix regression in get_related_subvolumes(): correctly match same btrbk file name scheme
Since we consider all accessible subvolumes in get_related_subvolumes,
checking for equal BTRBK_BASENAME and empty SUBVOL_DIR does not work
when checking for same btrbk file name scheme.

fixes regression: b37ef84e36 (btrbk: always read mountpoints; include all snapshots from mountpoint as candidates for best common parent)
2018-07-18 16:13:33 +02:00
Axel Burri bf5fd7a90b btrbk: cosmetics: fix prototype of get_related_subvolumes() 2018-07-18 16:13:29 +02:00
Axel Burri 1242913d9b btrbk: cosmetics: rename variables (spec -> fs_spec) 2018-07-12 18:26:35 +02:00
Axel Burri 47f6f730ab btrbk: cosmetics: change error message in btrfs_subvolume_delete; add comments 2018-07-12 18:26:35 +02:00
Axel Burri faec212324 btrbk: check if received subvolume is really garbled before deleting it
Improve error handling in btrfs_send_receive: on error, always try to
read the target subvolume and only delete it automatically if it is
garbled (read/write, no received_uuid).

This is especially important if the target subvolume was already
present before send/receive.

Reverts: 4c4afe77 btrbk: skip target metadata test if send/receive has errors
2018-07-12 18:26:35 +02:00
Axel Burri de57efff82 btrbk: bugfix: print all errors if send/receive fails
If stream_compress is enabled and compress command is not found, we
now print "command not found".
2018-07-12 18:26:34 +02:00
Axel Burri 9aeaf2b15c btrbk: fix regression introduced with btrfs_subvolume_list_complete
If btrfs_subvolume_show($vol, rootid => 5) fails, there are no
"received_uuid" and no "gen" keys in the root node.

Fixes: 0acbf74c57 (btrbk: add btrfs_subvolume_list_complete: fetch all subvolumes with all flags)
2018-07-09 18:46:24 +02:00
Axel Burri 669a34357a btrbk: bugfix: handle corner case: url="ssh://my.host" (without trailing slash)
As we allow <url> to be specified as "<hostname>:<directory>", an URL
"ssh://my.host" (without trailing slash) was parsed as hostname="ssh",
directory="/my.host".
2018-07-09 16:13:48 +02:00
Axel Burri 0acbf74c57 btrbk: add btrfs_subvolume_list_complete: fetch all subvolumes with all flags
Wrapper, returns complete list of all subvolumes (including btrfs
root, id=5) with all flags. Requires three calls to btrfs-progs.

Adaptions and cleanup in btr_tree().
2018-07-09 16:13:00 +02:00
Axel Burri d15133b3d4 btrbk: snapshot_name defaults to volume name if subvolume name is "." 2018-07-09 16:13:00 +02:00
Axel Burri 7088a91fa3 btrbk: cosmetics: sanitize trailing "/." in check_file() 2018-07-09 16:13:00 +02:00
Axel Burri de5004c744 btrbk: abort subvolume if it is btrfs root (id=5)
Btrfs root subvolume (id=5) have no UUID and cannot be backed
up. Abort if "subvolume ." is configured on btrfs root, e.g.:

  volume /path/to/btrfs_root
    subvolume .
2018-07-09 16:13:00 +02:00
Axel Burri b0d58fd0f1 btrbk: btr_tree: always read btrfs root node (id=5), hoping to get its uuid
Note that the UUID for btrfs root (id=5) is not always present:

 - btrfs-progs < 4.12 does not support rootid lookup
 - UUID can be missing if filesystem was created with btrfs-progs < 4.16

Still we need to always read it, as the whole tree is cached and we
don't know if it will be used.
2018-07-09 16:13:00 +02:00
Axel Burri cb5e361f7a btrbk: add --rootid command option for "btrfs subvolume show" 2018-07-09 16:13:00 +02:00
Axel Burri 1aa0fe1aad btrbk: remove obsolete realpath_cache update in btrfs_subvolume_show()
Recent btrfs-progs do not print the real path any more, this is now
handled by btrfs_mountpoint() -> system_realpath().
2018-07-09 16:13:00 +02:00
Axel Burri 177671e920 btrbk: validate output of "btrfs subvolume show"; also return uuid for btrfs root (if present)
Filesystems created with btrfs-progs < 4.16 have valid UUID, while
others have not [1]. Validate output of "btrfs subvolume show", and
provide uuid for btrfs root (id=5) only if it is valid.

  [1]: 0a0a03554a: btrfs-progs: mkfs: add uuid and otime to ROOT_ITEM of, FS_TREE
2018-07-09 16:13:00 +02:00
teesid 9c70231859 btrbk: allow backup of subvolume (subvolid != 5) mounted at "/"
It works with the configuration snippet below if subvolid != 5:

```
volume /
  subvolume  .
    snapshot_name  root
```
2018-07-09 16:13:00 +02:00
Axel Burri a0f6b55d28 btrbk: fix regression: undefined array reference when no received_uuid present
fixes #239 (@ian-kelling)
2018-06-25 13:30:14 +02:00
Samantha McVey 211943d4af btrbk: cosmetics: reformat a regex to be much more readable 2018-06-04 11:39:52 +02:00
Samantha McVey 969569592a btrbk: cosmetics: use heredocs for the help message
Avoids use having to use 40 print's and having to quote each line and is
much easier to edit.
2018-06-04 11:39:03 +02:00
Axel Burri 391e50b872 btrbk: do not warn on non-parseable btrfs mountpoint
Many people use whitespace even in mountpoints, silently ignore
(loglevel=info) non-parseable btrfs mountpoints.

Btrbk does not support file names with whitespace or special
characters by design, and specifying such mountpoints in the
configuration file fails anyway.
2018-05-31 00:34:50 +02:00
Axel Burri 2f56c55120 btrbk: fix regression: actions "list snapshots/backups" print all snapshots under sroot (not snaproot)
Regression from: c457540ce3
2018-05-14 23:43:13 +02:00
Axel Burri 09918bf5af btrbk: cosmetics: print (fix) reason why snapshots/backups are skipped/preserved 2018-05-11 00:17:52 +02:00
Axel Burri 9ae823a757 btrbk: cosmetics: remove too chatty debug log 2018-05-10 15:44:46 +02:00
Vít Novotný c8fcb01bc2 btrbk: bugfix: do not read target btrfs tree on "btrbk snapshot --preserve"
If running "btrbk snapshot --preserve", there is no need to initialize
targets, and we don't want to warn and fail (exitcode=10) on missing
targets.
2018-05-10 15:18:36 +02:00
Axel Burri 17f41118d3 btrbk: bugfix: compare all mountpoints while resolving
When comparing longest match in mounts, all mountpoints have to be
taken into account (not only the btrfs mount points).
2018-05-10 14:02:44 +02:00
Axel Burri 1c83a6545d btrbk: add filter capabilities to vinfo_subvol_list
Clean up (and speedup) code by filtering while building the list
instead of checking every item after building.
2018-05-10 11:48:34 +02:00
Axel Burri a25487e873 btrbk: cosmetics (log messages) 2018-05-10 11:48:34 +02:00
Axel Burri ef5c369a37 btrbk: use _is_same_fs_tree() where applicable 2018-05-10 11:48:34 +02:00
Axel Burri 0454f60ad1 btrbk: bugfix: match btrbk_basename in get_latest_snapshot_child() 2018-05-10 11:48:34 +02:00
Axel Burri 2c1c3b4d54 btrbk: cleanup: remove snapshot_dir, rename sroot->snaproot 2018-05-10 11:48:34 +02:00
Axel Burri c457540ce3 btrbk: use separate vinfo for snapshot directory (allows snapshot_dir to be a mountpoint)
Instead of passing snapshot_dir all over the place, use a separate
vinfo for the snapshot directory, accessible by vinfo_snapshot_root().
As it is initialized separately by vinfo_init_root(), it can be on a
different mountpoint.

This also allows us to use different semantics for snapshot_dir in the
future, as it does not need to be relative to the volume directory.
2018-05-10 11:48:34 +02:00
Axel Burri f5dc4e0a36 btrbk: add known mountpoints to btr_tree nodes as anchor for reverse lookup 2018-05-10 11:48:34 +02:00
Axel Burri e9374b3b1d btrbk: replace url_cache by spec_cache 2018-05-10 11:48:34 +02:00
Axel Burri 0ea0430c43 btrbk: cleanup (cosmetics, documentation) 2018-05-10 11:48:34 +02:00
Axel Burri b37ef84e36 btrbk: always read mountpoints; include all snapshots from mountpoint as candidates for best common parent
Dropped readin of subvolid and realpath by btrfs_subvolume_show(), we
now always read /proc/self/mounts (and call readlink).

When picking the best common parent in get_best_parent(), we want to
list as many snapshots as possible. For now, we list all from the
mountpoint of snaproot ($sroot/<snapshot_dir>), due to a bug in
btrfs-progs [1]. Also added code (commented out) to list snapshots
from all known mountpoints.

  [1] https://github.com/kdave/btrfs-progs/issues/96
2018-05-10 11:48:05 +02:00
Axel Burri b549e11b43 btrbk: raw targets: move tree readin to separate function; add caching
Adds new function vinfo_init_raw_root(), similar to vinfo_init_root().
Note that we don't (yet) resolve realpath for raw targets.
2018-05-10 11:36:21 +02:00
Axel Burri 7a1bc257c1 btrbk: raw targets: create fake btr_tree instead of maintaining separate list 2018-05-10 11:36:21 +02:00
Axel Burri 6c502cbdcc btrbk: search complete target tree for correlated subvolumes
- move matching for correlated subvolumes from get_receive_targets
  into new function _receive_target_nodes
- add lookup tables in btr_tree (RECEIVED_UUID_HASH, UUID_HASH),
  allowing for faster matching in _receive_target_nodes
- add vinfo_resolved() for mapping nodes to vinfo
- rename get_latest_common to get_best_parent (while moving some
  functionality to new function get_related)
- cleanup
2018-05-10 11:36:21 +02:00
Axel Burri 490f680f41 btrbk: bugfix: add backend mappings for "btrfs filesystem usage" 2018-04-30 14:15:30 +02:00
Axel Burri 719fb5fb74 btrbk: bugfix: correct scheduling of "first weekly backup in month/year"
In the scheduler, a month (or year) does not start at the first day,
but at the first `preserve_day_of_week`. Make sure that all days
before `preserve_day_of_week` in a month get delta_months+1.

Example (corner case):
  - `preserve_day_of_week  sunday`
  - `target_preserve  *m`
  - no backups in 2018-02
  - backup with timestamp 2018-03-01 (which is a thursday)
  - backup with timestamp 2018-03-04 (which is a sunday)

Without this patch, because there are no sunday backups in 2018-02,
the first backup is considered a weekly (+4d after sunday), and as
such "first weekly of month 2018-03", and the second one is discarded.

With this patch, the first item is considered "first weekly of month
2018-02", and the second gets "first weekly of month 2018-03".

NOTE: This change may result in (previously preserved) backups to be
deleted!
2018-04-05 18:00:29 +02:00
Axel Burri e4a0938712 btrbk: ignore "preserve_hour_of_day" on snapshots/backups having "timestamp_format=short"
Snapshots and backups having no exact time information (created with
"timestamp_format=short") are set to 00:00, which would be regarded as
"previous day" if preserve_hour_of_day is greater than 0. Fix this by
ignoring preserve_hour_of_day in this case.
2018-04-05 18:00:29 +02:00
Axel Burri c89ffd4213 btrbk: schedule: format preserve text only if needed
No functional changes, improves performance of schedule().
2018-04-05 18:00:24 +02:00
Thiodwitnir 5791d72171 btrbk: add "preserve_hour_of_day" configuration option
Introduces the new config option "preserve_hour_of_day" to specify
after what time backups should be considered as dailies.

Based on pull request #204, with changes:
 - calculation of weekly backups
 - change format of preserve_matrix
2018-04-05 16:37:31 +02:00
Axel Burri 951ae256fa btrbk: bump version to 0.27.0-dev 2018-04-05 16:26:57 +02:00
Axel Burri 1fd3a547df change version to 0.26.1; bump copyright year 2018-03-05 11:55:56 +01:00
Axel Burri 6f38536052 btrbk: set c_default for config keys with computed default
Suppress "Option redefined" warning for snapshot_name config option,
which has hardcoded (computed) default already set when checking.

fix regression: 0ebe2ea2e1
2018-02-26 16:06:12 +01:00
Axel Burri e75cf0c72c btrbk: fix exit status and transaction log when archive_exclude is set
Similar to ABORTED=USER_SKIP (active commandline filter), archives
having ABORTED=ARCHIVE_EXCLUDE_SKIP (active archive_exclude
configuration) do not cause exit status 10 and are hidden from
transaction log.
2018-02-26 14:35:26 +01:00
Axel Burri 5651c96e4e btrbk: archive: always print "[-]" if no action was performed for target 2018-02-14 00:18:44 +01:00
Axel Burri 8610e75459 btrbk: add archive_exclude configuration option
Support wildcard characters, matches against both "$sroot->{PATH}" and
"$sroot->{PATH}/$snapshot_name".
2018-02-13 22:50:23 +01:00
Axel Burri 0ebe2ea2e1 btrbk: add "allow_multiple" flag for config_options declaration; use for option "group" 2018-02-13 19:30:24 +01:00
Axel Burri 3aaafa3d88 btrbk: add "meta" context for config defaults
Preparatory patch to allow multiple identical config keys in same
section.
2018-02-13 19:28:38 +01:00
Axel Burri b2b43cf199 btrbk: add configurable error_statement for check functions
Corrects error messages from --exclude option.
Applies to in check_file(), check_url() and append_config_option().
2018-02-13 17:40:14 +01:00
Axel Burri db1fe2d11a btrbk: fix output of "btrbk list backups" and "btrbk stats" (match all uuid/received_uuid combinations) 2018-02-07 16:24:49 +01:00
Axel Burri a3641cff74 btrbk: fix filter statement matching for volume="/"
While $vol->{URL} can contain "//" if volume="/" (intentionally, this
is an assembled path), the filter statements are sanitized using
check_url(). This means we need to match the filter statement against
check_url($vol->{URL}). Same applies to subvol.
2018-02-03 12:55:21 +01:00
Axel Burri 90fed6525e btrbk: bugfix: restrict snapshot_dir and snapshot_create to root/volume/subvolume context 2018-01-31 19:01:00 +01:00
Axel Burri 753d68b2ed btrbk: add documentation on caching in btr_tree() 2018-01-30 14:02:36 +01:00
Axel Burri 84bac59ab4 btrbk: fix parsing of "openssl_iv_size" configuration option 2018-01-21 18:53:29 +01:00
Axel Burri 13f37491ed btrbk: cosmetics: change order of commands in help message 2017-10-12 17:08:46 +02:00
Axel Burri 79cbf7c0c3 change version to 0.26.0 2017-10-12 00:39:06 +02:00
Axel Burri 909c68f164 btrbk: transaction_log and transaction_syslog are only allowed in root context 2017-10-11 20:54:41 +02:00
Axel Burri d941ecfce9 documentation: change digint links to https:// 2017-10-11 20:54:41 +02:00
Axel Burri e3ee674085 btrbk: limit search depth to 256 when resolving ancestors
Note that the current implementation is not very optimized, we should
introduce a parent/child hash table for all queries in
get_latest_common().
2017-10-10 16:46:05 +02:00
Axel Burri 3be65b9f67 btrbk: resolve ancestors (recursive on parent_uuid chain) when searching for latest common subvolume 2017-10-10 13:10:33 +02:00
Axel Burri 0799820556 btrbk: support btrfs-progs 4.13.2: adapt parsing of "btrfs subvolume list"
btrfs-progs v4.13.2 changed the output of "btrfs subvolume list", in
order to make the tabular output format look nicer (?!?):

e4c6772f69
2017-10-09 23:04:07 +02:00
Axel Burri e9a517f161 btrbk: add options "{snapshot,target,archive}_qgroup_destroy": destroy qgroups whenever a subvolume is deleted
Btrfs does not destroy qgroups when subvolumes are deleted (see
https://bugzilla.kernel.org/show_bug.cgi?id=91751). As a workaround
for this, btrbk can be configured to always destroy the corresponding
default qgroup "0/<subvol-id>" whenever a subvolume (snapshot, backup
or archive) is deleted.

Added configuration options:
 - snapshot_qgroup_destroy
 - target_qgroup_destroy
 - archive_qgroup_destroy
2017-10-02 16:23:23 +02:00
Axel Burri 6cb98700d8 btrbk: allow archive_preserve_* options in root context only 2017-10-02 13:54:37 +02:00
Axel Burri 2e974c1f4f btrbk: add "--wipe" command line option 2017-09-28 14:17:00 +02:00
Axel Burri 5bdc3e527b btrbk: add "prune" command 2017-09-28 14:17:00 +02:00
Axel Burri 2809dc54c5 btrbk: remove sorting of deleted subvolumes in summary (not needed anymore)
Deleted subvolumes are already sorted by schedule().
Sorting by PATH is bad anyways, as it does not sort _NN postfix
correctly.
2017-09-28 14:17:00 +02:00
Axel Burri 512aca5332 btrbk: parse output of "btrfs subvolume delete"
When doing a batch delete (multiple deletes with one call to "btrfs
subvolume delete"), we want to know which subvolumes have failed. For
this, we need parse the error output.

On any parsing failure, we assume that nothing has been deleted, and
warn accordingly (forward compatibility).
2017-09-28 14:17:00 +02:00
Axel Burri 9d9527ca9a btrbk: simplify transaction function calls
Prefix transaction status with "dryrun_" in start_transaction() /
end_transaction if $dryrun is set.
2017-09-28 14:17:00 +02:00
Axel Burri 422d52c063 btrbk: add key derivation for encrypted raw targets using external backend 2017-09-28 14:17:00 +02:00
Axel Burri de7628ac7c btrbk: add openssl_enc encryption for raw targets; add system_urandom()
Example:

Manually create a key:

    # KEYFILE=/some/secure/place/btrbk.key
    # dd if=/dev/urandom bs=1 count=32 | od -x -A n | tr -d "[:space:]" > $KEYFILE

btrbk.conf:

    volume /mnt/btr_pool
      incremental no
      raw_target_encrypt  openssl_enc
      openssl_ciphername  aes-256-cbc
      openssl_iv_size     16  # NOTE: set to "no" if no IV is needed by the selected cipher
      openssl_keyfile     /some/secure/place/btrbk.key

      subvolume home
        target raw ssh://cloud.example.com/backup
2017-09-28 14:17:00 +02:00
Axel Burri 251c2fb2a1 btrbk: re-enable parsing of deprecated raw file format (uuid suffix) 2017-09-28 14:17:00 +02:00
Axel Burri e804930b5e btrbk: allow deletion of non-incremental raw targets
implemented directly in btrfs_subvolume_delete()
2017-09-28 14:17:00 +02:00
Axel Burri cd8d7e3a0a btrbk: use sidecar file "*.info" instead of encoding uuids into filename for raw targets
pros:

 - better forward compatibility, e.g. symmetrical encryption
 - better readability of files

cons:

 - two files per backup
2017-09-28 14:16:53 +02:00
Axel Burri 571dae4428 btrbk: do not run in perl taint mode by default: remove "perl -T" in hashbang; hardcode $PATH only if taint mode is enabled
While taint mode [1] is a nice feature of perl, e.g. it disallows
using variables (such as filenames from the config file) which were
not validated in system() commands, it also treats $PATH as insecure
(which inherently is, as perl cannot know who messed around with it).

  [1] perlsec(1): http://perldoc.perl.org/perlsec.html
  [2] perlrun(1): http://perldoc.perl.org/perlrun.html

Note that btrbk still does all taint checks, and can be run in taint
mode:

  - by executing `perl -T /usr/sbin/btrbk`,
  - or by changing the hashbang to: `!#/usr/bin/perl -T`.
2017-09-25 17:53:35 +02:00
Axel Burri 5f867c2347 btrbk: run_cmd(): catch all possible errors when executing system command 2017-09-25 15:00:40 +02:00
Axel Burri e402435dc8 btrbk: treat deprecated warnings as non-fatal
Despite FATAL warnings are discouraged in perl and may break forward
compatibility [1], we still use it as btrbk is usually run as root and
we really want perl to die on programmatic errors.

  [1] "perldoc warnings"
2017-09-25 15:00:40 +02:00
Axel Burri 6c2d56d621 btrbk: action "clean": dont list failed deletes in summary 2017-09-21 12:39:48 +02:00
Axel Burri f113436626 btrbk: bugfix: check path when expanding wildcards (warn and ignore if check fails)
Before this patch, btrbk errored (unsafe command), and then died.
Fixes #181.
2017-09-11 18:49:14 +02:00
boerwastaken d265c34149 btrbk: make SSH minimally chatty (always add '-q' option)
Fixes digint/btrbk#179: When SSH is chatty (informing of host key
rollover etc) the remote command output parser borks.
2017-09-04 13:00:19 +02:00
Axel Burri 8eb88a8681 documentation: replace POD header with comments 2017-08-28 20:33:00 +02:00
Axel Burri 88aa8c1fea btrbk: remove "duration" column from transaction_log/transaction_syslog
The "duration" column in the transaction log has proven to be
confusing to some users, especially on errors (e.g. "send-receive
ERROR 27" in issue #177). As it's not really necessary (duration can
be computed from the corresponding "starting" log entry), it's now
being dropped.
2017-08-28 17:55:27 +02:00
Axel Burri 6acea6a08d btrbk: bugfix: print correct time in end_transaction() 2017-08-28 17:54:17 +02:00
Axel Burri 5428e9cd93 btrbk: add "resume" and "snapshot" commands; add --preserve-snapshots and --preserve-backups options; deprecate "-r, --resume-only" command line option 2017-08-21 13:23:20 +02:00