]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/fhandler_mqueue.cc
5f97264cd28ee6f458444cc425b23433336fdab8
[newlib-cygwin.git] / winsup / cygwin / fhandler_mqueue.cc
1 /* fhandler_mqueue.cc: fhandler for POSIX message queue
2
3 This file is part of Cygwin.
4
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
8
9 #include "winsup.h"
10 #include "shared_info.h"
11 #include "path.h"
12 #include "fhandler.h"
13 #include "dtable.h"
14
15 fhandler_mqueue::fhandler_mqueue () :
16 fhandler_base ()
17 {
18 nohandle (true);
19 close_on_exec (true);
20 }
21
22 struct mq_info *
23 fhandler_mqueue::_mqinfo (HANDLE fh, SIZE_T filesize, mode_t mode, int flags,
24 bool just_open)
25 {
26 WCHAR buf[NAME_MAX + sizeof ("mqueue/XXX")];
27 UNICODE_STRING uname;
28 OBJECT_ATTRIBUTES attr;
29 NTSTATUS status;
30 LARGE_INTEGER fsiz = { QuadPart: (LONGLONG) filesize };
31 PVOID mptr = NULL;
32
33 /* Set sectsize prior to using filesize in NtMapViewOfSection. It will
34 get pagesize aligned, which breaks the next NtMapViewOfSection in fork. */
35 mqinfo ()->mqi_sectsize = filesize;
36 mqinfo ()->mqi_mode = mode;
37 mqinfo ()->mqi_flags = flags;
38
39 __small_swprintf (buf, L"mqueue/mtx%s", get_name ());
40 RtlInitUnicodeString (&uname, buf);
41 InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
42 get_shared_parent_dir (),
43 everyone_sd (CYG_MUTANT_ACCESS));
44 status = NtCreateMutant (&mqinfo ()->mqi_lock, CYG_MUTANT_ACCESS, &attr,
45 FALSE);
46 if (!NT_SUCCESS (status))
47 goto err;
48
49 wcsncpy (buf + 7, L"snd", 3);
50 /* same length, no RtlInitUnicodeString required */
51 InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
52 get_shared_parent_dir (),
53 everyone_sd (CYG_EVENT_ACCESS));
54 status = NtCreateEvent (&mqinfo ()->mqi_waitsend, CYG_EVENT_ACCESS, &attr,
55 NotificationEvent, FALSE);
56 if (!NT_SUCCESS (status))
57 goto err;
58 wcsncpy (buf + 7, L"rcv", 3);
59 /* same length, same attributes, no more init required */
60 status = NtCreateEvent (&mqinfo ()->mqi_waitrecv, CYG_EVENT_ACCESS, &attr,
61 NotificationEvent, FALSE);
62 if (!NT_SUCCESS (status))
63 goto err;
64
65 InitializeObjectAttributes (&attr, NULL, 0, NULL, NULL);
66 status = NtCreateSection (&mqinfo ()->mqi_sect, SECTION_ALL_ACCESS, &attr,
67 &fsiz, PAGE_READWRITE, SEC_COMMIT, fh);
68 if (!NT_SUCCESS (status))
69 goto err;
70
71 status = NtMapViewOfSection (mqinfo ()->mqi_sect, NtCurrentProcess (),
72 &mptr, 0, filesize, NULL, &filesize,
73 ViewShare, 0, PAGE_READWRITE);
74 if (!NT_SUCCESS (status))
75 goto err;
76
77 mqinfo ()->mqi_hdr = (struct mq_hdr *) mptr;
78
79 /* Special problem on Cygwin. /dev/mqueue is just a simple dir,
80 so there's a chance normal files are created in there. */
81 if (just_open && mqinfo ()->mqi_hdr->mqh_magic != MQI_MAGIC)
82 {
83 status = STATUS_ACCESS_DENIED;
84 goto err;
85 }
86
87 mqinfo ()->mqi_magic = MQI_MAGIC;
88 return mqinfo ();
89
90 err:
91 if (mqinfo ()->mqi_sect)
92 NtClose (mqinfo ()->mqi_sect);
93 if (mqinfo ()->mqi_waitrecv)
94 NtClose (mqinfo ()->mqi_waitrecv);
95 if (mqinfo ()->mqi_waitsend)
96 NtClose (mqinfo ()->mqi_waitsend);
97 if (mqinfo ()->mqi_lock)
98 NtClose (mqinfo ()->mqi_lock);
99 __seterrno_from_nt_status (status);
100 return NULL;
101 }
102
103 char *
104 fhandler_mqueue::get_proc_fd_name (char *buf)
105 {
106 return strcpy (buf, get_name ());
107 }
108
109 int __reg2
110 fhandler_mqueue::fstat (struct stat *buf)
111 {
112 int ret = fhandler_base::fstat (buf);
113 if (!ret)
114 {
115 buf->st_mode = S_IFREG | mqinfo ()->mqi_mode;
116 buf->st_dev = FH_MQUEUE;
117 buf->st_ino = hash_path_name (0, get_name ());
118 }
119 return ret;
120 }
121
122 int
123 fhandler_mqueue::dup (fhandler_base *child, int flags)
124 {
125 /* FIXME */
126 set_errno (EBADF);
127 return -1;
128 }
129
130 void
131 fhandler_mqueue::fixup_after_fork (HANDLE parent)
132 {
133 __try
134 {
135 PVOID mptr = NULL;
136 SIZE_T filesize = mqinfo ()->mqi_sectsize;
137 NTSTATUS status;
138
139 if (!DuplicateHandle (parent, mqinfo ()->mqi_sect,
140 GetCurrentProcess (), &mqinfo ()->mqi_sect,
141 0, FALSE, DUPLICATE_SAME_ACCESS))
142 __leave;
143 status = NtMapViewOfSection (mqinfo ()->mqi_sect, NtCurrentProcess (),
144 &mptr, 0, filesize, NULL, &filesize,
145 ViewShare, 0, PAGE_READWRITE);
146 if (!NT_SUCCESS (status))
147 api_fatal ("Mapping message queue failed in fork, status 0x%x\n",
148 status);
149
150 mqinfo ()->mqi_hdr = (struct mq_hdr *) mptr;
151 if (!DuplicateHandle (parent, mqinfo ()->mqi_waitsend,
152 GetCurrentProcess (), &mqinfo ()->mqi_waitsend,
153 0, FALSE, DUPLICATE_SAME_ACCESS))
154 __leave;
155 if (!DuplicateHandle (parent, mqinfo ()->mqi_waitrecv,
156 GetCurrentProcess (), &mqinfo ()->mqi_waitrecv,
157 0, FALSE, DUPLICATE_SAME_ACCESS))
158 __leave;
159 if (!DuplicateHandle (parent, mqinfo ()->mqi_lock,
160 GetCurrentProcess (), &mqinfo ()->mqi_lock,
161 0, FALSE, DUPLICATE_SAME_ACCESS))
162 __leave;
163 return;
164 }
165 __except (EFAULT) {}
166 __endtry
167 api_fatal ("Creating IPC object failed in fork, %E");
168 }
169
170 int
171 fhandler_mqueue::close ()
172 {
173 int ret = -1;
174
175 __try
176 {
177 mqinfo ()->mqi_magic = 0; /* just in case */
178 NtUnmapViewOfSection (NtCurrentProcess (), mqinfo ()->mqi_hdr);
179 NtClose (mqinfo ()->mqi_sect);
180 NtClose (mqinfo ()->mqi_waitsend);
181 NtClose (mqinfo ()->mqi_waitrecv);
182 NtClose (mqinfo ()->mqi_lock);
183 }
184 __except (0) {}
185 __endtry
186 return 0;
187 }
This page took 0.04275 seconds and 4 git commands to generate.