]>
Commit | Line | Data |
---|---|---|
06e18175 | 1 | /* fhandler_fifo.cc - See fhandler.h for a description of the fhandler classes. |
d1fb625d | 2 | |
a7d2cc16 | 3 | Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. |
d1fb625d CF |
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" | |
ade47a34 | 12 | #include "miscfuncs.h" |
d1fb625d CF |
13 | |
14 | #include "cygerrno.h" | |
d1fb625d CF |
15 | #include "security.h" |
16 | #include "path.h" | |
17 | #include "fhandler.h" | |
18 | #include "dtable.h" | |
19 | #include "cygheap.h" | |
d9c0e3ec CF |
20 | #include "sigproc.h" |
21 | #include "cygtls.h" | |
d1fb625d | 22 | |
d9c0e3ec CF |
23 | fhandler_fifo::fhandler_fifo (): |
24 | wait_state (fifo_unknown) | |
d1fb625d | 25 | { |
d9c0e3ec CF |
26 | get_overlapped ()->hEvent = NULL; |
27 | need_fork_fixup (true); | |
d1fb625d CF |
28 | } |
29 | ||
d9c0e3ec CF |
30 | HANDLE |
31 | fhandler_fifo::open_nonserver (const char *npname, unsigned low_flags, | |
32 | LPSECURITY_ATTRIBUTES sa_buf) | |
d1fb625d | 33 | { |
d9c0e3ec CF |
34 | DWORD mode = 0; |
35 | if (low_flags == O_RDONLY) | |
36 | mode = GENERIC_READ; | |
37 | else if (low_flags = O_WRONLY) | |
38 | mode = GENERIC_WRITE; | |
d1fb625d | 39 | else |
d9c0e3ec CF |
40 | mode = GENERIC_READ | GENERIC_WRITE; |
41 | while (1) | |
d1fb625d | 42 | { |
d9c0e3ec CF |
43 | HANDLE h = CreateFile (npname, mode, 0, sa_buf, OPEN_EXISTING, |
44 | FILE_FLAG_OVERLAPPED, NULL); | |
45 | if (h != INVALID_HANDLE_VALUE || GetLastError () != ERROR_PIPE_NOT_CONNECTED) | |
46 | return h; | |
47 | if (&_my_tls != _main_tls) | |
48 | low_priority_sleep (0); | |
49 | else if (WaitForSingleObject (signal_arrived, 0) == WAIT_OBJECT_0) | |
d1fb625d | 50 | { |
d9c0e3ec CF |
51 | set_errno (EINTR); |
52 | return NULL; | |
d1fb625d | 53 | } |
d1fb625d CF |
54 | } |
55 | } | |
56 | ||
d9c0e3ec | 57 | #define FIFO_PIPE_MODE (PIPE_TYPE_BYTE | PIPE_READMODE_BYTE) |
fb201f92 | 58 | |
d1fb625d | 59 | int |
d9c0e3ec | 60 | fhandler_fifo::open (int flags, mode_t) |
d1fb625d | 61 | { |
d9c0e3ec | 62 | int res; |
86a1bb43 | 63 | char npname[MAX_PATH]; |
d9c0e3ec CF |
64 | DWORD mode = 0; |
65 | ||
636c94d8 CV |
66 | /* Generate a semi-unique name to associate with this fifo. */ |
67 | __small_sprintf (npname, "\\\\.\\pipe\\__cygfifo__%08x_%016X", | |
68 | get_dev (), get_ino ()); | |
d9c0e3ec CF |
69 | |
70 | unsigned low_flags = flags & O_ACCMODE; | |
71 | if (low_flags == O_RDONLY) | |
72 | mode = PIPE_ACCESS_INBOUND; | |
73 | else if (low_flags == O_WRONLY) | |
74 | mode = PIPE_ACCESS_OUTBOUND; | |
75 | else if (low_flags == O_RDWR) | |
76 | mode = PIPE_ACCESS_DUPLEX; | |
77 | ||
78 | if (!mode) | |
d1fb625d | 79 | { |
d9c0e3ec CF |
80 | set_errno (EINVAL); |
81 | res = 0; | |
82 | } | |
83 | else | |
84 | { | |
85 | char char_sa_buf[1024]; | |
86 | LPSECURITY_ATTRIBUTES sa_buf = | |
87 | sec_user ((PSECURITY_ATTRIBUTES) char_sa_buf, cygheap->user.sid()); | |
88 | mode |= FILE_FLAG_OVERLAPPED; | |
89 | HANDLE h = CreateNamedPipe(npname, mode, FIFO_PIPE_MODE, | |
90 | PIPE_UNLIMITED_INSTANCES, 0, 0, | |
91 | NMPWAIT_WAIT_FOREVER, sa_buf); | |
92 | if (h != INVALID_HANDLE_VALUE) | |
93 | wait_state = fifo_wait_for_client; | |
beffbc5e | 94 | else |
d9c0e3ec | 95 | switch (GetLastError ()) |
d1fb625d | 96 | { |
d9c0e3ec CF |
97 | case ERROR_ACCESS_DENIED: |
98 | h = open_nonserver (npname, low_flags, sa_buf); | |
99 | if (h != INVALID_HANDLE_VALUE) | |
100 | { | |
101 | wait_state = fifo_wait_for_server; | |
102 | break; | |
103 | } | |
104 | /* fall through intentionally */ | |
105 | default: | |
beffbc5e | 106 | __seterrno (); |
d9c0e3ec | 107 | break; |
d1fb625d | 108 | } |
d9c0e3ec CF |
109 | if (!h || h == INVALID_HANDLE_VALUE) |
110 | res = 0; | |
111 | else if (!setup_overlapped ()) | |
112 | { | |
113 | __seterrno (); | |
114 | res = 0; | |
115 | } | |
116 | else | |
117 | { | |
118 | set_io_handle (h); | |
119 | set_flags (flags); | |
120 | res = 1; | |
d1fb625d | 121 | } |
d1fb625d CF |
122 | } |
123 | ||
d9c0e3ec | 124 | debug_printf ("returning %d, errno %d", res, get_errno ()); |
d1fb625d CF |
125 | return res; |
126 | } | |
127 | ||
d9c0e3ec CF |
128 | bool |
129 | fhandler_fifo::wait (bool iswrite) | |
d1fb625d | 130 | { |
d9c0e3ec | 131 | switch (wait_state) |
4470d66d | 132 | { |
d9c0e3ec CF |
133 | case fifo_wait_for_client: |
134 | bool res = ConnectNamedPipe (get_handle (), get_overlapped ()); | |
135 | if (res || GetLastError () == ERROR_PIPE_CONNECTED) | |
136 | return true; | |
ee298432 | 137 | return wait_overlapped (res, iswrite, NULL); |
d9c0e3ec CF |
138 | default: |
139 | break; | |
4470d66d | 140 | } |
d9c0e3ec CF |
141 | return true; |
142 | } | |
4470d66d | 143 | |
d9c0e3ec CF |
144 | void |
145 | fhandler_fifo::read (void *in_ptr, size_t& len) | |
146 | { | |
147 | if (!wait (false)) | |
148 | len = 0; | |
beffbc5e | 149 | else |
d9c0e3ec | 150 | read_overlapped (in_ptr, len); |
d1fb625d CF |
151 | } |
152 | ||
153 | int | |
d9c0e3ec | 154 | fhandler_fifo::write (const void *ptr, size_t len) |
d1fb625d | 155 | { |
d9c0e3ec | 156 | return wait (true) ? write_overlapped (ptr, len) : -1; |
d1fb625d | 157 | } |
3323df7e CV |
158 | |
159 | int __stdcall | |
160 | fhandler_fifo::fstatvfs (struct statvfs *sfs) | |
161 | { | |
86a1bb43 CV |
162 | fhandler_disk_file fh (pc); |
163 | fh.get_device () = FH_FS; | |
164 | return fh.fstatvfs (sfs); | |
3323df7e | 165 | } |