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 "%s/OSL_PIPE_%s" 39 #define SECPIPENAMEMASK "%s/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 */ 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 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 125 void __osl_destroyPipeImpl(oslPipe pImpl) 126 { 127 if (pImpl != NULL) 128 free(pImpl); 129 } 130 131 132 /*****************************************************************************/ 133 /* osl_createPipe */ 134 /*****************************************************************************/ 135 oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options, oslSecurity Security) 136 { 137 oslPipe pPipe=0; 138 rtl_String* strPipeName=NULL; 139 sal_Char* pszPipeName=NULL; 140 141 if ( ustrPipeName != NULL ) 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 != NULL ) 152 { 153 rtl_string_release(strPipeName); 154 } 155 } 156 157 return pPipe; 158 159 } 160 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 union 167 { 168 struct sockaddr addr; 169 struct sockaddr_un addr_un; 170 } s; 171 172 sal_Char name[PATH_MAX + 1]; 173 const sal_Char *pPath; 174 oslPipe pPipe; 175 176 if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0) 177 { 178 pPath = PIPEDEFAULTPATH; 179 } 180 else 181 { 182 pPath = PIPEALTERNATEPATH; 183 } 184 185 if (Security) 186 { 187 sal_Char Ident[256]; 188 189 Ident[0] = '\0'; 190 191 OSL_VERIFY(osl_psz_getUserIdent(Security, Ident, sizeof(Ident))); 192 193 snprintf(name, sizeof(name), SECPIPENAMEMASK, pPath, Ident, pszPipeName); 194 } 195 else 196 { 197 snprintf(name, sizeof(name), PIPENAMEMASK, pPath, pszPipeName); 198 } 199 200 201 /* alloc memory */ 202 pPipe= __osl_createPipeImpl(); 203 204 /* create socket */ 205 pPipe->m_Socket = socket(AF_UNIX, SOCK_STREAM, 0); 206 if ( pPipe->m_Socket < 0 ) 207 { 208 OSL_TRACE("osl_createPipe socket failed. Errno: %d; %s\n",errno, strerror(errno)); 209 __osl_destroyPipeImpl(pPipe); 210 return NULL; 211 } 212 213 /* OSL_TRACE("osl_createPipe : new Pipe on fd %i\n",pPipe->m_Socket);*/ 214 215 /* set close-on-exec flag */ 216 if ((Flags = fcntl(pPipe->m_Socket, F_GETFD, 0)) != -1) 217 { 218 Flags |= FD_CLOEXEC; 219 if (fcntl(pPipe->m_Socket, F_SETFD, Flags) == -1) 220 { 221 OSL_TRACE("osl_createPipe failed changing socket flags. Errno: %d; %s\n",errno,strerror(errno)); 222 } 223 } 224 225 memset(&s.addr_un, 0, sizeof(s.addr_un)); 226 227 OSL_TRACE("osl_createPipe : Pipe Name '%s'",name); 228 229 s.addr_un.sun_family = AF_UNIX; 230 strncpy(s.addr_un.sun_path, name, sizeof(s.addr_un.sun_path)); 231 #if defined(FREEBSD) 232 len = SUN_LEN(&s.addr_un); 233 #else 234 len = sizeof(s.addr_un); 235 #endif 236 237 if ( Options & osl_Pipe_CREATE ) 238 { 239 struct stat status; 240 241 /* check if there exists an orphan filesystem entry */ 242 if ( ( stat(name, &status) == 0) && 243 ( S_ISSOCK(status.st_mode) || S_ISFIFO(status.st_mode) ) ) 244 { 245 if ( connect(pPipe->m_Socket,&s.addr,len) >= 0 ) 246 { 247 OSL_TRACE("osl_createPipe : Pipe already in use. Errno: %d; %s\n",errno,strerror(errno)); 248 close (pPipe->m_Socket); 249 __osl_destroyPipeImpl(pPipe); 250 return NULL; 251 } 252 253 unlink(name); 254 } 255 256 /* ok, fs clean */ 257 if ( bind(pPipe->m_Socket, &s.addr, len) < 0 ) 258 { 259 OSL_TRACE("osl_createPipe : failed to bind socket. Errno: %d; %s\n",errno,strerror(errno)); 260 close (pPipe->m_Socket); 261 __osl_destroyPipeImpl(pPipe); 262 return NULL; 263 } 264 265 /* Only give access to all if no security handle was specified, otherwise security 266 depends on umask */ 267 268 if ( !Security ) 269 chmod(name,S_IRWXU | S_IRWXG |S_IRWXO); 270 271 272 strncpy(pPipe->m_Name, name, sizeof(pPipe->m_Name)); 273 274 if ( listen(pPipe->m_Socket, 5) < 0 ) 275 { 276 OSL_TRACE("osl_createPipe failed to listen. Errno: %d; %s\n",errno,strerror(errno)); 277 unlink(name); /* remove filesystem entry */ 278 close (pPipe->m_Socket); 279 __osl_destroyPipeImpl(pPipe); 280 return NULL; 281 } 282 283 return (pPipe); 284 } 285 else 286 { /* osl_pipe_OPEN */ 287 if ( access(name, F_OK) != -1 ) 288 { 289 if ( connect( pPipe->m_Socket, &s.addr, len) >= 0 ) 290 { 291 return (pPipe); 292 } 293 294 OSL_TRACE("osl_createPipe failed to connect. Errno: %d; %s\n",errno,strerror(errno)); 295 } 296 297 close (pPipe->m_Socket); 298 __osl_destroyPipeImpl(pPipe); 299 return NULL; 300 } 301 } 302 303 void SAL_CALL osl_acquirePipe( oslPipe pPipe ) 304 { 305 osl_incrementInterlockedCount( &(pPipe->m_nRefCount) ); 306 } 307 308 void SAL_CALL osl_releasePipe( oslPipe pPipe ) 309 { 310 311 if( 0 == pPipe ) 312 return; 313 314 if( 0 == osl_decrementInterlockedCount( &(pPipe->m_nRefCount) ) ) 315 { 316 if( ! pPipe->m_bClosed ) 317 osl_closePipe( pPipe ); 318 319 __osl_destroyPipeImpl( pPipe ); 320 } 321 } 322 323 void SAL_CALL osl_closePipe( oslPipe pPipe ) 324 { 325 int nRet; 326 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT 327 size_t len; 328 union 329 { 330 struct sockaddr_un addr_un; 331 struct sockaddr addr; 332 } s; 333 int fd; 334 #endif 335 int ConnFD; 336 337 if( ! pPipe ) 338 { 339 return; 340 } 341 342 if( pPipe->m_bClosed ) 343 { 344 return; 345 } 346 347 ConnFD = pPipe->m_Socket; 348 349 /* 350 Thread does not return from accept on some operating systems, so 351 connect to the accepting pipe 352 */ 353 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT 354 if ( pPipe->m_bIsAccepting ) 355 { 356 pPipe->m_bIsInShutdown = sal_True; 357 pPipe->m_Socket = -1; 358 fd = socket(AF_UNIX, SOCK_STREAM, 0); 359 memset(&s.addr_un, 0, sizeof(s.addr_un)); 360 361 OSL_TRACE("osl_destroyPipe : Pipe Name '%s'",pPipe->m_Name); 362 363 s.addr_un.sun_family = AF_UNIX; 364 strncpy(s.addr_un.sun_path, pPipe->m_Name, sizeof(s.addr_un.sun_path)); 365 #if defined(FREEBSD) 366 len = SUN_LEN(&s.addr_un); 367 #else 368 len = sizeof(s.addr_un); 369 #endif 370 371 nRet = connect( fd, &s.addr, len); 372 #if OSL_DEBUG_LEVEL > 1 373 if ( nRet < 0 ) 374 { 375 perror("connect in osl_destroyPipe"); 376 } 377 #endif /* OSL_DEBUG_LEVEL */ 378 close(fd); 379 } 380 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */ 381 382 383 nRet = shutdown(ConnFD, 2); 384 if ( nRet < 0 ) 385 { 386 OSL_TRACE("shutdown in destroyPipe failed : '%s'\n",strerror(errno)); 387 } 388 389 nRet = close(ConnFD); 390 if ( nRet < 0 ) 391 { 392 OSL_TRACE("close in destroyPipe failed : '%s'\n",strerror(errno)); 393 } 394 /* remove filesystem entry */ 395 if ( strlen(pPipe->m_Name) > 0 ) 396 { 397 unlink(pPipe->m_Name); 398 } 399 pPipe->m_bClosed = sal_True; 400 401 /* OSL_TRACE("Out osl_destroyPipe"); */ 402 } 403 404 405 /*****************************************************************************/ 406 /* osl_acceptPipe */ 407 /*****************************************************************************/ 408 oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe) 409 { 410 int s, flags; 411 oslPipe pAcceptedPipe; 412 413 OSL_ASSERT(pPipe); 414 if ( pPipe == 0 ) 415 { 416 return NULL; 417 } 418 419 OSL_ASSERT(strlen(pPipe->m_Name) > 0); 420 421 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT 422 pPipe->m_bIsAccepting = sal_True; 423 #endif 424 425 s = accept(pPipe->m_Socket, NULL, NULL); 426 427 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT 428 pPipe->m_bIsAccepting = sal_False; 429 #endif 430 431 if (s < 0) 432 { 433 OSL_TRACE("osl_acceptPipe : accept error '%s'", strerror(errno)); 434 return NULL; 435 } 436 437 #if CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT 438 if ( pPipe->m_bIsInShutdown ) 439 { 440 close(s); 441 return NULL; 442 } 443 #endif /* CLOSESOCKET_DOESNT_WAKE_UP_ACCEPT */ 444 else 445 { 446 /* alloc memory */ 447 pAcceptedPipe= __osl_createPipeImpl(); 448 449 OSL_ASSERT(pAcceptedPipe); 450 if(pAcceptedPipe==NULL) 451 { 452 close(s); 453 return NULL; 454 } 455 456 /* set close-on-exec flag */ 457 if (!((flags = fcntl(s, F_GETFD, 0)) < 0)) 458 { 459 flags |= FD_CLOEXEC; 460 if (fcntl(s, F_SETFD, flags) < 0) 461 { 462 OSL_TRACE("osl_acceptPipe: error changing socket flags. " 463 "Errno: %d; %s",errno,strerror(errno)); 464 } 465 } 466 467 pAcceptedPipe->m_Socket = s; 468 } 469 470 return pAcceptedPipe; 471 } 472 473 /*****************************************************************************/ 474 /* osl_receivePipe */ 475 /*****************************************************************************/ 476 sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe, 477 void* pBuffer, 478 sal_Int32 BytesToRead) 479 { 480 int nRet = 0; 481 482 OSL_ASSERT(pPipe); 483 484 if ( pPipe == 0 ) 485 { 486 OSL_TRACE("osl_receivePipe : Invalid socket"); 487 errno=EINVAL; 488 return -1; 489 } 490 491 nRet = recv(pPipe->m_Socket, 492 (sal_Char*)pBuffer, 493 BytesToRead, 0); 494 495 if ( nRet < 0 ) 496 { 497 OSL_TRACE("osl_receivePipe failed : %i '%s'",nRet,strerror(errno)); 498 } 499 500 return nRet; 501 } 502 503 504 /*****************************************************************************/ 505 /* osl_sendPipe */ 506 /*****************************************************************************/ 507 sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe, 508 const void* pBuffer, 509 sal_Int32 BytesToSend) 510 { 511 int nRet=0; 512 513 OSL_ASSERT(pPipe); 514 515 if ( pPipe == 0 ) 516 { 517 OSL_TRACE("osl_sendPipe : Invalid socket"); 518 errno=EINVAL; 519 return -1; 520 } 521 522 nRet = send(pPipe->m_Socket, 523 (sal_Char*)pBuffer, 524 BytesToSend, 0); 525 526 527 if ( nRet <= 0 ) 528 { 529 OSL_TRACE("osl_sendPipe failed : %i '%s'",nRet,strerror(errno)); 530 } 531 532 return nRet; 533 } 534 535 536 /*****************************************************************************/ 537 /* osl_getLastPipeError */ 538 /*****************************************************************************/ 539 oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe) 540 { 541 (void) pPipe; /* unused */ 542 return ERROR_FROM_NATIVE(errno); 543 } 544 545 546 sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n ) 547 { 548 /* loop until all desired bytes were send or an error occurred */ 549 sal_Int32 BytesSend= 0; 550 sal_Int32 BytesToSend= n; 551 552 OSL_ASSERT(pPipe); 553 while (BytesToSend > 0) 554 { 555 sal_Int32 RetVal; 556 557 RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend); 558 559 /* error occurred? */ 560 if(RetVal <= 0) 561 { 562 break; 563 } 564 565 BytesToSend -= RetVal; 566 BytesSend += RetVal; 567 pBuffer= (sal_Char*)pBuffer + RetVal; 568 } 569 570 return BytesSend; 571 } 572 573 sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n ) 574 { 575 /* loop until all desired bytes were read or an error occurred */ 576 sal_Int32 BytesRead= 0; 577 sal_Int32 BytesToRead= n; 578 579 OSL_ASSERT( pPipe ); 580 while (BytesToRead > 0) 581 { 582 sal_Int32 RetVal; 583 RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead); 584 585 /* error occurred? */ 586 if(RetVal <= 0) 587 { 588 break; 589 } 590 591 BytesToRead -= RetVal; 592 BytesRead += RetVal; 593 pBuffer= (sal_Char*)pBuffer + RetVal; 594 } 595 return BytesRead; 596 } 597 598 599