xref: /aoo41x/main/sal/osl/unx/pipe.c (revision ebd402a9)
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