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 */ 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=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 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 301 void SAL_CALL osl_acquirePipe( oslPipe pPipe ) 302 { 303 osl_incrementInterlockedCount( &(pPipe->m_nRefCount) ); 304 } 305 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 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 533 oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe) 534 { 535 (void) pPipe; /* unused */ 536 return ERROR_FROM_NATIVE(errno); 537 } 538 539 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 occurred */ 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 occurred? */ 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 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 occurred */ 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 occurred? */ 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