1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24
25 #include "system.h"
26
27 #include <osl/pipe.h>
28 #include <osl/diagnose.h>
29 /*#include <osl/signal.h>*/
30 #include <osl/thread.h>
31 #include <osl/interlck.h>
32
33 #include "sockimpl.h"
34
35 #define PIPEDEFAULTPATH "/tmp"
36 #define PIPEALTERNATEPATH "/var/tmp"
37
38 #define PIPENAMEMASK "OSL_PIPE_%s"
39 #define SECPIPENAMEMASK "OSL_PIPE_%s_%s"
40
41 sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax);
42 oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, oslSecurity Security);
43
44 /*#define DEBUG_OSL_PIPE*/
45 /*#define TRACE_OSL_PIPE*/
46
47
48 /*****************************************************************************/
49 /* enum oslPipeError */
50 /*****************************************************************************/
51
52 static struct
53 {
54 int errcode;
55 oslPipeError error;
56 } PipeError[]= {
57 { 0, osl_Pipe_E_None }, /* no error */
58 { EPROTOTYPE, osl_Pipe_E_NoProtocol }, /* Protocol wrong type for socket */
59 { ENOPROTOOPT, osl_Pipe_E_NoProtocol }, /* Protocol not available */
60 { EPROTONOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol not supported */
61 { ESOCKTNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Socket type not supported */
62 { EPFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol family not supported */
63 { EAFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Address family not supported by */
64 /* protocol family */
65 { ENETRESET, osl_Pipe_E_NetworkReset }, /* Network dropped connection because */
66 /* of reset */
67 { ECONNABORTED, osl_Pipe_E_ConnectionAbort }, /* Software caused connection abort */
68 { ECONNRESET, osl_Pipe_E_ConnectionReset }, /* Connection reset by peer */
69 { ENOBUFS, osl_Pipe_E_NoBufferSpace }, /* No buffer space available */
70 { ETIMEDOUT, osl_Pipe_E_TimedOut }, /* Connection timed out */
71 { ECONNREFUSED, osl_Pipe_E_ConnectionRefused }, /* Connection refused */
72 { -1, osl_Pipe_E_invalidError }
73 };
74
75
76 /* map */
77 /* mfe: NOT USED
78 static int osl_NativeFromPipeError(oslPipeError errorCode)
79 {
80 int i = 0;
81
82 while ((PipeError[i].error != osl_Pipe_E_invalidError) &&
83 (PipeError[i].error != errorCode)) i++;
84
85 return PipeError[i].errcode;
86
87 }
88 */
89
90 /* reverse map */
osl_PipeErrorFromNative(int nativeType)91 static oslPipeError osl_PipeErrorFromNative(int nativeType)
92 {
93 int i = 0;
94
95 while ((PipeError[i].error != osl_Pipe_E_invalidError) &&
96 (PipeError[i].errcode != nativeType)) i++;
97
98 return PipeError[i].error;
99 }
100
101
102 /* macros */
103 #define ERROR_TO_NATIVE(x) osl_NativeFromPipeError(x)
104 #define ERROR_FROM_NATIVE(y) osl_PipeErrorFromNative(y)
105
106
107 /*****************************************************************************/
108 /* osl_create/destroy-PipeImpl */
109 /*****************************************************************************/
110
__osl_createPipeImpl()111 oslPipe __osl_createPipeImpl()
112 {
113 oslPipe pPipeImpl;
114
115 pPipeImpl = (oslPipe)calloc(1, sizeof(struct oslPipeImpl));
116 pPipeImpl->m_nRefCount =1;
117 pPipeImpl->m_bClosed = sal_False;
118 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT
119 pPipeImpl->m_bIsInShutdown = sal_False;
120 pPipeImpl->m_bIsAccepting = sal_False;
121 #endif
122 return pPipeImpl;
123 }
124
__osl_destroyPipeImpl(oslPipe pImpl)125 void __osl_destroyPipeImpl(oslPipe pImpl)
126 {
127 if (pImpl != NULL)
128 free(pImpl);
129 }
130
131
132 /*****************************************************************************/
133 /* osl_createPipe */
134 /*****************************************************************************/
osl_createPipe(rtl_uString * ustrPipeName,oslPipeOptions Options,oslSecurity Security)135 oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options, oslSecurity Security)
136 {
137 oslPipe pPipe=0;
138 rtl_String* strPipeName=0;
139 sal_Char* pszPipeName=0;
140
141 if ( ustrPipeName != 0 )
142 {
143 rtl_uString2String( &strPipeName,
144 rtl_uString_getStr(ustrPipeName),
145 rtl_uString_getLength(ustrPipeName),
146 osl_getThreadTextEncoding(),
147 OUSTRING_TO_OSTRING_CVTFLAGS );
148 pszPipeName = rtl_string_getStr(strPipeName);
149 pPipe = osl_psz_createPipe(pszPipeName, Options, Security);
150
151 if ( strPipeName != 0 )
152 {
153 rtl_string_release(strPipeName);
154 }
155 }
156
157 return pPipe;
158
159 }
160
osl_psz_createPipe(const sal_Char * pszPipeName,oslPipeOptions Options,oslSecurity Security)161 oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options,
162 oslSecurity Security)
163 {
164 int Flags;
165 size_t len;
166 struct sockaddr_un addr;
167
168 sal_Char name[PATH_MAX + 1];
169 oslPipe pPipe;
170
171 if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0)
172 {
173 strncpy(name, PIPEDEFAULTPATH, sizeof(name));
174 }
175 else
176 {
177 strncpy(name, PIPEALTERNATEPATH, sizeof(name));
178 }
179
180
181 strncat(name, "/", sizeof(name));
182
183 if (Security)
184 {
185 sal_Char Ident[256];
186
187 Ident[0] = '\0';
188
189 OSL_VERIFY(osl_psz_getUserIdent(Security, Ident, sizeof(Ident)));
190
191 snprintf(&name[strlen(name)], sizeof(name), SECPIPENAMEMASK, Ident, pszPipeName);
192 }
193 else
194 {
195 snprintf(&name[strlen(name)], sizeof(name), PIPENAMEMASK, pszPipeName);
196 }
197
198
199 /* alloc memory */
200 pPipe= __osl_createPipeImpl();
201
202 /* create socket */
203 pPipe->m_Socket = socket(AF_UNIX, SOCK_STREAM, 0);
204 if ( pPipe->m_Socket < 0 )
205 {
206 OSL_TRACE("osl_createPipe socket failed. Errno: %d; %s\n",errno, strerror(errno));
207 __osl_destroyPipeImpl(pPipe);
208 return NULL;
209 }
210
211 /* OSL_TRACE("osl_createPipe : new Pipe on fd %i\n",pPipe->m_Socket);*/
212
213 /* set close-on-exec flag */
214 if ((Flags = fcntl(pPipe->m_Socket, F_GETFD, 0)) != -1)
215 {
216 Flags |= FD_CLOEXEC;
217 if (fcntl(pPipe->m_Socket, F_SETFD, Flags) == -1)
218 {
219 OSL_TRACE("osl_createPipe failed changing socket flags. Errno: %d; %s\n",errno,strerror(errno));
220 }
221 }
222
223 memset(&addr, 0, sizeof(addr));
224
225 OSL_TRACE("osl_createPipe : Pipe Name '%s'",name);
226
227 addr.sun_family = AF_UNIX;
228 strncpy(addr.sun_path, name, sizeof(addr.sun_path));
229 #if defined(FREEBSD)
230 len = SUN_LEN(&addr);
231 #else
232 len = sizeof(addr);
233 #endif
234
235 if ( Options & osl_Pipe_CREATE )
236 {
237 struct stat status;
238
239 /* check if there exists an orphan filesystem entry */
240 if ( ( stat(name, &status) == 0) &&
241 ( S_ISSOCK(status.st_mode) || S_ISFIFO(status.st_mode) ) )
242 {
243 if ( connect(pPipe->m_Socket,(struct sockaddr *)&addr,len) >= 0 )
244 {
245 OSL_TRACE("osl_createPipe : Pipe already in use. Errno: %d; %s\n",errno,strerror(errno));
246 close (pPipe->m_Socket);
247 __osl_destroyPipeImpl(pPipe);
248 return NULL;
249 }
250
251 unlink(name);
252 }
253
254 /* ok, fs clean */
255 if ( bind(pPipe->m_Socket, (struct sockaddr *)&addr, len) < 0 )
256 {
257 OSL_TRACE("osl_createPipe : failed to bind socket. Errno: %d; %s\n",errno,strerror(errno));
258 close (pPipe->m_Socket);
259 __osl_destroyPipeImpl(pPipe);
260 return NULL;
261 }
262
263 /* Only give access to all if no security handle was specified, otherwise security
264 depends on umask */
265
266 if ( !Security )
267 chmod(name,S_IRWXU | S_IRWXG |S_IRWXO);
268
269
270 strncpy(pPipe->m_Name, name, sizeof(pPipe->m_Name));
271
272 if ( listen(pPipe->m_Socket, 5) < 0 )
273 {
274 OSL_TRACE("osl_createPipe failed to listen. Errno: %d; %s\n",errno,strerror(errno));
275 unlink(name); /* remove filesystem entry */
276 close (pPipe->m_Socket);
277 __osl_destroyPipeImpl(pPipe);
278 return NULL;
279 }
280
281 return (pPipe);
282 }
283 else
284 { /* osl_pipe_OPEN */
285 if ( access(name, F_OK) != -1 )
286 {
287 if ( connect( pPipe->m_Socket, (struct sockaddr *)&addr, len) >= 0 )
288 {
289 return (pPipe);
290 }
291
292 OSL_TRACE("osl_createPipe failed to connect. Errno: %d; %s\n",errno,strerror(errno));
293 }
294
295 close (pPipe->m_Socket);
296 __osl_destroyPipeImpl(pPipe);
297 return NULL;
298 }
299 }
300
osl_acquirePipe(oslPipe pPipe)301 void SAL_CALL osl_acquirePipe( oslPipe pPipe )
302 {
303 osl_incrementInterlockedCount( &(pPipe->m_nRefCount) );
304 }
305
osl_releasePipe(oslPipe pPipe)306 void SAL_CALL osl_releasePipe( oslPipe pPipe )
307 {
308
309 if( 0 == pPipe )
310 return;
311
312 if( 0 == osl_decrementInterlockedCount( &(pPipe->m_nRefCount) ) )
313 {
314 if( ! pPipe->m_bClosed )
315 osl_closePipe( pPipe );
316
317 __osl_destroyPipeImpl( pPipe );
318 }
319 }
320
osl_closePipe(oslPipe pPipe)321 void SAL_CALL osl_closePipe( oslPipe pPipe )
322 {
323 int nRet;
324 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT
325 size_t len;
326 struct sockaddr_un addr;
327 int fd;
328 #endif
329 int ConnFD;
330
331 if( ! pPipe )
332 {
333 return;
334 }
335
336 if( pPipe->m_bClosed )
337 {
338 return;
339 }
340
341 ConnFD = pPipe->m_Socket;
342
343 /*
344 Thread does not return from accept on some operating systems, so
345 connect to the accepting pipe
346 */
347 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT
348 if ( pPipe->m_bIsAccepting )
349 {
350 pPipe->m_bIsInShutdown = sal_True;
351 pPipe->m_Socket = -1;
352 fd = socket(AF_UNIX, SOCK_STREAM, 0);
353 memset(&addr, 0, sizeof(addr));
354
355 OSL_TRACE("osl_destroyPipe : Pipe Name '%s'",pPipe->m_Name);
356
357 addr.sun_family = AF_UNIX;
358 strncpy(addr.sun_path, pPipe->m_Name, sizeof(addr.sun_path));
359 #if defined(FREEBSD)
360 len = SUN_LEN(&addr);
361 #else
362 len = sizeof(addr);
363 #endif
364
365 nRet = connect( fd, (struct sockaddr *)&addr, len);
366 #if OSL_DEBUG_LEVEL > 1
367 if ( nRet < 0 )
368 {
369 perror("connect in osl_destroyPipe");
370 }
371 #endif /* OSL_DEBUG_LEVEL */
372 close(fd);
373 }
374 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
375
376
377 nRet = shutdown(ConnFD, 2);
378 if ( nRet < 0 )
379 {
380 OSL_TRACE("shutdown in destroyPipe failed : '%s'\n",strerror(errno));
381 }
382
383 nRet = close(ConnFD);
384 if ( nRet < 0 )
385 {
386 OSL_TRACE("close in destroyPipe failed : '%s'\n",strerror(errno));
387 }
388 /* remove filesystem entry */
389 if ( strlen(pPipe->m_Name) > 0 )
390 {
391 unlink(pPipe->m_Name);
392 }
393 pPipe->m_bClosed = sal_True;
394
395 /* OSL_TRACE("Out osl_destroyPipe"); */
396 }
397
398
399 /*****************************************************************************/
400 /* osl_acceptPipe */
401 /*****************************************************************************/
osl_acceptPipe(oslPipe pPipe)402 oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe)
403 {
404 int s, flags;
405 oslPipe pAcceptedPipe;
406
407 OSL_ASSERT(pPipe);
408 if ( pPipe == 0 )
409 {
410 return NULL;
411 }
412
413 OSL_ASSERT(strlen(pPipe->m_Name) > 0);
414
415 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT
416 pPipe->m_bIsAccepting = sal_True;
417 #endif
418
419 s = accept(pPipe->m_Socket, NULL, NULL);
420
421 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT
422 pPipe->m_bIsAccepting = sal_False;
423 #endif
424
425 if (s < 0)
426 {
427 OSL_TRACE("osl_acceptPipe : accept error '%s'", strerror(errno));
428 return NULL;
429 }
430
431 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT
432 if ( pPipe->m_bIsInShutdown )
433 {
434 close(s);
435 return NULL;
436 }
437 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */
438 else
439 {
440 /* alloc memory */
441 pAcceptedPipe= __osl_createPipeImpl();
442
443 OSL_ASSERT(pAcceptedPipe);
444 if(pAcceptedPipe==NULL)
445 {
446 close(s);
447 return NULL;
448 }
449
450 /* set close-on-exec flag */
451 if (!((flags = fcntl(s, F_GETFD, 0)) < 0))
452 {
453 flags |= FD_CLOEXEC;
454 if (fcntl(s, F_SETFD, flags) < 0)
455 {
456 OSL_TRACE("osl_acceptPipe: error changing socket flags. "
457 "Errno: %d; %s",errno,strerror(errno));
458 }
459 }
460
461 pAcceptedPipe->m_Socket = s;
462 }
463
464 return pAcceptedPipe;
465 }
466
467 /*****************************************************************************/
468 /* osl_receivePipe */
469 /*****************************************************************************/
osl_receivePipe(oslPipe pPipe,void * pBuffer,sal_Int32 BytesToRead)470 sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe,
471 void* pBuffer,
472 sal_Int32 BytesToRead)
473 {
474 int nRet = 0;
475
476 OSL_ASSERT(pPipe);
477
478 if ( pPipe == 0 )
479 {
480 OSL_TRACE("osl_receivePipe : Invalid socket");
481 errno=EINVAL;
482 return -1;
483 }
484
485 nRet = recv(pPipe->m_Socket,
486 (sal_Char*)pBuffer,
487 BytesToRead, 0);
488
489 if ( nRet < 0 )
490 {
491 OSL_TRACE("osl_receivePipe failed : %i '%s'",nRet,strerror(errno));
492 }
493
494 return nRet;
495 }
496
497
498 /*****************************************************************************/
499 /* osl_sendPipe */
500 /*****************************************************************************/
osl_sendPipe(oslPipe pPipe,const void * pBuffer,sal_Int32 BytesToSend)501 sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe,
502 const void* pBuffer,
503 sal_Int32 BytesToSend)
504 {
505 int nRet=0;
506
507 OSL_ASSERT(pPipe);
508
509 if ( pPipe == 0 )
510 {
511 OSL_TRACE("osl_sendPipe : Invalid socket");
512 errno=EINVAL;
513 return -1;
514 }
515
516 nRet = send(pPipe->m_Socket,
517 (sal_Char*)pBuffer,
518 BytesToSend, 0);
519
520
521 if ( nRet <= 0 )
522 {
523 OSL_TRACE("osl_sendPipe failed : %i '%s'",nRet,strerror(errno));
524 }
525
526 return nRet;
527 }
528
529
530 /*****************************************************************************/
531 /* osl_getLastPipeError */
532 /*****************************************************************************/
osl_getLastPipeError(oslPipe pPipe)533 oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe)
534 {
535 (void) pPipe; /* unused */
536 return ERROR_FROM_NATIVE(errno);
537 }
538
539
osl_writePipe(oslPipe pPipe,const void * pBuffer,sal_Int32 n)540 sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n )
541 {
542 /* loop until all desired bytes were send or an error occured */
543 sal_Int32 BytesSend= 0;
544 sal_Int32 BytesToSend= n;
545
546 OSL_ASSERT(pPipe);
547 while (BytesToSend > 0)
548 {
549 sal_Int32 RetVal;
550
551 RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend);
552
553 /* error occured? */
554 if(RetVal <= 0)
555 {
556 break;
557 }
558
559 BytesToSend -= RetVal;
560 BytesSend += RetVal;
561 pBuffer= (sal_Char*)pBuffer + RetVal;
562 }
563
564 return BytesSend;
565 }
566
osl_readPipe(oslPipe pPipe,void * pBuffer,sal_Int32 n)567 sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n )
568 {
569 /* loop until all desired bytes were read or an error occured */
570 sal_Int32 BytesRead= 0;
571 sal_Int32 BytesToRead= n;
572
573 OSL_ASSERT( pPipe );
574 while (BytesToRead > 0)
575 {
576 sal_Int32 RetVal;
577 RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead);
578
579 /* error occured? */
580 if(RetVal <= 0)
581 {
582 break;
583 }
584
585 BytesToRead -= RetVal;
586 BytesRead += RetVal;
587 pBuffer= (sal_Char*)pBuffer + RetVal;
588 }
589 return BytesRead;
590 }
591
592
593