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

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

commit b62450cf172971c7805143a39c6c491a7a3c9785
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Tue May 25 16:49:04 2021 +0200

    Cygwin: POSIX msg queues: implement open/mq_open entirely in fhandler
    
    The mq_open call is just a framework now.  This patch moves the
    entire functionality into fhandler_mqueue.  To support standard
    OS calls (as on Linux), make fhandler_mqueue a derived class from
    fhandler_disk_file and keep the base handle the handle to the
    default stream, to allow implementing O_PATH functionlaity as well
    as reading from the file and NOT reading binary message queue data.
    
    Implement a standard fhandler_mqueue::open method, allowing, for
    instance, to touch a file under /dev/mqueue and if it doesn't exist,
    to create a message queue file.
    
    FIXME: This introduces a BAD HACK into path_conv::check, which needs
    reviewing.
    
    Keep the posix path intact in the fhandler, and change get_proc_fd_name
    accordingly to return only the basename plus leading slash for
    /proc/<PID>/fd.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/fhandler.h         |  19 ++-
 winsup/cygwin/fhandler_mqueue.cc | 271 ++++++++++++++++++++++++++++++++++++---
 winsup/cygwin/globals.cc         |   1 +
 winsup/cygwin/path.cc            |  12 ++
 winsup/cygwin/posix_ipc.cc       | 180 +++-----------------------
 5 files changed, 293 insertions(+), 190 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 0ffc5a697..4c8fe0f1f 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -3103,11 +3103,15 @@ class fhandler_timerfd : public fhandler_base
   }
 };
 
-class fhandler_mqueue: public fhandler_base
+class fhandler_mqueue: public fhandler_disk_file
 {
   struct mq_info mqi;
 
-  struct mq_info *_mqinfo (HANDLE, SIZE_T, mode_t, int, bool);
+  struct mq_info *_mqinfo (SIZE_T, mode_t, int, bool);
+
+  struct mq_info *mqinfo_create (struct mq_attr *, mode_t, int);
+  struct mq_info *mqinfo_open (int);
+  void mq_open_finish (bool success, bool created);
 
 public:
   fhandler_mqueue ();
@@ -3118,14 +3122,9 @@ public:
 
   char *get_proc_fd_name (char *);
 
-  struct mq_info *mqinfo_create (HANDLE _h, SIZE_T _s, mode_t _m, int _f)
-  {
-    return _mqinfo (_h, _s, _m, _f, false);
-  }
-  struct mq_info *mqinfo_open (HANDLE _h, SIZE_T _s, mode_t _m, int _f)
-  {
-    return _mqinfo (_h, _s, _m, _f, true);
-  }
+  int open (int, mode_t);
+  int mq_open (int, mode_t, struct mq_attr *);
+
   struct mq_info *mqinfo () { return &mqi; }
 
   void fixup_after_fork (HANDLE);
diff --git a/winsup/cygwin/fhandler_mqueue.cc b/winsup/cygwin/fhandler_mqueue.cc
index 5f97264cd..6b0d98d75 100644
--- a/winsup/cygwin/fhandler_mqueue.cc
+++ b/winsup/cygwin/fhandler_mqueue.cc
@@ -11,21 +11,124 @@ details. */
 #include "path.h"
 #include "fhandler.h"
 #include "dtable.h"
+#include <mqueue.h>
+#include <sys/param.h>
+
+#define MSGSIZE(i)      roundup((i), sizeof(long))
+
+struct mq_attr defattr = { 0, 10, 8192, 0 };	/* Linux defaults. */
 
 fhandler_mqueue::fhandler_mqueue () :
-  fhandler_base ()
+  fhandler_disk_file ()
 {
-  nohandle (true);
   close_on_exec (true);
 }
 
+int
+fhandler_mqueue::open (int flags, mode_t mode)
+{
+  /* FIXME: reopen by handle semantics missing yet */
+  flags &= ~(O_NOCTTY | O_PATH | O_BINARY | O_TEXT);
+  return mq_open (flags, mode, NULL);
+}
+
+int
+fhandler_mqueue::mq_open (int oflags, mode_t mode, struct mq_attr *attr)
+{
+  NTSTATUS status;
+  IO_STATUS_BLOCK io;
+  PUNICODE_STRING mqstream;
+  OBJECT_ATTRIBUTES oa;
+  struct mq_info *mqinfo = NULL;
+  bool created = false;
+
+  if ((oflags & ~(O_ACCMODE | O_CLOEXEC | O_CREAT | O_EXCL | O_NONBLOCK))
+      || (oflags & O_ACCMODE) == O_ACCMODE)
+    {
+      set_errno (EINVAL);
+      return 0;
+    }
+
+  /* attach a stream suffix to the NT filename, thus creating a stream. */
+  mqstream = pc.get_nt_native_path (&ro_u_mq_suffix);
+  pc.get_object_attr (oa, sec_none_nih);
+
+again:
+  if (oflags & O_CREAT)
+    {
+      /* Create and disallow sharing */
+      status = NtCreateFile (&get_handle (),
+			     GENERIC_READ | GENERIC_WRITE | DELETE
+			     | SYNCHRONIZE, &oa, &io, NULL,
+			     FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
+			     FILE_CREATE,
+			     FILE_OPEN_FOR_BACKUP_INTENT
+			     | FILE_SYNCHRONOUS_IO_NONALERT,
+			     NULL, 0);
+      if (!NT_SUCCESS (status))
+	{
+	  if (status == STATUS_OBJECT_NAME_COLLISION && (oflags & O_EXCL) == 0)
+	    goto exists;
+	  __seterrno_from_nt_status (status);
+	  return 0;
+	}
+      if (pc.has_acls ())
+	set_created_file_access (get_handle (), pc, mode);
+      created = true;
+      goto out;
+    }
+exists:
+  /* Open the file, and loop while detecting a sharing violation. */
+  while (true)
+    {
+      status = NtOpenFile (&get_handle (),
+			   GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+			   &oa, &io, FILE_SHARE_VALID_FLAGS,
+			   FILE_OPEN_FOR_BACKUP_INTENT
+			   | FILE_SYNCHRONOUS_IO_NONALERT);
+      if (NT_SUCCESS (status))
+	break;
+      if (status == STATUS_OBJECT_NAME_NOT_FOUND && (oflags & O_CREAT))
+	goto again;
+      if (status != STATUS_SHARING_VIOLATION)
+	{
+	  __seterrno_from_nt_status (status);
+	  return -1;
+	}
+      Sleep (100L);
+    }
+out:
+  /* We need the filename without STREAM_SUFFIX later on */
+  mqstream->Length -= ro_u_mq_suffix.Length;
+  mqstream->Buffer[mqstream->Length / sizeof (WCHAR)] = L'\0';
+
+  if (created)
+    {
+      if (attr == NULL)
+	attr = &defattr;
+      /* Check minimum and maximum values.  The max values are pretty much
+	 arbitrary, taken from the linux mq_overview man page, up to Linux
+	 3.4.  These max values make sure that the internal mq_fattr
+	 structure can use 32 bit types. */
+      if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > 32768
+	       || attr->mq_msgsize <= 0 || attr->mq_msgsize > 1048576)
+	set_errno (EINVAL);
+      else
+	mqinfo = mqinfo_create (attr, mode, oflags & O_NONBLOCK);
+    }
+  else
+    mqinfo = mqinfo_open (oflags & O_NONBLOCK);
+  mq_open_finish (mqinfo != NULL, created);
+  return mqinfo ? 1 : 0;
+}
+
 struct mq_info *
-fhandler_mqueue::_mqinfo (HANDLE fh, SIZE_T filesize, mode_t mode, int flags,
+fhandler_mqueue::_mqinfo (SIZE_T filesize, mode_t mode, int flags,
 			  bool just_open)
 {
   WCHAR buf[NAME_MAX + sizeof ("mqueue/XXX")];
   UNICODE_STRING uname;
-  OBJECT_ATTRIBUTES attr;
+  OBJECT_ATTRIBUTES oa;
   NTSTATUS status;
   LARGE_INTEGER fsiz = { QuadPart: (LONGLONG) filesize };
   PVOID mptr = NULL;
@@ -38,33 +141,33 @@ fhandler_mqueue::_mqinfo (HANDLE fh, SIZE_T filesize, mode_t mode, int flags,
 
   __small_swprintf (buf, L"mqueue/mtx%s", get_name ());
   RtlInitUnicodeString (&uname, buf);
-  InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+  InitializeObjectAttributes (&oa, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
                               get_shared_parent_dir (),
                               everyone_sd (CYG_MUTANT_ACCESS));
-  status = NtCreateMutant (&mqinfo ()->mqi_lock, CYG_MUTANT_ACCESS, &attr,
+  status = NtCreateMutant (&mqinfo ()->mqi_lock, CYG_MUTANT_ACCESS, &oa,
 			   FALSE);
   if (!NT_SUCCESS (status))
     goto err;
 
   wcsncpy (buf + 7, L"snd", 3);
   /* same length, no RtlInitUnicodeString required */
-  InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+  InitializeObjectAttributes (&oa, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
                               get_shared_parent_dir (),
                               everyone_sd (CYG_EVENT_ACCESS));
-  status = NtCreateEvent (&mqinfo ()->mqi_waitsend, CYG_EVENT_ACCESS, &attr,
+  status = NtCreateEvent (&mqinfo ()->mqi_waitsend, CYG_EVENT_ACCESS, &oa,
 			  NotificationEvent, FALSE);
   if (!NT_SUCCESS (status))
     goto err;
   wcsncpy (buf + 7, L"rcv", 3);
   /* same length, same attributes, no more init required */
-  status = NtCreateEvent (&mqinfo ()->mqi_waitrecv, CYG_EVENT_ACCESS, &attr,
+  status = NtCreateEvent (&mqinfo ()->mqi_waitrecv, CYG_EVENT_ACCESS, &oa,
 			  NotificationEvent, FALSE);
   if (!NT_SUCCESS (status))
     goto err;
 
-  InitializeObjectAttributes (&attr, NULL, 0, NULL, NULL);
-  status = NtCreateSection (&mqinfo ()->mqi_sect, SECTION_ALL_ACCESS, &attr,
-			    &fsiz, PAGE_READWRITE, SEC_COMMIT, fh);
+  InitializeObjectAttributes (&oa, NULL, 0, NULL, NULL);
+  status = NtCreateSection (&mqinfo ()->mqi_sect, SECTION_ALL_ACCESS, &oa,
+			    &fsiz, PAGE_READWRITE, SEC_COMMIT, get_handle ());
   if (!NT_SUCCESS (status))
     goto err;
 
@@ -100,22 +203,152 @@ err:
   return NULL;
 }
 
+struct mq_info *
+fhandler_mqueue::mqinfo_open (int flags)
+{
+  FILE_STANDARD_INFORMATION fsi;
+  IO_STATUS_BLOCK io;
+  NTSTATUS status;
+  mode_t mode;
+
+  fsi.EndOfFile.QuadPart = 0;
+  status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
+				   FileStandardInformation);
+  if (!NT_SUCCESS (status))
+    {
+      __seterrno_from_nt_status (status);
+      return NULL;
+    }
+  if (get_file_attribute (get_handle (), pc, &mode, NULL, NULL))
+    mode = STD_RBITS | STD_WBITS;
+
+  return _mqinfo (fsi.EndOfFile.QuadPart, mode, flags, true);
+}
+
+struct mq_info *
+fhandler_mqueue::mqinfo_create (struct mq_attr *attr, mode_t mode, int flags)
+{
+  long msgsize;
+  off_t filesize = 0;
+  FILE_END_OF_FILE_INFORMATION feofi;
+  IO_STATUS_BLOCK io;
+  NTSTATUS status;
+  struct mq_info *mqinfo = NULL;
+
+  msgsize = MSGSIZE (attr->mq_msgsize);
+  filesize = sizeof (struct mq_hdr)
+	     + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
+  feofi.EndOfFile.QuadPart = filesize;
+  status = NtSetInformationFile (get_handle (), &io, &feofi, sizeof feofi,
+				 FileEndOfFileInformation);
+  if (!NT_SUCCESS (status))
+    {
+      __seterrno_from_nt_status (status);
+      return NULL;
+    }
+
+  mqinfo = _mqinfo (filesize, mode, flags, false);
+
+  if (mqinfo)
+    {
+      /* Initialize header at beginning of file */
+      /* Create free list with all messages on it */
+      int8_t *mptr;
+      struct mq_hdr *mqhdr;
+      struct msg_hdr *msghdr;
+
+      mptr = (int8_t *) mqinfo->mqi_hdr;
+      mqhdr = mqinfo->mqi_hdr;
+      mqhdr->mqh_attr.mq_flags = 0;
+      mqhdr->mqh_attr.mq_maxmsg = attr->mq_maxmsg;
+      mqhdr->mqh_attr.mq_msgsize = attr->mq_msgsize;
+      mqhdr->mqh_attr.mq_curmsgs = 0;
+      mqhdr->mqh_nwait = 0;
+      mqhdr->mqh_pid = 0;
+      mqhdr->mqh_head = 0;
+      mqhdr->mqh_magic = MQI_MAGIC;
+      long index = sizeof (struct mq_hdr);
+      mqhdr->mqh_free = index;
+      for (int i = 0; i < attr->mq_maxmsg - 1; i++)
+	{
+	  msghdr = (struct msg_hdr *) &mptr[index];
+	  index += sizeof (struct msg_hdr) + msgsize;
+	  msghdr->msg_next = index;
+	}
+      msghdr = (struct msg_hdr *) &mptr[index];
+      msghdr->msg_next = 0;         /* end of free list */
+    }
+
+  return mqinfo;
+}
+
+void
+fhandler_mqueue::mq_open_finish (bool success, bool created)
+{
+  NTSTATUS status;
+  HANDLE def_stream;
+  OBJECT_ATTRIBUTES oa;
+  IO_STATUS_BLOCK io;
+
+  if (get_handle ())
+    {
+      /* If we have an open queue stream handle, close it and set it to NULL */
+      HANDLE queue_stream = get_handle ();
+      set_handle (NULL);
+      if (success)
+	{
+	  /* In case of success, open the default stream for reading.  This
+	     can be used to implement various IO functions without exposing
+	     the actual message queue. */
+	  pc.get_object_attr (oa, sec_none_nih);
+	  status = NtOpenFile (&def_stream, GENERIC_READ | SYNCHRONIZE,
+			       &oa, &io, FILE_SHARE_VALID_FLAGS,
+			       FILE_OPEN_FOR_BACKUP_INTENT
+			       | FILE_SYNCHRONOUS_IO_NONALERT);
+	  if (NT_SUCCESS (status))
+	    set_handle (def_stream);
+	  else /* Note that we don't treat this as an error! */
+	    {
+	      debug_printf ("Opening default stream failed: status %y", status);
+	      nohandle (true);
+	    }
+	}
+      else if (created)
+	{
+	  /* In case of error at creation time, delete the file */
+	  FILE_DISPOSITION_INFORMATION disp = { TRUE };
+
+	  NtSetInformationFile (queue_stream, &io, &disp, sizeof disp,
+				FileDispositionInformation);
+	  /* We also have to set the delete disposition on the default stream,
+	     otherwise only the queue stream will get deleted */
+	  pc.get_object_attr (oa, sec_none_nih);
+	  status = NtOpenFile (&def_stream, DELETE, &oa, &io,
+			       FILE_SHARE_VALID_FLAGS,
+			       FILE_OPEN_FOR_BACKUP_INTENT);
+	  if (NT_SUCCESS (status))
+	    {
+	      NtSetInformationFile (def_stream, &io, &disp, sizeof disp,
+				    FileDispositionInformation);
+	      NtClose (def_stream);
+	    }
+	}
+      NtClose (queue_stream);
+    }
+}
+
 char *
 fhandler_mqueue::get_proc_fd_name (char *buf)
 {
-  return strcpy (buf, get_name ());
+  return strcpy (buf, strrchr (get_name (), '/'));
 }
 
 int __reg2
 fhandler_mqueue::fstat (struct stat *buf)
 {
-  int ret = fhandler_base::fstat (buf);
+  int ret = fhandler_disk_file::fstat (buf);
   if (!ret)
-    {
-      buf->st_mode = S_IFREG | mqinfo ()->mqi_mode;
-      buf->st_dev = FH_MQUEUE;
-      buf->st_ino = hash_path_name (0, get_name ());
-    }
+    buf->st_dev = FH_MQUEUE;
   return ret;
 }
 
diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc
index d0c6046a5..3b25c2803 100644
--- a/winsup/cygwin/globals.cc
+++ b/winsup/cygwin/globals.cc
@@ -153,6 +153,7 @@ const int __collate_load_error = 0;
   extern UNICODE_STRING _RDATA ro_u_natsyml = _ROU (L"SymbolicLink");
   extern UNICODE_STRING _RDATA ro_u_natdev = _ROU (L"Device");
   extern UNICODE_STRING _RDATA ro_u_npfs = _ROU (L"\\Device\\NamedPipe\\");
+  extern UNICODE_STRING _RDATA ro_u_mq_suffix = _ROU (L":mqueue");
   #undef _ROU
 
   /* This is an exported copy of environ which can be used by DLLs
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 2b480131a..39ba17514 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -1225,6 +1225,18 @@ path_conv::check (const char *src, unsigned opt,
 	    set_exec (1);
 	  else if (issymlink () || issocket ())
 	    set_exec (0);
+
+	  /* FIXME: bad hack alert!!!  We need a better solution */
+
+#define MQ_PATH "/dev/mqueue/"
+#define MQ_LEN  (sizeof (MQ_PATH) - 1)
+
+	  if (!strncmp (src, MQ_PATH, MQ_LEN))
+	    {
+	      size_t len = strlen (src + MQ_LEN);
+	      if (len > 0 && len <= NAME_MAX && !strpbrk (src + MQ_LEN, "/\\"))
+		dev.parse (FH_MQUEUE);
+	    }
 	}
 
       if (opt & PC_NOFULL)
diff --git a/winsup/cygwin/posix_ipc.cc b/winsup/cygwin/posix_ipc.cc
index 300a3f46f..772072d93 100644
--- a/winsup/cygwin/posix_ipc.cc
+++ b/winsup/cygwin/posix_ipc.cc
@@ -16,6 +16,7 @@ details. */
 #include "cygheap.h"
 #include "sigproc.h"
 #include "ntdll.h"
+#include "tls_pbuf.h"
 #include <io.h>
 #include <sys/mman.h>
 #include <sys/param.h>
@@ -24,8 +25,6 @@ details. */
 #include <mqueue.h>
 #include <semaphore.h>
 
-extern "C" int ftruncate64 (int fd, off_t length);
-
 /* The prefix_len is the length of the path prefix including trailing "/"
    (or "/sem." for semaphores) as well as the trailing NUL. */
 static struct
@@ -300,39 +299,13 @@ shm_unlink (const char *name)
    files are created under /dev/mqueue.  mq_timedsend and mq_timedreceive
    are implemented additionally. */
 
-#pragma pack (push, 4)
-struct msg_hdr
-{
-  int32_t         msg_next;	 /* index of next on linked list */
-  int32_t         msg_len;	 /* actual length */
-  unsigned int    msg_prio;	 /* priority */
-};
-#pragma pack (pop)
-
-#define MSGSIZE(i)	roundup((i), sizeof(long))
-
-#define	 MAX_TRIES	10	/* for waiting for initialization */
-
-struct mq_attr defattr = { 0, 10, 8192, 0 };	/* Linux defaults. */
-
-extern "C" off_t lseek64 (int, off_t, int);
-extern "C" void *mmap64 (void *, size_t, int, int, int, off_t);
-
 extern "C" mqd_t
 mq_open (const char *name, int oflag, ...)
 {
-  int i, fd = -1, nonblock, created = 0;
-  long msgsize, index;
-  off_t filesize = 0;
   va_list ap;
-  mode_t mode;
+  mode_t mode = 0;
   fhandler_mqueue *fh = NULL;
-  struct stat statbuff;
-  int8_t *mptr = NULL;
-  struct mq_hdr *mqhdr;
-  struct msg_hdr *msghdr;
-  struct mq_attr *attr;
-  struct mq_info *mqinfo = NULL;
+  struct mq_attr *attr = NULL;
 
   size_t len = strlen (name);
   char mqname[ipc_names[mqueue].prefix_len + len];
@@ -342,155 +315,36 @@ mq_open (const char *name, int oflag, ...)
 
   __try
     {
-      oflag &= (O_CREAT | O_EXCL | O_NONBLOCK);
-      nonblock = oflag & O_NONBLOCK;
-      oflag &= ~O_NONBLOCK;
-
-    again:
       if (oflag & O_CREAT)
 	{
 	  va_start (ap, oflag);		/* init ap to final named argument */
 	  mode = va_arg (ap, mode_t) & ~S_IXUSR;
 	  attr = va_arg (ap, struct mq_attr *);
 	  va_end (ap);
-
-	  /* Open and specify O_EXCL and user-execute */
-	  fd = open (mqname, oflag | O_EXCL | O_RDWR | O_CLOEXEC,
-		     mode | S_IXUSR);
-	  if (fd < 0)
-	    {
-	      if (errno == EEXIST && (oflag & O_EXCL) == 0)
-		goto exists;		/* already exists, OK */
-	      return (mqd_t) -1;
-	    }
-	  created = 1;
-	  /* First one to create the file initializes it */
-	  if (attr == NULL)
-	    attr = &defattr;
-	  /* Check minimum and maximum values.  The max values are pretty much
-	     arbitrary, taken from the linux mq_overview man page.  However,
-	     these max values make sure that the internal mq_fattr structure
-	     can use 32 bit types. */
-	  else if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > 32768
-		   || attr->mq_msgsize <= 0 || attr->mq_msgsize > 1048576)
-	    {
-	      set_errno (EINVAL);
-	      __leave;
-	    }
-	  /* Calculate and set the file size */
-	  msgsize = MSGSIZE (attr->mq_msgsize);
-	  filesize = sizeof (struct mq_hdr)
-		     + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
-	  if (ftruncate64 (fd, filesize) == -1)
-	    __leave;
-
-	  /* Create file descriptor for mqueue */
-	  cygheap_fdnew fdm;
-
-	  if (fdm < 0)
-	    __leave;
-	  fh = (fhandler_mqueue *) build_fh_dev (*mqueue_dev, name);
-	  if (!fh)
-	    __leave;
-
-	  mqinfo = fh->mqinfo_create ((HANDLE) _get_osfhandle (fd), filesize,
-				      mode, nonblock);
-	  if (!mqinfo)
-	    __leave;
-
-	  /* Initialize header at beginning of file */
-	  /* Create free list with all messages on it */
-	  mptr = (int8_t *) mqinfo->mqi_hdr;
-	  mqhdr = mqinfo->mqi_hdr;
-	  mqhdr->mqh_attr.mq_flags = 0;
-	  mqhdr->mqh_attr.mq_maxmsg = attr->mq_maxmsg;
-	  mqhdr->mqh_attr.mq_msgsize = attr->mq_msgsize;
-	  mqhdr->mqh_attr.mq_curmsgs = 0;
-	  mqhdr->mqh_nwait = 0;
-	  mqhdr->mqh_pid = 0;
-	  mqhdr->mqh_head = 0;
-	  mqhdr->mqh_magic = MQI_MAGIC;
-	  index = sizeof (struct mq_hdr);
-	  mqhdr->mqh_free = index;
-	  for (i = 0; i < attr->mq_maxmsg - 1; i++)
-	    {
-	      msghdr = (struct msg_hdr *) &mptr[index];
-	      index += sizeof (struct msg_hdr) + msgsize;
-	      msghdr->msg_next = index;
-	    }
-	  msghdr = (struct msg_hdr *) &mptr[index];
-	  msghdr->msg_next = 0;		/* end of free list */
-
-	  /* Initialization complete, turn off user-execute bit */
-	  if (fchmod (fd, mode) == -1)
-	    __leave;
-	  close (fd);
-	  fdm = fh;
-	  return (mqd_t) fdm;
-	}
-
-    exists:
-      /* Open the file then memory map */
-      if ((fd = open (mqname, O_RDWR | O_CLOEXEC)) < 0)
-	{
-	  if (errno == ENOENT && (oflag & O_CREAT))
-	    goto again;
-	  __leave;
-	}
-      /* Make certain initialization is complete */
-      for (i = 0; i < MAX_TRIES; i++)
-	{
-	  if (stat64 (mqname, &statbuff) == -1)
-	    {
-	      if (errno == ENOENT && (oflag & O_CREAT))
-		{
-		  close (fd);
-		  fd = -1;
-		  goto again;
-		}
-	      __leave;
-	    }
-	  if ((statbuff.st_mode & S_IXUSR) == 0)
-	    break;
-	  sleep (1);
-	}
-      if (i == MAX_TRIES)
-	{
-	  set_errno (ETIMEDOUT);
-	  __leave;
 	}
 
       /* Create file descriptor for mqueue */
-      cygheap_fdnew fdm;
+      cygheap_fdnew fd;
 
-      if (fdm < 0)
+      if (fd < 0)
 	__leave;
-      fh = (fhandler_mqueue *) build_fh_dev (*mqueue_dev, name);
+      fh = (fhandler_mqueue *) build_fh_name (mqname,
+					      PC_OPEN | PC_POSIX
+					      | PC_SYM_NOFOLLOW | PC_NULLEMPTY,
+					      NULL);
       if (!fh)
 	__leave;
 
-      mqinfo = fh->mqinfo_open ((HANDLE) _get_osfhandle (fd), statbuff.st_size,
-				statbuff.st_mode, nonblock);
-      if (!mqinfo)
-	__leave;
-
-      close (fd);
-      fdm = fh;
-      return (mqd_t) fdm;
+      if (fh->mq_open (oflag, mode, attr))
+	{
+	  fd = fh;
+	  return (mqd_t) fd;
+	}
     }
   __except (EFAULT) {}
   __endtry
-  /* Don't let following function calls change errno */
-  save_errno save;
-  if (created)
-    unlink (mqname);
-  if (fd >= 0)
-    close (fd);
   if (fh)
-    {
-      fh->close ();
-      delete fh;
-    }
+    delete fh;
   return (mqd_t) -1;
 }
 
@@ -921,6 +775,8 @@ mq_unlink (const char *name)
    the already existing semaphore class in thread.cc.  Using a file backed
    solution allows to implement kernel persistent named semaphores.  */
 
+#define	 MAX_TRIES	10	/* for waiting for initialization */
+
 struct sem_finfo
 {
   unsigned int       value;
@@ -1049,6 +905,8 @@ sem_open (const char *name, int oflag, ...)
   return SEM_FAILED;
 }
 
+extern "C" off_t lseek64 (int, off_t, int);
+
 int
 _sem_close (sem_t *sem, bool do_close)
 {


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

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

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-25 14:56 [newlib-cygwin] Cygwin: POSIX msg queues: implement open/mq_open entirely in fhandler 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).