4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-18 23:12:15 +08:00

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>
This commit is contained in:
Corinna Vinschen 2021-05-25 20:19:19 +02:00
parent 517c7e79da
commit efef4b8bf1
2 changed files with 110 additions and 5 deletions

View File

@ -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 ();

View File

@ -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;
}