aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2021-05-25 20:19:19 +0200
committerCorinna Vinschen <corinna@vinschen.de>2021-05-25 20:19:19 +0200
commitefef4b8bf1eadb17b2696d724106724dcd941305 (patch)
tree940754d1f7583546c502d2e20f30a4cba8856f5f
parent517c7e79da0a64d8e732409d2c65693cbc931bf3 (diff)
downloadnewlib-efef4b8bf1eadb17b2696d724106724dcd941305.zip
newlib-efef4b8bf1eadb17b2696d724106724dcd941305.tar.gz
newlib-efef4b8bf1eadb17b2696d724106724dcd941305.tar.bz2
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>
-rw-r--r--winsup/cygwin/fhandler.h14
-rw-r--r--winsup/cygwin/fhandler_mqueue.cc101
2 files changed, 110 insertions, 5 deletions
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 7152482..5e298a8 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 d1aa8c8..04a6c36 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;
}