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 defined(LINUX) 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 defined(LINUX) 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 linux, so 345 connect to the accepting pipe 346 */ 347 #if defined(LINUX) 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 len = sizeof(addr); 360 361 nRet = connect( fd, (struct sockaddr *)&addr, len); 362 #if OSL_DEBUG_LEVEL > 1 363 if ( nRet < 0 ) 364 { 365 perror("connect in osl_destroyPipe"); 366 } 367 #endif /* OSL_DEBUG_LEVEL */ 368 close(fd); 369 } 370 #endif /* LINUX */ 371 372 373 nRet = shutdown(ConnFD, 2); 374 if ( nRet < 0 ) 375 { 376 OSL_TRACE("shutdown in destroyPipe failed : '%s'\n",strerror(errno)); 377 } 378 379 nRet = close(ConnFD); 380 if ( nRet < 0 ) 381 { 382 OSL_TRACE("close in destroyPipe failed : '%s'\n",strerror(errno)); 383 } 384 /* remove filesystem entry */ 385 if ( strlen(pPipe->m_Name) > 0 ) 386 { 387 unlink(pPipe->m_Name); 388 } 389 pPipe->m_bClosed = sal_True; 390 391 /* OSL_TRACE("Out osl_destroyPipe"); */ 392 } 393 394 395 /*****************************************************************************/ 396 /* osl_acceptPipe */ 397 /*****************************************************************************/ 398 oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe) 399 { 400 int s, flags; 401 oslPipe pAcceptedPipe; 402 403 OSL_ASSERT(pPipe); 404 if ( pPipe == 0 ) 405 { 406 return NULL; 407 } 408 409 OSL_ASSERT(strlen(pPipe->m_Name) > 0); 410 411 #if defined(LINUX) 412 pPipe->m_bIsAccepting = sal_True; 413 #endif 414 415 s = accept(pPipe->m_Socket, NULL, NULL); 416 417 #if defined(LINUX) 418 pPipe->m_bIsAccepting = sal_False; 419 #endif 420 421 if (s < 0) 422 { 423 OSL_TRACE("osl_acceptPipe : accept error '%s'", strerror(errno)); 424 return NULL; 425 } 426 427 #if defined(LINUX) 428 if ( pPipe->m_bIsInShutdown ) 429 { 430 close(s); 431 return NULL; 432 } 433 #endif /* LINUX */ 434 else 435 { 436 /* alloc memory */ 437 pAcceptedPipe= __osl_createPipeImpl(); 438 439 OSL_ASSERT(pAcceptedPipe); 440 if(pAcceptedPipe==NULL) 441 { 442 close(s); 443 return NULL; 444 } 445 446 /* set close-on-exec flag */ 447 if (!((flags = fcntl(s, F_GETFD, 0)) < 0)) 448 { 449 flags |= FD_CLOEXEC; 450 if (fcntl(s, F_SETFD, flags) < 0) 451 { 452 OSL_TRACE("osl_acceptPipe: error changing socket flags. " 453 "Errno: %d; %s",errno,strerror(errno)); 454 } 455 } 456 457 pAcceptedPipe->m_Socket = s; 458 } 459 460 return pAcceptedPipe; 461 } 462 463 /*****************************************************************************/ 464 /* osl_receivePipe */ 465 /*****************************************************************************/ 466 sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe, 467 void* pBuffer, 468 sal_Int32 BytesToRead) 469 { 470 int nRet = 0; 471 472 OSL_ASSERT(pPipe); 473 474 if ( pPipe == 0 ) 475 { 476 OSL_TRACE("osl_receivePipe : Invalid socket"); 477 errno=EINVAL; 478 return -1; 479 } 480 481 nRet = recv(pPipe->m_Socket, 482 (sal_Char*)pBuffer, 483 BytesToRead, 0); 484 485 if ( nRet < 0 ) 486 { 487 OSL_TRACE("osl_receivePipe failed : %i '%s'",nRet,strerror(errno)); 488 } 489 490 return nRet; 491 } 492 493 494 /*****************************************************************************/ 495 /* osl_sendPipe */ 496 /*****************************************************************************/ 497 sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe, 498 const void* pBuffer, 499 sal_Int32 BytesToSend) 500 { 501 int nRet=0; 502 503 OSL_ASSERT(pPipe); 504 505 if ( pPipe == 0 ) 506 { 507 OSL_TRACE("osl_sendPipe : Invalid socket"); 508 errno=EINVAL; 509 return -1; 510 } 511 512 nRet = send(pPipe->m_Socket, 513 (sal_Char*)pBuffer, 514 BytesToSend, 0); 515 516 517 if ( nRet <= 0 ) 518 { 519 OSL_TRACE("osl_sendPipe failed : %i '%s'",nRet,strerror(errno)); 520 } 521 522 return nRet; 523 } 524 525 526 /*****************************************************************************/ 527 /* osl_getLastPipeError */ 528 /*****************************************************************************/ 529 oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe) 530 { 531 (void) pPipe; /* unused */ 532 return ERROR_FROM_NATIVE(errno); 533 } 534 535 536 sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n ) 537 { 538 /* loop until all desired bytes were send or an error occured */ 539 sal_Int32 BytesSend= 0; 540 sal_Int32 BytesToSend= n; 541 542 OSL_ASSERT(pPipe); 543 while (BytesToSend > 0) 544 { 545 sal_Int32 RetVal; 546 547 RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend); 548 549 /* error occured? */ 550 if(RetVal <= 0) 551 { 552 break; 553 } 554 555 BytesToSend -= RetVal; 556 BytesSend += RetVal; 557 pBuffer= (sal_Char*)pBuffer + RetVal; 558 } 559 560 return BytesSend; 561 } 562 563 sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n ) 564 { 565 /* loop until all desired bytes were read or an error occured */ 566 sal_Int32 BytesRead= 0; 567 sal_Int32 BytesToRead= n; 568 569 OSL_ASSERT( pPipe ); 570 while (BytesToRead > 0) 571 { 572 sal_Int32 RetVal; 573 RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead); 574 575 /* error occured? */ 576 if(RetVal <= 0) 577 { 578 break; 579 } 580 581 BytesToRead -= RetVal; 582 BytesRead += RetVal; 583 pBuffer= (sal_Char*)pBuffer + RetVal; 584 } 585 return BytesRead; 586 } 587 588 589