public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: POSIX msg queues: implement read(2)/lseek(2)
@ 2021-05-25 18:20 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2021-05-25 18:20 UTC (permalink / raw)
  To: cygwin-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=efef4b8bf1eadb17b2696d724106724dcd941305

commit efef4b8bf1eadb17b2696d724106724dcd941305
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Tue May 25 20:19:19 2021 +0200

    Cygwin: POSIX msg queues: implement read(2)/lseek(2)
    
    reuse fhandler_virtual implementation to implement read and lseek.
    The output from read(2) is modelled after the output when reading
    from an mq file on Linux.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/fhandler.h         |  14 ++++--
 winsup/cygwin/fhandler_mqueue.cc | 101 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 110 insertions(+), 5 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 7152482ed..5e298a82f 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -3106,6 +3106,10 @@ class fhandler_timerfd : public fhandler_base
 class fhandler_mqueue: public fhandler_disk_file
 {
   struct mq_info mqi;
+  /* Duplicate filebuf usage of fhandler_virtual */
+  char *filebuf;
+  off_t filesize;
+  off_t position;
 
   struct mq_info *_mqinfo (SIZE_T, mode_t, int, bool);
 
@@ -3115,6 +3119,8 @@ class fhandler_mqueue: public fhandler_disk_file
 
   int _dup (HANDLE parent, fhandler_mqueue *child);
 
+  bool fill_filebuf ();
+
   int mutex_lock (HANDLE mtx, bool eintr);
   int mutex_unlock (HANDLE mtx);
   int cond_timedwait (HANDLE evt, HANDLE mtx, const struct timespec *abstime);
@@ -3123,7 +3129,7 @@ class fhandler_mqueue: public fhandler_disk_file
 public:
   fhandler_mqueue ();
   fhandler_mqueue (void *) {}
-  ~fhandler_mqueue () {}
+  ~fhandler_mqueue ();
 
   fhandler_mqueue *is_mqueue () { return this; }
 
@@ -3143,8 +3149,10 @@ public:
 
   void fixup_after_fork (HANDLE);
 
-  int __reg2 fstat (struct stat *buf);
-  int dup (fhandler_base *child, int);
+  void __reg3 read (void *, size_t&);
+  off_t lseek (off_t, int);
+  int __reg2 fstat (struct stat *);
+  int dup (fhandler_base *, int);
   int ioctl (unsigned int, void *);
   int close ();
 
diff --git a/winsup/cygwin/fhandler_mqueue.cc b/winsup/cygwin/fhandler_mqueue.cc
index d1aa8c8e3..04a6c3611 100644
--- a/winsup/cygwin/fhandler_mqueue.cc
+++ b/winsup/cygwin/fhandler_mqueue.cc
@@ -12,19 +12,28 @@ details. */
 #include "fhandler.h"
 #include "dtable.h"
 #include "clock.h"
+#include <stdio.h>
 #include <mqueue.h>
 #include <sys/param.h>
 
 #define MSGSIZE(i)      roundup((i), sizeof(long))
 
+#define FILESIZE	80
+
 struct mq_attr defattr = { 0, 10, 8192, 0 };	/* Linux defaults. */
 
 fhandler_mqueue::fhandler_mqueue () :
   fhandler_disk_file ()
 {
+  filebuf = (char *) ccalloc_abort (HEAP_BUF, 1, FILESIZE);
   close_on_exec (true);
 }
 
+fhandler_mqueue::~fhandler_mqueue ()
+{
+  cfree (filebuf);
+}
+
 int
 fhandler_mqueue::open (int flags, mode_t mode)
 {
@@ -344,12 +353,97 @@ fhandler_mqueue::get_proc_fd_name (char *buf)
   return strcpy (buf, strrchr (get_name (), '/'));
 }
 
+/* Do what fhandler_virtual does for read/lseek */
+bool
+fhandler_mqueue::fill_filebuf ()
+{
+  unsigned long qsize = 0;
+  int notify = 0;
+  int signo = 0;
+  int notify_pid = 0;
+
+  if (mutex_lock (mqinfo ()->mqi_lock, true) == 0)
+    {
+      struct mq_hdr *mqhdr = mqinfo ()->mqi_hdr;
+      int8_t *mptr = (int8_t *) mqhdr;
+      struct msg_hdr *msghdr;
+      for (long index = mqhdr->mqh_head; index; index = msghdr->msg_next)
+	{
+	  msghdr = (struct msg_hdr *) &mptr[index];
+	  qsize += msghdr->msg_len;
+	}
+      if (mqhdr->mqh_pid)
+	{
+	  notify = mqhdr->mqh_event.sigev_notify;
+	  if (notify == SIGEV_SIGNAL)
+	    signo = mqhdr->mqh_event.sigev_signo;
+	  notify_pid = mqhdr->mqh_pid;
+	}
+      mutex_unlock (mqinfo ()->mqi_lock);
+    }
+  /* QSIZE:      bytes of all current msgs
+     NOTIFY:     sigev_notify if there's a notifier
+     SIGNO:      signal number if NOTIFY && sigev_notify == SIGEV_SIGNAL
+     NOTIFY_PID: if NOTIFY pid */
+  snprintf (filebuf, FILESIZE,
+	    "QSIZE:%-10lu NOTIFY:%-5d SIGNO:%-5d NOTIFY_PID:%-6d\n",
+	    qsize, notify, signo, notify_pid);
+  filesize = strlen (filebuf);
+  return true;
+}
+
+void __reg3
+fhandler_mqueue::read (void *in_ptr, size_t& len)
+{
+  if (len == 0)
+    return;
+  if (!filebuf[0] && !fill_filebuf ())
+    {
+      len = (size_t) -1;
+      return;
+    }
+  if ((ssize_t) len > filesize - position)
+    len = (size_t) (filesize - position);
+  if ((ssize_t) len < 0)
+    len = 0;
+  else
+    memcpy (in_ptr, filebuf + position, len);
+  position += len;
+}
+
+off_t
+fhandler_mqueue::lseek (off_t offset, int whence)
+{
+  if (!fill_filebuf ())
+    return (off_t) -1;
+  switch (whence)
+    {
+    case SEEK_SET:
+      position = offset;
+      break;
+    case SEEK_CUR:
+      position += offset;
+      break;
+    case SEEK_END:
+      position = filesize + offset;
+      break;
+    default:
+      set_errno (EINVAL);
+      return (off_t) -1;
+    }
+  return position;
+}
+
+
 int __reg2
 fhandler_mqueue::fstat (struct stat *buf)
 {
   int ret = fhandler_disk_file::fstat (buf);
   if (!ret)
-    buf->st_dev = FH_MQUEUE;
+    {
+      buf->st_size = FILESIZE;
+      buf->st_dev = FH_MQUEUE;
+    }
   return ret;
 }
 
@@ -400,7 +494,10 @@ fhandler_mqueue::dup (fhandler_base *child, int flags)
 
   int ret = fhandler_disk_file::dup (child, flags);
   if (!ret)
-    ret = _dup (GetCurrentProcess (), fhc);
+    {
+      memcpy (fhc->filebuf, filebuf, FILESIZE);
+      ret = _dup (GetCurrentProcess (), fhc);
+    }
   return ret;
 }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-05-25 18:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-25 18:20 [newlib-cygwin] Cygwin: POSIX msg queues: implement read(2)/lseek(2) Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).