OSDN Git Service

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