1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 #include "system.h" 30 31 #include <osl/pipe.h> 32 #include <osl/diagnose.h> 33 /*#include <osl/signal.h>*/ 34 #include <osl/thread.h> 35 #include <osl/interlck.h> 36 37 #include "sockimpl.h" 38 39 #define PIPEDEFAULTPATH "/tmp" 40 #define PIPEALTERNATEPATH "/var/tmp" 41 42 #define PIPENAMEMASK "OSL_PIPE_%s" 43 #define SECPIPENAMEMASK "OSL_PIPE_%s_%s" 44 45 sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax); 46 oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, oslSecurity Security); 47 48 /*#define DEBUG_OSL_PIPE*/ 49 /*#define TRACE_OSL_PIPE*/ 50 51 52 /*****************************************************************************/ 53 /* enum oslPipeError */ 54 /*****************************************************************************/ 55 56 static struct 57 { 58 int errcode; 59 oslPipeError error; 60 } PipeError[]= { 61 { 0, osl_Pipe_E_None }, /* no error */ 62 { EPROTOTYPE, osl_Pipe_E_NoProtocol }, /* Protocol wrong type for socket */ 63 { ENOPROTOOPT, osl_Pipe_E_NoProtocol }, /* Protocol not available */ 64 { EPROTONOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol not supported */ 65 { ESOCKTNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Socket type not supported */ 66 { EPFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol family not supported */ 67 { EAFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Address family not supported by */ 68 /* protocol family */ 69 { ENETRESET, osl_Pipe_E_NetworkReset }, /* Network dropped connection because */ 70 /* of reset */ 71 { ECONNABORTED, osl_Pipe_E_ConnectionAbort }, /* Software caused connection abort */ 72 { ECONNRESET, osl_Pipe_E_ConnectionReset }, /* Connection reset by peer */ 73 { ENOBUFS, osl_Pipe_E_NoBufferSpace }, /* No buffer space available */ 74 { ETIMEDOUT, osl_Pipe_E_TimedOut }, /* Connection timed out */ 75 { ECONNREFUSED, osl_Pipe_E_ConnectionRefused }, /* Connection refused */ 76 { -1, osl_Pipe_E_invalidError } 77 }; 78 79 80 /* map */ 81 /* mfe: NOT USED 82 static int osl_NativeFromPipeError(oslPipeError errorCode) 83 { 84 int i = 0; 85 86 while ((PipeError[i].error != osl_Pipe_E_invalidError) && 87 (PipeError[i].error != errorCode)) i++; 88 89 return PipeError[i].errcode; 90 91 } 92 */ 93 94 /* reverse map */ 95 static oslPipeError osl_PipeErrorFromNative(int nativeType) 96 { 97 int i = 0; 98 99 while ((PipeError[i].error != osl_Pipe_E_invalidError) && 100 (PipeError[i].errcode != nativeType)) i++; 101 102 return PipeError[i].error; 103 } 104 105 106 /* macros */ 107 #define ERROR_TO_NATIVE(x) osl_NativeFromPipeError(x) 108 #define ERROR_FROM_NATIVE(y) osl_PipeErrorFromNative(y) 109 110 111 /*****************************************************************************/ 112 /* osl_create/destroy-PipeImpl */ 113 /*****************************************************************************/ 114 115 oslPipe __osl_createPipeImpl() 116 { 117 oslPipe pPipeImpl; 118 119 pPipeImpl = (oslPipe)calloc(1, sizeof(struct oslPipeImpl)); 120 pPipeImpl->m_nRefCount =1; 121 pPipeImpl->m_bClosed = sal_False; 122 #if defined(LINUX) 123 pPipeImpl->m_bIsInShutdown = sal_False; 124 pPipeImpl->m_bIsAccepting = sal_False; 125 #endif 126 return pPipeImpl; 127 } 128 129 void __osl_destroyPipeImpl(oslPipe pImpl) 130 { 131 if (pImpl != NULL) 132 free(pImpl); 133 } 134 135 136 /*****************************************************************************/ 137 /* osl_createPipe */ 138 /*****************************************************************************/ 139 oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options, oslSecurity Security) 140 { 141 oslPipe pPipe=0; 142 rtl_String* strPipeName=0; 143 sal_Char* pszPipeName=0; 144 145 if ( ustrPipeName != 0 ) 146 { 147 rtl_uString2String( &strPipeName, 148 rtl_uString_getStr(ustrPipeName), 149 rtl_uString_getLength(ustrPipeName), 150 osl_getThreadTextEncoding(), 151 OUSTRING_TO_OSTRING_CVTFLAGS ); 152 pszPipeName = rtl_string_getStr(strPipeName); 153 pPipe = osl_psz_createPipe(pszPipeName, Options, Security); 154 155 if ( strPipeName != 0 ) 156 { 157 rtl_string_release(strPipeName); 158 } 159 } 160 161 return pPipe; 162 163 } 164 165 oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, 166 oslSecurity Security) 167 { 168 int Flags; 169 size_t len; 170 struct sockaddr_un addr; 171 172 sal_Char name[PATH_MAX + 1]; 173 oslPipe pPipe; 174 175 if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0) 176 { 177 strncpy(name, PIPEDEFAULTPATH, sizeof(name)); 178 } 179 else 180 { 181 strncpy(name, PIPEALTERNATEPATH, sizeof(name)); 182 } 183 184 185 strncat(name, "/", sizeof(name)); 186 187 if (Security) 188 { 189 sal_Char Ident[256]; 190 191 Ident[0] = '\0'; 192 193 OSL_VERIFY(osl_psz_getUserIdent(Security, Ident, sizeof(Ident))); 194 195 snprintf(&name[strlen(name)], sizeof(name), SECPIPENAMEMASK, Ident, pszPipeName); 196 } 197 else 198 { 199 snprintf(&name[strlen(name)], sizeof(name), PIPENAMEMASK, pszPipeName); 200 } 201 202 203 /* alloc memory */ 204 pPipe= __osl_createPipeImpl(); 205 206 /* create socket */ 207 pPipe->m_Socket = socket(AF_UNIX, SOCK_STREAM, 0); 208 if ( pPipe->m_Socket < 0 ) 209 { 210 OSL_TRACE("osl_createPipe socket failed. Errno: %d; %s\n",errno, strerror(errno)); 211 __osl_destroyPipeImpl(pPipe); 212 return NULL; 213 } 214 215 /* OSL_TRACE("osl_createPipe : new Pipe on fd %i\n",pPipe->m_Socket);*/ 216 217 /* set close-on-exec flag */ 218 if ((Flags = fcntl(pPipe->m_Socket, F_GETFD, 0)) != -1) 219 { 220 Flags |= FD_CLOEXEC; 221 if (fcntl(pPipe->m_Socket, F_SETFD, Flags) == -1) 222 { 223 OSL_TRACE("osl_createPipe failed changing socket flags. Errno: %d; %s\n",errno,strerror(errno)); 224 } 225 } 226 227 memset(&addr, 0, sizeof(addr)); 228 229 OSL_TRACE("osl_createPipe : Pipe Name '%s'",name); 230 231 addr.sun_family = AF_UNIX; 232 strncpy(addr.sun_path, name, sizeof(addr.sun_path)); 233 #if defined(FREEBSD) 234 len = SUN_LEN(&addr); 235 #else 236 len = sizeof(addr); 237 #endif 238 239 if ( Options & osl_Pipe_CREATE ) 240 { 241 struct stat status; 242 243 /* check if there exists an orphan filesystem entry */ 244 if ( ( stat(name, &status) == 0) && 245 ( S_ISSOCK(status.st_mode) || S_ISFIFO(status.st_mode) ) ) 246 { 247 if ( connect(pPipe->m_Socket,(struct sockaddr *)&addr,len) >= 0 ) 248 { 249 OSL_TRACE("osl_createPipe : Pipe already in use. Errno: %d; %s\n",errno,strerror(errno)); 250 close (pPipe->m_Socket); 251 __osl_destroyPipeImpl(pPipe); 252 return NULL; 253 } 254 255 unlink(name); 256 } 257 258 /* ok, fs clean */ 259 if ( bind(pPipe->m_Socket, (struct sockaddr *)&addr, len) < 0 ) 260 { 261 OSL_TRACE("osl_createPipe : failed to bind socket. Errno: %d; %s\n",errno,strerror(errno)); 262 close (pPipe->m_Socket); 263 __osl_destroyPipeImpl(pPipe); 264 return NULL; 265 } 266 267 /* Only give access to all if no security handle was specified, otherwise security 268 depends on umask */ 269 270 if ( !Security ) 271 chmod(name,S_IRWXU | S_IRWXG |S_IRWXO); 272 273 274 strncpy(pPipe->m_Name, name, sizeof(pPipe->m_Name)); 275 276 if ( listen(pPipe->m_Socket, 5) < 0 ) 277 { 278 OSL_TRACE("osl_createPipe failed to listen. Errno: %d; %s\n",errno,strerror(errno)); 279 unlink(name); /* remove filesystem entry */ 280 close (pPipe->m_Socket); 281 __osl_destroyPipeImpl(pPipe); 282 return NULL; 283 } 284 285 return (pPipe); 286 } 287 else 288 { /* osl_pipe_OPEN */ 289 if ( access(name, F_OK) != -1 ) 290 { 291 if ( connect( pPipe->m_Socket, (struct sockaddr *)&addr, len) >= 0 ) 292 { 293 return (pPipe); 294 } 295 296 OSL_TRACE("osl_createPipe failed to connect. Errno: %d; %s\n",errno,strerror(errno)); 297 } 298 299 close (pPipe->m_Socket); 300 __osl_destroyPipeImpl(pPipe); 301 return NULL; 302 } 303 } 304 305 void SAL_CALL osl_acquirePipe( oslPipe pPipe ) 306 { 307 osl_incrementInterlockedCount( &(pPipe->m_nRefCount) ); 308 } 309 310 void SAL_CALL osl_releasePipe( oslPipe pPipe ) 311 { 312 313 if( 0 == pPipe ) 314 return; 315 316 if( 0 == osl_decrementInterlockedCount( &(pPipe->m_nRefCount) ) ) 317 { 318 if( ! pPipe->m_bClosed ) 319 osl_closePipe( pPipe ); 320 321 __osl_destroyPipeImpl( pPipe ); 322 } 323 } 324 325 void SAL_CALL osl_closePipe( oslPipe pPipe ) 326 { 327 int nRet; 328 #if defined(LINUX) 329 size_t len; 330 struct sockaddr_un addr; 331 int fd; 332 #endif 333 int ConnFD; 334 335 if( ! pPipe ) 336 { 337 return; 338 } 339 340 if( pPipe->m_bClosed ) 341 { 342 return; 343 } 344 345 ConnFD = pPipe->m_Socket; 346 347 /* 348 Thread does not return from accept on linux, so 349 connect to the accepting pipe 350 */ 351 #if defined(LINUX) 352 if ( pPipe->m_bIsAccepting ) 353 { 354 pPipe->m_bIsInShutdown = sal_True; 355 pPipe->m_Socket = -1; 356 fd = socket(AF_UNIX, SOCK_STREAM, 0); 357 memset(&addr, 0, sizeof(addr)); 358 359 OSL_TRACE("osl_destroyPipe : Pipe Name '%s'",pPipe->m_Name); 360 361 addr.sun_family = AF_UNIX; 362 strncpy(addr.sun_path, pPipe->m_Name, sizeof(addr.sun_path)); 363 len = sizeof(addr); 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 /* LINUX */ 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 defined(LINUX) 416 pPipe->m_bIsAccepting = sal_True; 417 #endif 418 419 s = accept(pPipe->m_Socket, NULL, NULL); 420 421 #if defined(LINUX) 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 defined(LINUX) 432 if ( pPipe->m_bIsInShutdown ) 433 { 434 close(s); 435 return NULL; 436 } 437 #endif /* LINUX */ 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 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 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