Commit Graph

168 Commits

Author SHA1 Message Date
Matthias Görgens
7297044ada
Fuse mount: make auto_unmount compatible with suid/dev mount options (#762)
* Fuse mount: make auto_unmount compatible with suid/dev mount options

> When you run as root, fuse normally does not call fusermount but uses
> the mount system call directly. When you specify auto_unmount, it goes
> through fusermount instead. However, fusermount is a setuid binary that
> is normally called by regular users, so it cannot in general accept suid
> or dev options.

In this patch, we split up how fuse mounts as root when `auto_unmount`
is specified.

First, we mount using system calls directly, then we reach out to
fusermount to set up auto_unmount only (with no actual mounting done in
fusermount).

Fixes: #148
2023-04-12 08:39:32 +01:00
Matthias Goergens
eb88309882 Migrate away from deprecated distutils
Before:

```
=============================== warnings summary ===============================
test/test_ctests.py:12
  /tmp/libfuse-build-mB50ZC/build-gcc-9/test/test_ctests.py:12: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
    from distutils.version import LooseVersion

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
```
2023-04-11 13:32:00 +01:00
Matthias Goergens
c261271aa9 Fix typo 2023-04-11 11:58:33 +01:00
Matthias Goergens
6ce27f48bc Fix PytestReturnNotNoneWarning
```
test_examples.py::test_printcap
  /usr/local/lib/python3.9/dist-packages/_pytest/python.py:199: PytestReturnNotNoneWarning: Expected None, but test_examples.py::test_printcap returned ((7, 38), {'FUSE_CAP_READDIRPLUS_AUTO', 'FUSE_CAP_ASYNC_DIO', 'FUSE_CAP_SPLICE_READ', 'FUSE_CAP_CACHE_SYMLINKS', 'FUSE_CAP_IOCTL_DIR', 'FUSE_CAP_NO_OPENDIR_SUPPORT', 'FUSE_CAP_NO_OPEN_SUPPORT', 'FUSE_CAP_POSIX_LOCKS', 'FUSE_CAP_READDIRPLUS', 'FUSE_CAP_POSIX_ACL', 'FUSE_CAP_ATOMIC_O_TRUNC', 'FUSE_CAP_SPLICE_MOVE', 'FUSE_CAP_EXPORT_SUPPORT', 'FUSE_CAP_FLOCK_LOCKS', 'FUSE_CAP_EXPLICIT_INVAL_DATA', 'FUSE_CAP_EXPIRE_ONLY', 'FUSE_CAP_DONT_MASK', 'FUSE_CAP_WRITEBACK_CACHE', 'FUSE_CAP_AUTO_INVAL_DATA', 'FUSE_CAP_PARALLEL_DIROPS', 'FUSE_CAP_SPLICE_WRITE', 'FUSE_CAP_ASYNC_READ'}), which will be an error in a future version of pytest.  Did you mean to use `assert` instead of `return`?
    warnings.warn(
```
2023-04-07 15:31:58 +01:00
Matthias Goergens
b9b4307e4d Fix deprecated @pytest.mark.hookwrapper
```
PytestDeprecationWarning: The hookimpl pytest_pyfunc_call uses old-style configuration options (marks or attributes).
  Please use the pytest.hookimpl(hookwrapper=True) decorator instead
   to configure the hooks.
   See https://docs.pytest.org/en/latest/deprecations.html#configuring-hook-specs-impls-using-markers
    @pytest.mark.hookwrapper
```
2023-04-07 15:31:58 +01:00
Matthias Goergens
7555d032a2 Fix meson deprecation warning
Also for rest of CI
2023-04-07 14:01:16 +01:00
Matthias Goergens
b37f6dfe70 Upgrade meson version in CI 2023-04-07 13:32:35 +01:00
Nikolaus Rath
d65686ac2c Add unit tests for setxattr() et al
Hopefully, this will catch issues as in commit 024eccbf3
2023-04-01 16:49:01 +01:00
Nikolaus Rath
17e8b3e273 Migrate from Travis to Github actions
With current Ubuntu, Valgrind apparently does not like clang debug info, so do not run
valgrind with clang-compiled binaries.
2023-02-20 20:28:12 +00:00
Bernd Schubert
db35a37def Install a the configure_file (config.h) and use in headers
This addresses: https://github.com/libfuse/libfuse/issues/724

HAVE_LIBC_VERSIONED_SYMBOLS configures the library if to use
versioned symbols and is set at meson configuration time.
External filesystems (the main target, actually)
include fuse headers and the preprocessor
then acts on HAVE_LIBC_VERSIONED_SYMBOLS. Problem was now that
'config.h' was not distributed with libfuse and so
HAVE_LIBC_VERSIONED_SYMBOLS was never defined with external
tools and the preprocessor did the wrong decision.

This commit also increases the the minimal meson version,
as this depends on meson feature only available in 0.50

<quote 'meson' >
WARNING: Project specifies a minimum meson_
version '>= 0.42' but uses features which were added
 in newer versions:
 * 0.50.0: {'install arg in configure_file'}
</quote>

Additionally the config file has been renamed to "fuse_config.h"
to avoid clashes - 'config.h' is not very specific.
2023-01-28 09:35:34 +00:00
Bernd Schubert
e42b972271 Update travis to ubuntu jammy (22.04)
A newer ubuntu version is required to get a more recent meson
(at least 0.50 now)
2023-01-28 09:35:34 +00:00
Bernd Schubert
856c683c36 passthrough_hp: Add options for clone_fd, max_threads, daemonize
This is useful for benchmarking.

Note: This changes behavior - passthrough_hp runs in background by default
      now.
2023-01-13 10:21:42 +00:00
Tofik Sonono
50c74e6459
Support application-defined I/O functions for FUSE fd
The io for FUSE requests and responses can now be further customized by allowing to write custom functions for reading/writing the responses. This includes overriding the splice io.

The reason for this addition is that having a custom file descriptor is not sufficient to allow custom io. Different types of file descriptor require different mechanisms of io interaction. For example, some file descriptor communication has boundaries (SOCK_DGRAM, EOF, etc...), while other types of fd:s might be unbounded (SOCK_STREAMS, ...). For unbounded communication, you have to read the header of the FUSE request first, and then read the remaining packet data. Furthermore, the one read call does not necessarily return all the data expected, requiring further
calls in a loop.
2023-01-10 10:04:35 +00:00
HereThereBeDragons
c0a344e379 Test for fuse_lowlevel_notify_expire_entry.
This test is too simple to check for all functionalities of notify_expire as it always successfully passes when libfuse supports the function (even if kernel does not support it -  it just takes it as notify_inval)
2023-01-06 18:35:52 +00:00
Bernd Schubert
d372d3f80b Fixes when HAVE_LIBC_VERSIONED_SYMBOLS is not defined
fuse_loop_mt and fuse_new had not been defined when
HAVE_LIBC_VERSIONED_SYMBOLS had not been set and additionally,
fuse_new_31 was missing in the version script and was therefore
an unusable symbol.

This also adds a test for unset HAVE_LIBC_VERSIONED_SYMBOLS.
2023-01-04 15:27:21 +00:00
Bernd Schubert
8d934122df Fix a test strncpy compilation warning with recent gcc
meson configure -D buildtype=debugoptimized
meson configure -D b_sanitize=address,undefined

Results in '-fsanitize=address,undefined ... -O2 -g' that made
compilation to give errors with recent gcc versions.


bernd@t1700bs build-ubuntu>ninja -v
[1/2] ccache gcc -Itest/test_syscalls.p -Itest -I../test -Iinclude -I../include -Ilib -I../lib -I. -I.. -fdiagnostics-color=always -fsanitize=address,undefined -fno-omit-frame-pointer -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -O2 -g -D_REENTRANT -DHAVE_CONFIG_H -Wno-sign-compare -Wstrict-prototypes -Wmissing-declarations -Wwrite-strings -fno-strict-aliasing -Wno-unused-result -DHAVE_SYMVER_ATTRIBUTE -MD -MQ test/test_syscalls.p/test_syscalls.c.o -MF test/test_syscalls.p/test_syscalls.c.o.d -o test/test_syscalls.p/test_syscalls.c.o -c ../test/test_syscalls.c
FAILED: test/test_syscalls.p/test_syscalls.c.o
ccache gcc -Itest/test_syscalls.p -Itest -I../test -Iinclude -I../include -Ilib -I../lib -I. -I.. -fdiagnostics-color=always -fsanitize=address,undefined -fno-omit-frame-pointer -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -O2 -g -D_REENTRANT -DHAVE_CONFIG_H -Wno-sign-compare -Wstrict-prototypes -Wmissing-declarations -Wwrite-strings -fno-strict-aliasing -Wno-unused-result -DHAVE_SYMVER_ATTRIBUTE -MD -MQ test/test_syscalls.p/test_syscalls.c.o -MF test/test_syscalls.p/test_syscalls.c.o.d -o test/test_syscalls.p/test_syscalls.c.o -c ../test/test_syscalls.c
In file included from /usr/include/string.h:519,
                 from ../test/test_syscalls.c:7:
In function ‘strncpy’,
    inlined from ‘test_socket’ at ../test/test_syscalls.c:1885:2,
    inlined from ‘main’ at ../test/test_syscalls.c:2030:9:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:95:10: error: ‘__builtin_strncpy’ output may be truncated copying 107 bytes from a string of length 1023 [-Werror=stringop-truncation]
   95 |   return __builtin___strncpy_chk (__dest, __src, __len,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   96 |                                   __glibc_objsize (__dest));
      |                                   ~~~~~~~~~~~~~~~~~~~~~~~~~



I disagree a bit on the gcc sanity here, as the code was behaving
correctly and even already checked the string length. But sice
the string length is already verified, that length can be used
for the final strncpy.
2022-05-06 21:21:06 +01:00
Amir Goldstein
435a14e029 Add test for FOPEN_NOFLUSH flag
Simulate write() delay and verify that close(rofd) does not
block waiting on pending writes.

The support for the flag was added in kernel v5.16-rc1.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
2022-01-05 08:43:43 +02:00
Luis Henriques
cee6de8d66
test/test_syscalls.c: allow EBADF in fcheck_stat() (#631)
Test test/test_examples.py::test_passthrough_hp[False] fails because, on
kernels >= 5.14, fstat() will return -EBADF:

3 [check_unlinked_testfile] fcheck_stat() - fstat: Bad file descriptor
4 [check_unlinked_testfile] fcheck_stat() - fstat: Bad file descriptor
5 [check_unlinked_testfile] fcheck_stat() - fstat: Bad file descriptor
9 [check_unlinked_testfile] fcheck_stat() - fstat: Bad file descriptor
...

This patch simply whitelists the EBADF errno code.

Signed-off-by: Luís Henriques <lhenriques@suse.de>
Co-authored-by: Luís Henriques <lhenriques@suse.de>
2021-11-20 10:09:25 +00:00
Nikolaus Rath
624327ba00 Travis-CI: Make sure lsan supppressions file can be read by root. 2021-06-24 09:11:29 +01:00
Amir Goldstein
570933394e Do not run unlinked files test on passthrough_hp with old kernels
test_syscalls unlinked testfiles check fails on passthourhg_hp without
the kernel commit "fuse: fix illegal access to inode with reused nodeid"
queued for kernel 5.14 [1].

Make this check opt-in and do not run it with kernel version before 5.14.

[1] https://lore.kernel.org/linux-fsdevel/CAJfpegtGKjeK8E5QsHKF0=re1J9wVHuGRVgg9NDJ_OOwQdCUNg@mail.gmail.com/

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
2021-06-23 11:46:19 +01:00
Amir Goldstein
10ecd4fda4 test/test_syscalls.c: check unlinked testfiles at the end of the test
On some tests on regular files, open an O_PATH fd of the testfile and
record it along side the size and mode and inode.

At the end of all tests, use recorded testfiles info to re-check the size
mode and inode of the unlinked testfiles.

With O_PATH fd, the server does not have to keep the inode alive so FUSE
inode may be stale or bad.  Therefore, ESTALE and EIO are valid results
for fstat() on the old testfile fd's, but returning the wrong size or
mode is an invalid result.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
2021-06-14 09:13:12 +01:00
Amir Goldstein
494e15127c test/test_syscalls.c: refactor fcheck_* helpers
Avoid multiple fstat() calls and consolidate all fcheck_* helpers
into fcheck_stat().

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
2021-06-14 09:13:12 +01:00
Amir Goldstein
057d6de867 test/test_syscalls.c: use unique filename per test
Generate unique filename per test (only for regular file for now).
Make sure to unlink the unique filename after each test.

realpath variable was renamed to basepath_r to fix build warning
on conflicting symbols with realpath() function.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
2021-06-14 09:13:12 +01:00
Christian Menges
57b46adc35
Cuse example: Fix memory leak (#607)
* cuse example: fix memory leak

* Travis CI: re-enable leak checking
2021-06-09 09:04:41 +01:00
Amir Goldstein
8852a22399
test/test_syscalls.c: fix test failure on xfs src dir (#611)
rename dir loop test fails when test tmp dir is xfs with an error
 test_rename_dir_loop() - rename : File exists

That is because xfs returns EEXIST for the case of renaming over
a non-empty directory.

According to rename(2) man page, EEXIST and ENOTEMPTY are both valid
error code in this case.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
2021-06-02 10:23:06 +01:00
Jean-Pierre André
bdd2d4110f
Fix returning d_ino and d_type by readdir(3) in non-plus mode
When not using the readdir_plus mode, the d_type was not returned,
and the use_ino flag was not used for returning d_ino.

This patch fixes the returned values for d_ino and d_type by readdir(3)

The test for the returned value of d_ino has been adjusted to also
take the d_type into consideration and to check the returned values in
both basic readdir and readdir_plus modes. This is done by executing
the passthrough test twice.

Co-authored-by: Jean-Pierre André <jpandre@users.sourceforge.net>
2021-03-18 09:52:30 +00:00
Martin Pärtel
5012a05ac8
Fix returning inode numbers from readdir() in offset==0 mode. (#584)
- Test added for all passthrough examples.
- passthrough.c uses offset==0 mode. The others don't.
- passthrough.c changed to set FUSE_FILL_DIR_PLUS to make the test pass.
- This fixes #583.
2021-02-03 09:53:21 +00:00
Zhiqiang Liu
71f0d7c366 test/test_syscalls.c: fix potential fd leakage problems
In test_syscalls.c, several funcs have potential fd leakage
problems. This patch will fix them.

Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
Signed-off-by: Haotian Li <lihaotian9@huawei.com>
2020-11-06 19:26:03 +00:00
Tom Callaway
d7d08595e2
Update Travis to Ubuntu Bionic 2020-09-12 09:28:27 +01:00
Tom Callaway
83f6823855
Implement GCC 10 style symbol versioning (#545) 2020-09-11 10:15:43 +01:00
Seunghoon Yeon
5021d6a0a1
Typo fixed. (#520) 2020-06-22 06:27:58 +01:00
Rosen Penev
c3f6de8549
fix format in test (#515)
Fixes warning under 32-bit.
2020-05-15 19:34:31 +01:00
Dr. David Alan Gilbert
252e978c54
State GPL version in comment (#485)
IN a bunch of comments we say 'under the terms of the GNU GPL', make
it clear this is GPLv2 (as LICENSE says).

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
2020-03-13 16:46:44 +00:00
philmd
29b71ac481
Travis-CI: Fix ImportError: No module named 'zipp' (#502)
Upgrade pip to fix [*]:

  [66/66] Linking target example/passthrough_hp.
  Traceback (most recent call last):
    File "/usr/lib/python3.5/runpy.py", line 174, in _run_module_as_main
      mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
    File "/usr/lib/python3.5/runpy.py", line 133, in _get_module_details
      return _get_module_details(pkg_main_name, error)
    File "/usr/lib/python3.5/runpy.py", line 109, in _get_module_details
      __import__(pkg_name)
    File "/usr/local/lib/python3.5/dist-packages/pytest/__init__.py", line 6, in <module>
      from _pytest.assertion import register_assert_rewrite
    File "/usr/local/lib/python3.5/dist-packages/_pytest/assertion/__init__.py", line 7, in <module>
      from _pytest.assertion import rewrite
    File "/usr/local/lib/python3.5/dist-packages/_pytest/assertion/rewrite.py", line 24, in <module>
      from _pytest.assertion import util
    File "/usr/local/lib/python3.5/dist-packages/_pytest/assertion/util.py", line 14, in <module>
      import _pytest._code
    File "/usr/local/lib/python3.5/dist-packages/_pytest/_code/__init__.py", line 2, in <module>
      from .code import Code  # noqa
    File "/usr/local/lib/python3.5/dist-packages/_pytest/_code/code.py", line 28, in <module>
      import pluggy
    File "/usr/local/lib/python3.5/dist-packages/pluggy/__init__.py", line 16, in <module>
      from .manager import PluginManager, PluginValidationError
    File "/usr/local/lib/python3.5/dist-packages/pluggy/manager.py", line 11, in <module>
      import importlib_metadata
    File "/usr/local/lib/python3.5/dist-packages/importlib_metadata/__init__.py", line 9, in <module>
      import zipp
  ImportError: No module named 'zipp'
  The command "test/travis-build.sh" exited with 1.

[*] https://travis-ci.org/libfuse/libfuse/builds/651523034

Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2020-02-24 21:41:28 +00:00
Anthony Rebello
aaa5c0931e Fixes 477, optional src_dir in tst_(rmdir,unlink) (#493)
tst_rmdir and tst_unlink now pass for passthrough_hp.

Previously, tst_rmdir and tst_unlink created the directory / file
using src_dir, causing the test to fail as the cache was stale.
Now, the src_dir is optional. When cache is enabled, tst_rmdir
and tst_unlink do not provide a src_dir, forcing the test to
use mnt_dir itself.
2020-01-25 10:17:09 +00:00
Nikolaus Rath
bb52fccb59 Invoke cleanup() with right arguments.
This currently causes hangs if the test fails, cf issue #459.
2019-11-20 11:38:33 +00:00
Stefan Hajnoczi
f39c71dcf9 Avoid gcc 9.1 strncpy(3) warnings (#447)
Recent GCC releases have warnings related to common strncpy(3) bugs.
These warnings can be avoided by explicitly NUL-terminating the buffer
or using memcpy(3) when the intention is to copy just the characters
without the NUL terminator.

This commit fixes the following warnings:

  [1/27] Compiling C object 'test/9f86d08@@test_syscalls@exe/test_syscalls.c.o'.
  In function ‘test_socket’,
      inlined from ‘main’ at ../test/test_syscalls.c:1899:9:
  ../test/test_syscalls.c:1760:2: warning: ‘strncpy’ output may be truncated copying 108 bytes from a string of length 1023 [-Wstringop-truncation]
   1760 |  strncpy(su.sun_path, testsock, sizeof(su.sun_path));
        |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  [2/27] Compiling C object 'lib/76b5a35@@fuse3@sha/fuse.c.o'.
  ../lib/fuse.c: In function ‘add_name’:
  ../lib/fuse.c:968:2: warning: ‘strncpy’ output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation]
    968 |  strncpy(s, name, len);
        |  ^~~~~~~~~~~~~~~~~~~~~
  ../lib/fuse.c:944:15: note: length computed here
    944 |  size_t len = strlen(name);
        |               ^~~~~~~~~~~~
  [3/27] Compiling C object 'lib/76b5a35@@fuse3@sha/fuse_lowlevel.c.o'.
  ../lib/fuse_lowlevel.c: In function ‘fuse_add_direntry’:
  ../lib/fuse_lowlevel.c:288:2: warning: ‘strncpy’ output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation]
    288 |  strncpy(dirent->name, name, namelen);
        |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ../lib/fuse_lowlevel.c:276:12: note: length computed here
    276 |  namelen = strlen(name);
        |            ^~~~~~~~~~~~
  ../lib/fuse_lowlevel.c: In function ‘fuse_add_direntry_plus’:
  ../lib/fuse_lowlevel.c:381:2: warning: ‘strncpy’ output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation]
    381 |  strncpy(dirent->name, name, namelen);
        |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ../lib/fuse_lowlevel.c:366:12: note: length computed here
    366 |  namelen = strlen(name);
        |            ^~~~~~~~~~~~

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2019-08-29 20:28:29 +01:00
Nikolaus Rath
65075085b5 Do not run passthrough test when caching is active.
Readdir caching means that direct modifications to the source
directory will not be seen immediately, so the test becomes flaky.

Fixes: #416.
2019-07-09 05:29:49 -07:00
Nikolaus Rath
4cfbc27d4e
test_cuse: fix runtime error
We are no longer using the capfd mechanism.
2019-07-05 11:03:31 +01:00
Nikolaus Rath
1343f59c27 Fix output checking in test cases
py.test's capture plugin does not work reliably when used by
other fixtures. Therefore, implement our own version.
2019-07-04 21:20:41 +01:00
Alan Somers
1f842c996e passthrough: fix unix-domain sockets on FreeBSD (#413)
FreeBSD doesn't allow creating sockets using mknod(2). Instead, one has to use socket(2)
and bind(2).  Add appropriate logic to the examples and add a test case.
2019-05-15 21:35:57 +01:00
Nikolaus Rath
055f272517 Added new example filesystem
passthrough_hp puts emphasis and performance and correctness, rather
than simplicity.
2019-05-09 14:16:37 -05:00
maxice8
b1b06d1920 Define ALLPERMS for musl libc systems. (#379) 2019-03-11 17:32:45 +00:00
Tomohiro Kusumi
b394699a66 Work around -Wformat-truncation=/-Wformat-overflow= warnings (#356)
sprintf(3)/snprintf(3) destination buffers need to be large enough
so that gcc doesn't warn -Wformat-truncation= or -Wformat-overflow=
when source buffer size is 1024 bytes.

--
../test/test_syscalls.c:1445:47: warning: '%s' directive output may be truncated writing 1 byte into a region of size between 0 and 1023 [-Wformat-truncation=]
 #define PATH(p)  (snprintf(path, sizeof path, "%s/%s", testdir, p), path)
                                               ^~~~~~~
../test/test_syscalls.c:1458:19:
  res = mkdir(PATH("a"), 0755);
                   ~~~

Signed-off-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
2019-03-09 10:39:02 +00:00
Alan Somers
1b7d2b8862 Document fuse_fsync_in.fsync_flags and remove magic numbers (#375) 2019-03-08 21:24:50 +00:00
Nikolaus Rath
86ebe1d2df Travis CI: Use Xenial instead of Trusty. 2019-02-27 21:20:58 +00:00
Nikolaus Rath
b35afb000a Added testcase for "big" readdir. 2018-11-24 20:51:47 +00:00
Nikolaus Rath
68f177d238 Kill filesystem process on test cleanup. 2018-11-24 20:51:34 +00:00
Niels de Vos
0c73b8389a tests: add copy_file_range() to the syscall tests 2018-11-19 12:33:56 +00:00
Nikolaus Rath
df37856738 Update CI build script
There is no gcc-6 package anymore.
2018-11-06 18:54:06 +00:00