Commit Graph

315 Commits

Author SHA1 Message Date
Takashi Yano b03601a671 Cygwin: fstat(): Fix st_rdev returned by fstat() for /dev/tty.
While st_rdev returned by fstat() for /dev/tty should be FH_TTY,
the current cygwin1.dll returns FH_PTYS+minor or FH_CONS+minor.
Similarly, fstat() does not return correct value for /dev/console,
/dev/conout, /dev/conin or /dev/ptmx.

This patch fixes the issue by:
1) Introduce dev_referred_via in fhandler_termios.
2) Add new argument, which has dev_t value referred by open(),
  for constructors of fhandler_pty_slave and fhandler_pty_master to
  set the value of dev_referred_via.
3) Set st_rdev using dev_referred_via in fhandler_termios::fstat()
  if it is available.

Reviewed-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
2023-07-08 08:03:22 +09:00
Takashi Yano 3edb55af82 Cygwin: stat(): Fix "Bad address" error on stat() for /dev/tty.
As reported in
https://cygwin.com/pipermail/cygwin/2023-June/253888.html,
"Bad address" error occurs when stat() is called after the commit
3721a756b0 ("Cygwin: console: Make the console accessible from
other terminals.").

There are two problems in the current code. One is fhandler_console::
fstat() calls get_ttyp()->getsid(). However, fh_alloc() in dtable.cc
omits to initialize the fhandler_console instance when stat() is
called. Due to this, get_ttyp() returns NULL and access violation
occurs. The other problem is fh_alloc() assigns fhandler_console
even if the CTTY is not a console. So the first problem above occurs
even if the CTTY is a pty.

This patch fixes the issue by:
1) Call set_unit() to initialize _tc if the get_ttyp() returns NULL.
2) Assign fhandler_pty_slave for /dev/tty if CTTY is a pty in fh_alloc().

Fixes: 3721a756b0 ("Cygwin: console: Make the console accessible
  from other terminals.").
Fixes: 23771fa1f7 ("dtable.cc (fh_alloc): Make different decisions
  when generating fhandler for not-opened devices. Add kludge to deal
  with opening /dev/tty.")
Reported-by: Bruce Jerrick <bmj001@gmail.com>
Reviewed-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
2023-07-08 08:03:16 +09:00
Takashi Yano 93f70d7849 Cygwin: ctty: Remove old 'kludge' code.
Remove old 'kludge' code which does not seem necessary anymore. The
comment of the 'kludge' is as follows.

  * syscalls.cc (setsid): On second thought, in the spirit of keeping
    things kludgy, set ctty to -2 here as a special flag, and...
    (open): ...only eschew setting O_NOCTTY when that case is detected.

Fixes: c38a2d8373
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
2023-03-07 10:51:44 +09:00
Takashi Yano 13a84ac79b Cygwin: ctty: Replace ctty constant with more descriptive macros.
This patch replaces ctty constants with more descriptive macros
(CTTY_UNINITIALIZED and CTTY_RELEASED) rather than -1 and -2 as
well as checking sign with CTTY_IS_VALID().

Fixes: 3b7df69aaa (Cygwin: ctty: Add comments for the special values: -1 and -2.)
Suggested-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
2023-03-07 10:51:29 +09:00
Takashi Yano 523985b31e Cygwin: ctty: Add missing fixup_after_{exec,fork}() call.
Previously, fixup_after_{exec,fork}() calls for CTTY were missing.
This patch fixes that.

Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
2023-03-07 10:14:25 +09:00
Ken Brown 30c5411d07 Cygwin: remove most occurrences of __stdcall and __cdecl
These have no effect on x86_64.  Retain a few occurrences of __cdecl
in files imported from other sources.

Also retain all occurrences of WINAPI, even though the latter is
simply a macro that expands to __stdcall.  Most of these occurrences
are associated with Windows API functions, and removing them might
make the code confusing instead of simpler.
2022-06-06 12:00:45 -04:00
Johannes Schindelin 4ec08891a0 Cygwin: Implicitly support the /dev/fd symlink and friends
Bash has a very convenient feature that is called process substitution
(e.g. `diff -u <(seq 0 10) <(seq 1 11)`). To make this work, Bash
requires the `/dev/fd` symlink to exist, and Cygwin therefore creates
this symlink (together with the `stdin`, `stdout` and `stderr` ones)
upon start-up.

This strategy is incompatible with the idea of providing a subset of
Cygwin in a `.zip` file (because there is no standard way to represent
symlinks in `.zip` files, and besides, older Windows versions would
potentially lack support for them anyway).

That type of `.zip` file is what Git for Windows wants to use, though,
bundling a minimal subset for third-party applications in MinGit (see
https://github.com/git-for-windows/git/wiki/MinGit for details).

Let's side-step this problem completely by creating those symlinks
implicitly, similar to the way `/dev/` is populated with special
devices.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2022-02-22 13:33:00 +01:00
Takashi Yano 2cab4d0bb4 Cygwin: pty, console: Refactor the code processing special keys.
- This patch commonize the code which processes special keys in pty
  and console to improve maintanancibility. As a result, some small
  bugs have been fixed.
2022-02-20 19:21:51 +09:00
Takashi Yano 90788821b7 Cygwin: pipe: Restore blocking mode for cygwin process at startup.
- Set blocking mode properly at startup of cygwin process. This is
  needed if the cygwin process is executed from non-cygwin process.
2021-12-12 22:14:29 +09:00
Ken Brown be08c5c40b Cygwin: make callers of open_setup check for failure
open_setup is called by dtable::init_std_file_from_handle and
fhandler_base::open_with_arch.  In both cases, failure of open_setup
is now a fatal error.

Currently this can only happen in the following situation: A Cygwin
process is started by a non-Cygwin process, one of the standard IO
handles is a pipe handle, and Cygwin is unable to create a required
mutex (read_mtx or hdl_cnt_mtx).
2021-09-18 09:10:23 -04:00
Ken Brown 99be238347 Cygwin: set buffer size for pipes created by non-Cygwin processes
Rename fhandler_pipe_and_fifo::max_atomic_write to pipe_buf_size.
This reflect its actual meaning better.  The fhandler_pipe_and_fifo
constructor initializes it to DEFAULT_PIPEBUFSIZE (== 64K), which is
the buffer size for the windows pipes created by fhandler_pipe and
fhandler_fifo.  But if we inherit a stdio pipe handle from a
non-Cygwin process, the buffer size could be different.

To remedy this, add a method fhandler_pipe::set_pipe_buf_size that
queries the OS for the pipe buffer size, and use it in
dtable::init_std_file_from_handle.
2021-09-13 17:45:54 +02:00
Corinna Vinschen 4fc922b2c8 Cygwin: POSIX msg queues: Convert mqd_t to a descriptor
So far, the mqd_t type returned a pointer to an allocated
area under the hood.  The mutex and event objects attached
to the message queue were implemented as inheritable types.

As unfortunate side effect the HANDLEs to these objects
were inherited by exec'd child processes, even though all
other message queue properties are not inherted, per POSIX.

Fix this by converting an mqd_t to a descriptor, and create a
matching fhandler_mqueue object to handle various aspects of
the message queues inside the fhandler.  Especially, create the
IPC objects as non-inheritable and duplicate the HANDLEs as
part of the fixup_after_fork mechanism.

Drop using mmap and create the memory map with NT functions.
This allows to control duplication of handle and mapping in the
forked child process, without the requirement to regenerate the
map in the same spot.  It also allows to dup() the descriptor,
as on Linux, albeit this isn't implemented yet.

This patch is the first cut.  There's a bit more to do, like
moving more functionality from the POSIX functions into the
fhandler and making sure the mqd_t type can't be used in other
descriptor-related functions willy-nilly.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2021-05-21 13:43:24 +02:00
Corinna Vinschen 5f0913df13 Cygwin: drop path_conv::reset_conv_handle
path_conv::reset_conv_handle is only called after fhandler::copyto
has been called.  This duplicated the path_conv_handle if there was
one, so just setting the conv handle to NULL potentially produces a
handle leak.  Replace reset_conv_handle calls with calls to
close_conv_handle and drop the reset_conv_handle method.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2021-02-10 10:42:38 +01:00
Ken Brown 5b8358e6ed Cygwin: remove the OPEN_MAX_MAX macro
Replace all occurrences of OPEN_MAX_MAX by OPEN_MAX, and define the
latter to be 3200, which was the value of the former.  In view of the
recent change to getdtablesize, there is no longer a need to
distinguish between these two macros.
2021-02-01 09:55:08 -05:00
Ken Brown b6624e23e1 Cygwin: dtable::dup_worker: update comment and debug output
The comment and debug output became obsolete in commit 23771fa1f7 when
dup_worker started calling fhandler_base::clone instead of build_fh_pc
and fhandler_base::operator=.
2020-12-07 16:19:57 -05:00
Takashi Yano bb42852062 Cygwin: pty: Implement new pseudo console support.
- In this implementation, pseudo console is created for each native
  console app. Advantages and disadvantages of this implementation
  over the previous implementation are as follows.

  Advantages:
  1) No performance degradation in pty output for cygwin process.
      https://cygwin.com/pipermail/cygwin/2020-February/243858.html
  2) Free from the problem caused by difference of behaviour of control
     sequences between real terminal and pseudo console.
      https://cygwin.com/pipermail/cygwin/2019-December/243281.html
      https://cygwin.com/pipermail/cygwin/2020-February/243855.html
  3) Free from the problem in cgdb and emacs gud.
      https://cygwin.com/pipermail/cygwin/2020-January/243601.html
      https://cygwin.com/pipermail/cygwin/2020-March/244146.html
  4) Redrawing screen on executing native console apps is not necessary.
  5) cygwin-console-helper is not necessary for the pseudo console
     support.
  6) The codes for pseudo console support are much simpler than that
     of the previous one.

  Disadvantages:
  1) The cygwin program which calls console API directly does not work.
  2) The apps which use console API cannot be debugged with gdb. This
     is because pseudo console is not activated since gdb uses
     CreateProcess() rather than exec(). Even with this limitation,
     attaching gdb to native apps, in which pseudo console is already
     activated, works.
  3) Typeahead key inputs are discarded while native console app is
     executed. Simirally, typeahead key inputs while cygwin app is
     executed are not inherited to native console app.
  4) Code page cannot be changed by chcp.com. Acctually, chcp works
     itself and changes code page of its own pseudo console.  However,
     since pseudo console is recreated for another process, it cannot
     inherit the code page.
  5) system_printf() does not work after stderr is closed. (Same with
     cygwin 3.0.7)
  6) Startup time of native console apps is about 3 times slower than
     previous implemenation.
  7) Pseudo console cannot be activated if it is already activated for
     another process on same pty.
2020-08-22 13:43:49 +02:00
Corinna Vinschen d2ef2331f9 Cygwin: fix formatting: drop spaces leading tabs
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2020-03-11 13:45:58 +01:00
Takashi Yano edb1be4cce Cygwin: pty: Convert CamelCase names to snake_case names. 2019-11-18 11:12:08 +01:00
Takashi Yano 3355a6d4b9 Cygwin: pty: Switch input and output pipes individually.
- Previously, input and output pipes were switched together between
  the traditional pty and the pseudo console. However, for example,
  if stdin is redirected to another device, it is better to leave
  input pipe traditional pty side even for non-cygwin program. This
  patch realizes such behaviour.
2019-09-14 09:19:04 -04:00
Takashi Yano b7e4294200 Cygwin: pty: Fix potential state mismatch regarding pseudo console.
- PTY with pseudo console support sitll has problem which potentially
  cause state mismatch between state variable and real console state.
  This patch fixes this issue.
2019-09-05 13:59:37 +02:00
Takashi Yano 583102e7c9 Cygwin: pty: Fix state management for pseudo console support.
- Pseudo console support introduced by commit
  169d65a577 has some bugs which
  cause mismatch between state variables and real pseudo console
  state regarding console attaching and r/w pipe switching. This
  patch fixes this issue by redesigning the state management.
2019-09-04 12:05:15 +02:00
Takashi Yano 169d65a577 Cygwin: pty: add pseudo console support.
- Support pseudo console in PTY. Pseudo console is a new feature
  in Windows 10 1809, which provides console APIs on virtual
  terminal. With this patch, native console applications can work
  in PTYs such as mintty, ssh, gnu screen or tmux.
2019-08-29 13:47:40 +02:00
Takashi Yano a9c661a94d Cygwin: [gs]et_io_handle(): renamed to [gs]et_handle().
- Unify get_io_handle() and get_handle() to get_handle().
  Both of them returned same value; io_handle.
- Rename set_io_handle() to set_handle().
2019-03-30 20:08:36 +01:00
Corinna Vinschen 0be0b8f033 Cygwin: execve: fix setting O_APPEND file offset for native child
dtable::set_file_pointers_for_exec is called from
child_info_spawn::worker to move the file position of O_APPEND
files to EOF if the child is a native child.

However, this only works correctly for the first O_APPEND
file descriptor:

- set_file_pointers_for_exec calls SetFilePointer.  The higher
  4 bytes of the desired file offset are given to SetFilePointer
  as pointer to a DWORD value.  On return, SetFilePointer returns
  the higher 4 bytes of the new file position in this DWORD.

- So for the second and subsequent descriptors the higher 4 byte
  of the file position depend on what the actual file position
  of the previous file has been set to:

- If the file is > 2 Gigs, the high offset will not be 0 anymore.

- If the desciptor points to a non-seekable file (i.e., a pipe
  or socket), SetFilePosition returns an error and sets the high
  position to -1.

Fix this by calling SetFilePointerEx instead, which does not
modify the incoming position value.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2019-02-09 15:36:02 +01:00
Corinna Vinschen 068182e26c Cygwin: timers: implement timerfd
First cut of a timerfd implementation.

Still TODO:
- fork/exec semantics
- timerfd_settime TFD_TIMER_CANCEL_ON_SET flag
- ioctl(TFD_IOC_SET_TICKS)
- bug fixes

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2019-01-15 22:02:33 +01:00
Corinna Vinschen 9d13a2995c Cygwin: signal: implement signalfd
First cut of a signalfd implementation.

Still TODO: Non-polling select.

This should mostly work as on Linux except for missing support
for some members of struct signalfd_siginfo, namely ssi_fd,
ssi_band (both SIGIO/SIGPOLL, not fully implemented) and ssi_trapno
(HW exception, required HW support).

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2019-01-13 23:13:33 +01:00
Corinna Vinschen 7aca27b4fe Cygwin: introduce fhandler_process_fd and add stat(2) handling
move special fd symlink code into own fhandler_process_fd class
to simplify further additions to /proc/PID/fd/DESCRIPTOR symlink
handling.

Add a method to handle stat(2) on such a proc fd symlink by handle.
This allows correct reply from stat(2) if the target file has been
deleted.  This eventually fixes `awk -f /dev/fd/3 3<<eof'.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2019-01-06 20:30:14 +01:00
Corinna Vinschen 6c55be9dbb Cygwin: Allow to build without experimental AF_UNIX code by default
Introduce __WITH_AF_UNIX preprocessor flag to enable the new code

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2018-06-26 16:31:17 +02:00
Corinna Vinschen 23b5ecdaf3 Cygwin: delete /dev/kmsg and thus fhandler_mailslot without substitution
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2018-03-25 12:38:14 +02:00
Corinna Vinschen 7f7532fafb Cygwin: Create empty fhandler_socket_unix
* Make distinct from AF_LOCAL for testing purposes.  This will have
  to be reverted as soon as fhandler_socket_unix goes life.

* Move saw_reuseaddr flag back to fhandler_socket status

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2018-02-23 21:00:43 +01:00
Corinna Vinschen 03f380c2bc Cygwin: drop unused device nodes and clean up socket devices
* Rename DEV_TCP_MAJOR to DEV_SOCK_MAJOR
* Drop FH_TCP, FH_UDP, FH_ICMP in favor of single FH_INET
* Drop FH_UNIX, FH_STREAM, FH_DGRAM in favor of single FH_LOCAL

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2018-02-23 13:32:51 +01:00
Corinna Vinschen 859d215b7e Cygwin: split out fhandler_socket into inet and local classes
First cut, still incomplete

* fhandler_socket is now base class for other socket classes
* fhandler_socket_inet handles AF_INET and AF_INET6 sockets
* fhandler_socket_local handles AF_LOCAL/AF_UNIX sockets
* finally get rid of fdsock by using set_socket_handle in accept4
* align file-related calls (fstat,  fstatvfs, fchown, fchmod, facl)
  to Linux.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2018-02-21 21:40:01 +01:00
Corinna Vinschen 00e9bf2bb3 Fix various OS-related comments
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2016-06-24 23:32:39 +02:00
Corinna Vinschen b2867a68b9 Handle up to 63 partitions per drive
Revamp device parsing code.  Introducing support for more partitions
into the shilka-generated parser has the unfortunate side-effect of
raising the size of the DLL by almost 2 Megs.  Therefore we split out
the handling for /dev/sdXY devices into a tiny bit of hand-written
code.

While at it, remove some unused cruft from devices.* and generally
clean up the device class to provide access methods instead of direct
access to members.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2016-06-23 16:56:41 +02:00
Corinna Vinschen 6e623e9320 Switching the Cygwin DLL to LGPLv3+, dropping commercial buyout option
Bump GPLv2+ to GPLv3+ for some files, clarify BSD 2-clause.

Everything else stays under GPLv3+.

New Linking Exception exempts resulting executables from LGPLv3 section 4.

Add CONTRIBUTORS file to keep track of licensing.

Remove 'Copyright Red Hat Inc' comments.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2016-06-23 10:09:17 +02:00
Corinna Vinschen 8e732f7f7f Remove MALLOC_CHECK and calls to it entirely
MALLOC_CHECK got useless with commit b259af5.  Remove it throughout.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
2016-04-01 14:04:09 +02:00
Corinna Vinschen d2bd82aa92 * path.h (path_conv): Make path_flags private. Rename known_suffix to
suffix and make private.  Rename normalized_path to posix_path and
	make privtae.  Accommodate name changes throughout in path_conv
	methods.
	(path_conv::known_suffix): New method.  Use throughout instead of
	accessing suffix directly.
	(path_conv::get_win32): Constify.
	(path_conv::get_posix): New method to read posix_path.  Use throughout
	instead of accessing normalized_path directly.
	(path_conv::set_posix): Rename from set_normalized_path.  Accommodate
	name change throughout.
	* spawn.cc (find_exec): Return POSIX path, not Win32 path.
2015-02-15 08:59:55 +00:00
Corinna Vinschen 1091d4404e * dtable.cc (dtable::init_std_file_from_handle): Mention that console
handles are kernel objects since Windows 8.
	* fhandler.h (enum conn_state): Add "listener" state.
	(class fhandler_socket): Drop listener status flag.
	(fhandler_socket::lseek): Return -1 and errno ESPIPE.
	(fhandler_serial::lseek): Ditto.
	* fhandler_socket.cc (fhandler_socket::listen): Set connect_state to
	listener.  Add comment.
	(fhandler_socket::accept4): Explicitely check if the socket is listening
	and fail with EINVAL, if not.  Explain why we have to do that.
	(fhandler_socket::recv_internal): Explicitely check if the socket is
	connected if it's a stream socket.  Explain why we have to do that.
	(fhandler_socket::getpeereid): Drop now redundant test.
2014-08-18 11:09:56 +00:00
Corinna Vinschen 9c36b394d9 * dtable.cc (handle_to_fn): Fix length parameter in call to
QueryDosDeviceW (CID 59936).
2014-05-19 11:17:59 +00:00
Christopher Faylor 09244c002e * cygheap.h (cygheap_fdnew): Avoid setting errno directly since it will have
been set by a previous function.
* dtable.h (dtable::extend): Accept second size_t argument.
* dtable.cc (dtable::extend): Accept second "min" argument which allows
checking for OPEN_MAX_MAX boundary conditions.
(dtable_init): Accommodate second argument to dtable::extend.
(dtable::find_unused_handle): Ditto.
* syscalls.cc (setdtablesize): Ditto.
(dup): Return any error passed by cygheap_fdnew() directly.
(getdtablesize): Just return dtable size directly.
2013-12-05 19:43:34 +00:00
Christopher Faylor 9915ebec8a * dtable.cc (dtable::find_unused_handle): When extending, always make sure that
there is a NOFILE_INCR chunk following the free fd.
2013-12-04 17:55:17 +00:00
Christopher Faylor 9262c05537 * dtable.cc (dtable::find_unused_handle): Break out of the right loop. 2013-12-01 19:17:56 +00:00
Christopher Faylor f456b9f6f8 * dtable.cc (dtable::find_unused_handle): Fix off-by-one error. Always exit
through the bottom.
(cygwin_attach_handle_to_fd): Make sure that fd tab is locked for the duration
of this function.
* dtable.h (dtable::lock): Make public.
(dtable::unlock): Ditto.
(dtable): Remove friends.
2013-12-01 17:52:48 +00:00
Corinna Vinschen eeaa47ef21 * dtable.cc (dtable::extend): Change local variable new_size to size_t
as well.

	* thread.cc: Fix comment.
2013-12-01 10:27:16 +00:00
Christopher Faylor 499494d2cc * dtable.h (dtable::first_fd_for_open): Change declaration to size_t.
(dtable::extend): Change parameter to size_t.
(dtable::find_unused_handle): Ditto.
* dtable.cc: Remove now-unused header.
(dtable::extend): Remove pointless test.  Change parameter to size_t.
(dtable::find_unused_handle): Rework to avoid MAX calculation in extend() call.
Change parameter to size_t.
2013-12-01 02:52:54 +00:00
Christopher Faylor 483c843a6a * dtable.cc (build_fh_pc): When creating an archetype, use native name rather
than unix name if name doesn't exist.
2013-12-01 02:09:22 +00:00
Corinna Vinschen bd1af1cab5 * dtable.cc: Include sys/param.h for MAX definition. 2013-11-24 13:01:25 +00:00
Eric Blake 3a4ce7315f dup2: fix off-by-one crash
* dtable.cc (dup3): Fix off-by-one.
(find_unused_handle): Reduce time spent expanding during dup.
* syscalls.cc (setdtablesize): Report error on invalid value.
2013-11-23 13:51:53 +00:00
Corinna Vinschen 4c4693008a Remove /dev/mem, /dev/kmem, /dev/port support.
* Makefile.in (DLL_OFILES): Drop fhandler_mem.o.
	(fhandler_mem_CFLAGS): Remove rule.
	* devices.in (enum fh_devices): Remove FH_MEM, FH_KMEM and FH_PORT.
	* devices.cc: Regenerate.
	* dtable.cc (fh_alloc): Drop handling for FH_MEM, FH_KMEM and FH_PORT.
	* fhandler.h (class fhandler_dev_mem): Remove.
	* fhandler_mem.cc: Remove file.
	* globals.cc (ro_u_pmem): Remove.
	* mmap.cc (fhandler_dev_mem::mmap): Remove.
	(fhandler_dev_mem::munmap): Remove.
	(fhandler_dev_mem::fixup_mmap_after_fork): Remove.
2013-07-15 13:54:27 +00:00
Corinna Vinschen 61522196c7 * Merge in cygwin-64bit-branch. 2013-04-23 09:44:36 +00:00