OSDN Git Service

* path.cc (conv_path_list): Take cygwin_conv_path_t as third parameter.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / fhandler_mailslot.cc
1 /* fhandler_mailslot.cc.  See fhandler.h for a description of the fhandler classes.
2
3    Copyright 2005, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
4
5    This file is part of Cygwin.
6
7    This software is a copyrighted work licensed under the terms of the
8    Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9    details. */
10
11 #include "winsup.h"
12
13 #include "cygerrno.h"
14 #include "path.h"
15 #include "fhandler.h"
16 #include "ntdll.h"
17 #include "shared_info.h"
18 #include "tls_pbuf.h"
19
20 /**********************************************************************/
21 /* fhandler_mailslot */
22
23 fhandler_mailslot::fhandler_mailslot ()
24   : fhandler_base_overlapped ()
25 {
26 }
27
28 int __stdcall
29 fhandler_mailslot::fstat (struct __stat64 *buf)
30 {
31   debug_printf ("here");
32
33   fhandler_base_overlapped::fstat (buf);
34   if (is_auto_device ())
35     {
36       buf->st_mode = S_IFCHR | S_IRUSR | S_IWUSR;
37       buf->st_uid = geteuid32 ();
38       buf->st_gid = getegid32 ();
39       buf->st_nlink = 1;
40       buf->st_blksize = PREFERRED_IO_BLKSIZE;
41       time_as_timestruc_t (&buf->st_ctim);
42       buf->st_atim = buf->st_mtim = buf->st_birthtim = buf->st_ctim;
43     }
44   return 0;
45 }
46
47 POBJECT_ATTRIBUTES
48 fhandler_mailslot::get_object_attr (OBJECT_ATTRIBUTES &attr,
49                                     PUNICODE_STRING path,
50                                     int flags)
51 {
52
53   RtlCopyUnicodeString (path, pc.get_nt_native_path ());
54   RtlAppendUnicodeStringToString (path, &installation_key);
55   InitializeObjectAttributes (&attr, path,
56                               OBJ_CASE_INSENSITIVE
57                               | (flags & O_CLOEXEC ? 0 : OBJ_INHERIT),
58                               NULL, NULL);
59   return &attr;
60 }
61
62 int
63 fhandler_mailslot::open (int flags, mode_t mode)
64 {
65   int res = 0;
66   NTSTATUS status;
67   IO_STATUS_BLOCK io;
68   OBJECT_ATTRIBUTES attr;
69   HANDLE x;
70   LARGE_INTEGER timeout;
71   tmp_pathbuf tp;
72   UNICODE_STRING path;
73
74   tp.u_get (&path);
75
76   switch (flags & O_ACCMODE)
77     {
78     case O_RDONLY:      /* Server */
79       timeout.QuadPart = (flags & O_NONBLOCK) ? 0LL : 0x8000000000000000LL;
80       status = NtCreateMailslotFile (&x, GENERIC_READ | SYNCHRONIZE,
81                                      get_object_attr (attr, &path, flags),
82                                      &io, FILE_SYNCHRONOUS_IO_NONALERT,
83                                      0, 0, &timeout);
84       if (!NT_SUCCESS (status))
85         {
86           /* FIXME: It's not possible to open the read side of an existing
87              mailslot again.  You'll get a handle, but using it in ReadFile
88              returns ERROR_INVALID_PARAMETER.  On the other hand,
89              NtCreateMailslotFile returns with STATUS_OBJECT_NAME_EXISTS if
90              the mailslot has been created already.
91              So this is an exclusive open for now.  *Duplicating* read side
92              handles works, though, so it might be an option to duplicate
93              the handle from the first process to the current process for
94              opening the mailslot. */
95 #if 0
96           if (status != STATUS_OBJECT_NAME_COLLISION)
97             {
98               __seterrno_from_nt_status (status);
99               break;
100             }
101           status = NtOpenFile (&x, GENERIC_READ | SYNCHRONIZE,
102                                get_object_attr (attr, &path, flags), &io,
103                                FILE_SHARE_VALID_FLAGS,
104                                FILE_SYNCHRONOUS_IO_NONALERT);
105 #endif
106           if (!NT_SUCCESS (status))
107             {
108               __seterrno_from_nt_status (status);
109               break;
110             }
111         }
112       set_io_handle (x);
113       set_flags (flags, O_BINARY);
114       res = 1;
115       set_open_status ();
116       break;
117     case O_WRONLY:      /* Client */
118       /* The client is the DLL exclusively.  Don't allow opening from
119          application code. */
120       extern fhandler_mailslot *dev_kmsg;
121       if (this != dev_kmsg)
122         {
123           set_errno (EPERM);    /* As on Linux. */
124           break;
125         }
126       status = NtOpenFile (&x, GENERIC_WRITE | SYNCHRONIZE,
127                            get_object_attr (attr, &path, flags), &io,
128                            FILE_SHARE_VALID_FLAGS, 0);
129       if (!NT_SUCCESS (status))
130         {
131           __seterrno_from_nt_status (status);
132           break;
133         }
134       set_io_handle (x);
135       set_flags (flags, O_BINARY);
136       res = 1;
137       set_open_status ();
138       break;
139     default:
140       set_errno (EINVAL);
141       break;
142     }
143   return res;
144 }
145
146 ssize_t __stdcall
147 fhandler_mailslot::raw_write (const void *ptr, size_t len)
148 {
149   /* Check for 425/426 byte weirdness */
150   if (len == 425 || len == 426)
151     {
152       char buf[427];
153       buf[425] = buf[426] = '\0';
154       memcpy (buf, ptr, len);
155       return raw_write (buf, 427);
156     }
157   return fhandler_base_overlapped::raw_write (ptr, len);
158 }
159
160 int
161 fhandler_mailslot::ioctl (unsigned int cmd, void *buf)
162 {
163   int res = -1;
164   NTSTATUS status;
165   IO_STATUS_BLOCK io;
166
167   switch (cmd)
168     {
169     case FIONBIO:
170       {
171         FILE_MAILSLOT_SET_INFORMATION fmsi;
172         fmsi.ReadTimeout.QuadPart = buf ? 0LL : 0x8000000000000000LL;
173         status = NtSetInformationFile (get_handle (), &io, &fmsi, sizeof fmsi,
174                                        FileMailslotSetInformation);
175         if (!NT_SUCCESS (status))
176           {
177             debug_printf ("NtSetInformationFile (%X): %08x",
178                           fmsi.ReadTimeout.QuadPart, status);
179             __seterrno_from_nt_status (status);
180             break;
181           }
182       }
183       /*FALLTHRU*/
184     default:
185       res =  fhandler_base_overlapped::ioctl (cmd, buf);
186       break;
187     }
188   return res;
189 }