diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-14 15:20:06 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-14 15:20:06 +0000 |
commit | ea03f11cfac38afdad7ea45b3a7787bd9b4f4711 (patch) | |
tree | f167b9eb1fe57eab105475cfc78555fde74a9fc8 /src/util | |
parent | dbc46fb04fb3e1257b2473aee609c06c5b56f3c9 (diff) | |
download | gnunet-ea03f11cfac38afdad7ea45b3a7787bd9b4f4711.tar.gz gnunet-ea03f11cfac38afdad7ea45b3a7787bd9b4f4711.zip |
LRN: new pipe creation function GNUNET_DISK_pipe_from_fd to wrap existing file descriptor pair
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/disk.c | 158 |
1 files changed, 144 insertions, 14 deletions
diff --git a/src/util/disk.c b/src/util/disk.c index 430d9cc46..8d1fe3c12 100644 --- a/src/util/disk.c +++ b/src/util/disk.c | |||
@@ -2037,6 +2037,116 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write) | |||
2037 | return p; | 2037 | return p; |
2038 | } | 2038 | } |
2039 | 2039 | ||
2040 | /** | ||
2041 | * Creates a pipe object from a couple of file descriptors. | ||
2042 | * Useful for wrapping existing pipe FDs. | ||
2043 | * | ||
2044 | * @param blocking creates an asynchronous pipe if set to GNUNET_NO | ||
2045 | * @param fd an array of two fd values. One of them may be -1 for read-only or write-only pipes | ||
2046 | * | ||
2047 | * @return handle to the new pipe, NULL on error | ||
2048 | */ | ||
2049 | struct GNUNET_DISK_PipeHandle * | ||
2050 | GNUNET_DISK_pipe_from_fd (int blocking, int fd[2]) | ||
2051 | { | ||
2052 | struct GNUNET_DISK_PipeHandle *p; | ||
2053 | struct GNUNET_DISK_FileHandle *fds; | ||
2054 | |||
2055 | p = GNUNET_malloc (sizeof (struct GNUNET_DISK_PipeHandle) + | ||
2056 | 2 * sizeof (struct GNUNET_DISK_FileHandle)); | ||
2057 | fds = (struct GNUNET_DISK_FileHandle *) &p[1]; | ||
2058 | p->fd[0] = &fds[0]; | ||
2059 | p->fd[1] = &fds[1]; | ||
2060 | #ifndef MINGW | ||
2061 | int ret; | ||
2062 | int flags; | ||
2063 | int eno; | ||
2064 | |||
2065 | p->fd[0]->fd = fd[0]; | ||
2066 | p->fd[1]->fd = fd[1]; | ||
2067 | ret = 0; | ||
2068 | if (fd[0] >= 0) | ||
2069 | { | ||
2070 | flags = fcntl (fd[0], F_GETFL); | ||
2071 | if (!blocking) | ||
2072 | flags |= O_NONBLOCK; | ||
2073 | if (0 > fcntl (fd[0], F_SETFL, flags)) | ||
2074 | ret = -1; | ||
2075 | flags = fcntl (fd[0], F_GETFD); | ||
2076 | flags |= FD_CLOEXEC; | ||
2077 | if (0 > fcntl (fd[0], F_SETFD, flags)) | ||
2078 | ret = -1; | ||
2079 | } | ||
2080 | |||
2081 | if (fd[1] >= 0) | ||
2082 | { | ||
2083 | flags = fcntl (fd[1], F_GETFL); | ||
2084 | if (!blocking) | ||
2085 | flags |= O_NONBLOCK; | ||
2086 | if (0 > fcntl (fd[1], F_SETFL, flags)) | ||
2087 | ret = -1; | ||
2088 | flags = fcntl (fd[1], F_GETFD); | ||
2089 | flags |= FD_CLOEXEC; | ||
2090 | if (0 > fcntl (fd[1], F_SETFD, flags)) | ||
2091 | ret = -1; | ||
2092 | } | ||
2093 | if (ret == -1) | ||
2094 | { | ||
2095 | eno = errno; | ||
2096 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fcntl"); | ||
2097 | if (p->fd[0]->fd >= 0) | ||
2098 | GNUNET_break (0 == close (p->fd[0]->fd)); | ||
2099 | if (p->fd[1]->fd >= 0) | ||
2100 | GNUNET_break (0 == close (p->fd[1]->fd)); | ||
2101 | GNUNET_free (p); | ||
2102 | errno = eno; | ||
2103 | return NULL; | ||
2104 | } | ||
2105 | #else | ||
2106 | BOOL ret; | ||
2107 | |||
2108 | if (fd[0] >= 0) | ||
2109 | p->fd[0]->h = _get_osfhandle (fd[0]); | ||
2110 | else | ||
2111 | p->fd[0]->h = INVALID_HANDLE_VALUE; | ||
2112 | if (fd[1] >= 0) | ||
2113 | p->fd[1]->h = _get_osfhandle (fd[1]); | ||
2114 | else | ||
2115 | p->fd[1]->h = INVALID_HANDLE_VALUE; | ||
2116 | |||
2117 | if (!blocking) | ||
2118 | { | ||
2119 | DWORD mode; | ||
2120 | |||
2121 | mode = PIPE_NOWAIT; | ||
2122 | if (p->fd[0]->h != INVALID_HANDLE_VALUE) | ||
2123 | SetNamedPipeHandleState (p->fd[0]->h, &mode, NULL, NULL); | ||
2124 | if (p->fd[1]->h != INVALID_HANDLE_VALUE) | ||
2125 | SetNamedPipeHandleState (p->fd[1]->h, &mode, NULL, NULL); | ||
2126 | /* this always fails on Windows 95, so we don't care about error handling */ | ||
2127 | } | ||
2128 | |||
2129 | if (p->fd[0]->h != INVALID_HANDLE_VALUE) | ||
2130 | { | ||
2131 | p->fd[0]->type = GNUNET_PIPE; | ||
2132 | p->fd[0]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
2133 | p->fd[0]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
2134 | p->fd[0]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
2135 | p->fd[0]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
2136 | } | ||
2137 | |||
2138 | if (p->fd[1]->h != INVALID_HANDLE_VALUE) | ||
2139 | { | ||
2140 | p->fd[1]->type = GNUNET_PIPE; | ||
2141 | p->fd[1]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
2142 | p->fd[1]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); | ||
2143 | p->fd[1]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
2144 | p->fd[1]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); | ||
2145 | } | ||
2146 | #endif | ||
2147 | return p; | ||
2148 | } | ||
2149 | |||
2040 | 2150 | ||
2041 | /** | 2151 | /** |
2042 | * Closes an interprocess channel | 2152 | * Closes an interprocess channel |
@@ -2055,21 +2165,31 @@ GNUNET_DISK_pipe_close_end (struct GNUNET_DISK_PipeHandle *p, | |||
2055 | #ifdef MINGW | 2165 | #ifdef MINGW |
2056 | if (end == GNUNET_DISK_PIPE_END_READ) | 2166 | if (end == GNUNET_DISK_PIPE_END_READ) |
2057 | { | 2167 | { |
2058 | if (!CloseHandle (p->fd[0]->h)) | 2168 | if (p->fd[0]->h != INVALID_HANDLE_VALUE) |
2059 | { | 2169 | { |
2060 | SetErrnoFromWinError (GetLastError ()); | 2170 | if (!CloseHandle (p->fd[0]->h)) |
2061 | ret = GNUNET_SYSERR; | 2171 | { |
2172 | SetErrnoFromWinError (GetLastError ()); | ||
2173 | ret = GNUNET_SYSERR; | ||
2174 | } | ||
2175 | GNUNET_free (p->fd[0]->oOverlapRead); | ||
2176 | GNUNET_free (p->fd[0]->oOverlapWrite); | ||
2177 | p->fd[0]->h = INVALID_HANDLE_VALUE; | ||
2062 | } | 2178 | } |
2063 | p->fd[0]->h = INVALID_HANDLE_VALUE; | ||
2064 | } | 2179 | } |
2065 | else if (end == GNUNET_DISK_PIPE_END_WRITE) | 2180 | else if (end == GNUNET_DISK_PIPE_END_WRITE) |
2066 | { | 2181 | { |
2067 | if (!CloseHandle (p->fd[1]->h)) | 2182 | if (p->fd[0]->h != INVALID_HANDLE_VALUE) |
2068 | { | 2183 | { |
2069 | SetErrnoFromWinError (GetLastError ()); | 2184 | if (!CloseHandle (p->fd[1]->h)) |
2070 | ret = GNUNET_SYSERR; | 2185 | { |
2186 | SetErrnoFromWinError (GetLastError ()); | ||
2187 | ret = GNUNET_SYSERR; | ||
2188 | } | ||
2189 | GNUNET_free (p->fd[1]->oOverlapRead); | ||
2190 | GNUNET_free (p->fd[1]->oOverlapWrite); | ||
2191 | p->fd[1]->h = INVALID_HANDLE_VALUE; | ||
2071 | } | 2192 | } |
2072 | p->fd[1]->h = INVALID_HANDLE_VALUE; | ||
2073 | } | 2193 | } |
2074 | save = errno; | 2194 | save = errno; |
2075 | #else | 2195 | #else |
@@ -2110,15 +2230,25 @@ GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p) | |||
2110 | int save; | 2230 | int save; |
2111 | 2231 | ||
2112 | #ifdef MINGW | 2232 | #ifdef MINGW |
2113 | if (!CloseHandle (p->fd[0]->h)) | 2233 | if (p->fd[0]->h != INVALID_HANDLE_VALUE) |
2114 | { | 2234 | { |
2115 | SetErrnoFromWinError (GetLastError ()); | 2235 | if (!CloseHandle (p->fd[0]->h)) |
2116 | ret = GNUNET_SYSERR; | 2236 | { |
2237 | SetErrnoFromWinError (GetLastError ()); | ||
2238 | ret = GNUNET_SYSERR; | ||
2239 | } | ||
2240 | GNUNET_free (p->fd[0]->oOverlapRead); | ||
2241 | GNUNET_free (p->fd[0]->oOverlapWrite); | ||
2117 | } | 2242 | } |
2118 | if (!CloseHandle (p->fd[1]->h)) | 2243 | if (p->fd[1]->h != INVALID_HANDLE_VALUE) |
2119 | { | 2244 | { |
2120 | SetErrnoFromWinError (GetLastError ()); | 2245 | if (!CloseHandle (p->fd[1]->h)) |
2121 | ret = GNUNET_SYSERR; | 2246 | { |
2247 | SetErrnoFromWinError (GetLastError ()); | ||
2248 | ret = GNUNET_SYSERR; | ||
2249 | } | ||
2250 | GNUNET_free (p->fd[1]->oOverlapRead); | ||
2251 | GNUNET_free (p->fd[1]->oOverlapWrite); | ||
2122 | } | 2252 | } |
2123 | save = errno; | 2253 | save = errno; |
2124 | #else | 2254 | #else |