From df451d6a539fdf3c7248e16203026bd8df423e53 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Wed, 19 Nov 2014 11:56:22 +0100 Subject: pipe.c -> pipe.cxx Change-Id: I0c9659379e6120c0bf01b6436d3127b83ad01af1 --- sal/Library_sal.mk | 2 +- sal/osl/unx/pipe.c | 612 --------------------------------------------------- sal/osl/unx/pipe.cxx | 612 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 613 insertions(+), 613 deletions(-) delete mode 100644 sal/osl/unx/pipe.c create mode 100644 sal/osl/unx/pipe.cxx (limited to 'sal') diff --git a/sal/Library_sal.mk b/sal/Library_sal.mk index 6dfcfaac37d3..4bc6d08de2db 100644 --- a/sal/Library_sal.mk +++ b/sal/Library_sal.mk @@ -163,6 +163,7 @@ $(eval $(call gb_Library_add_exception_objects,sal,\ sal/osl/unx/module \ sal/osl/unx/mutex \ sal/osl/unx/nlsupport \ + sal/osl/unx/pipe \ sal/osl/unx/process \ sal/osl/unx/process_impl \ sal/osl/unx/profile \ @@ -172,7 +173,6 @@ $(eval $(call gb_Library_add_exception_objects,sal,\ $(if $(filter DESKTOP,$(BUILD_TYPE)), sal/osl/unx/salinit) \ )) $(eval $(call gb_Library_add_cobjects,sal,\ - sal/osl/unx/pipe \ sal/osl/unx/readwrite_helper \ sal/osl/unx/socket \ sal/osl/unx/system \ diff --git a/sal/osl/unx/pipe.c b/sal/osl/unx/pipe.c deleted file mode 100644 index e3e08b55a469..000000000000 --- a/sal/osl/unx/pipe.c +++ /dev/null @@ -1,612 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include "system.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "sockimpl.h" -#include "secimpl.h" - -#define PIPEDEFAULTPATH "/tmp" -#define PIPEALTERNATEPATH "/var/tmp" - -#define PIPENAMEMASK "OSL_PIPE_%s" -#define SECPIPENAMEMASK "OSL_PIPE_%s_%s" - -oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, oslSecurity Security); - -static struct -{ - int errcode; - oslPipeError error; -} PipeError[]= { - { 0, osl_Pipe_E_None }, /* no error */ - { EPROTOTYPE, osl_Pipe_E_NoProtocol }, /* Protocol wrong type for socket */ - { ENOPROTOOPT, osl_Pipe_E_NoProtocol }, /* Protocol not available */ - { EPROTONOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol not supported */ - { ESOCKTNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Socket type not supported */ - { EPFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol family not supported */ - { EAFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Address family not supported by */ - /* protocol family */ - { ENETRESET, osl_Pipe_E_NetworkReset }, /* Network dropped connection because */ - /* of reset */ - { ECONNABORTED, osl_Pipe_E_ConnectionAbort }, /* Software caused connection abort */ - { ECONNRESET, osl_Pipe_E_ConnectionReset }, /* Connection reset by peer */ - { ENOBUFS, osl_Pipe_E_NoBufferSpace }, /* No buffer space available */ - { ETIMEDOUT, osl_Pipe_E_TimedOut }, /* Connection timed out */ - { ECONNREFUSED, osl_Pipe_E_ConnectionRefused }, /* Connection refused */ - { -1, osl_Pipe_E_invalidError } -}; - -/* map */ -/* mfe: NOT USED - static int osl_NativeFromPipeError(oslPipeError errorCode) - { - int i = 0; - - while ((PipeError[i].error != osl_Pipe_E_invalidError) && - (PipeError[i].error != errorCode)) i++; - - return PipeError[i].errcode; - - } -*/ - -/* reverse map */ -static oslPipeError osl_PipeErrorFromNative(int nativeType) -{ - int i = 0; - - while ((PipeError[i].error != osl_Pipe_E_invalidError) && - (PipeError[i].errcode != nativeType)) i++; - - return PipeError[i].error; -} - -/* macros */ -#define ERROR_FROM_NATIVE(y) osl_PipeErrorFromNative(y) - -oslPipe __osl_createPipeImpl(void) -{ - oslPipe pPipeImpl; - - pPipeImpl = (oslPipe)calloc(1, sizeof(struct oslPipeImpl)); - if (pPipeImpl == NULL) - return NULL; - pPipeImpl->m_nRefCount =1; - pPipeImpl->m_bClosed = sal_False; -#if defined(LINUX) - pPipeImpl->m_bIsInShutdown = sal_False; - pPipeImpl->m_bIsAccepting = sal_False; -#endif - return pPipeImpl; -} - -void __osl_destroyPipeImpl(oslPipe pImpl) -{ - if (pImpl != NULL) - free(pImpl); -} - -oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options, oslSecurity Security) -{ - oslPipe pPipe=0; - rtl_String* strPipeName=0; - sal_Char* pszPipeName=0; - - if ( ustrPipeName != 0 ) - { - rtl_uString2String( &strPipeName, - rtl_uString_getStr(ustrPipeName), - rtl_uString_getLength(ustrPipeName), - osl_getThreadTextEncoding(), - OUSTRING_TO_OSTRING_CVTFLAGS ); - pszPipeName = rtl_string_getStr(strPipeName); - pPipe = osl_psz_createPipe(pszPipeName, Options, Security); - - if ( strPipeName != 0 ) - { - rtl_string_release(strPipeName); - } - } - - return pPipe; - -} - -static sal_Bool -cpyBootstrapSocketPath(sal_Char *name, size_t len) -{ - sal_Bool bRet = sal_False; - rtl_uString *pName = 0, *pValue = 0; - - rtl_uString_newFromAscii(&pName, "OSL_SOCKET_PATH"); - - if (rtl_bootstrap_get(pName, &pValue, NULL)) - { - if (pValue && pValue->length > 0) - { - rtl_String *pStrValue = 0; - - rtl_uString2String(&pStrValue, pValue->buffer, - pValue->length, RTL_TEXTENCODING_UTF8, - OUSTRING_TO_OSTRING_CVTFLAGS); - if (pStrValue) - { - if (pStrValue->length > 0) - { - size_t nCopy = (len-1 < (size_t)pStrValue->length) ? len-1 : (size_t)pStrValue->length; - strncpy (name, pStrValue->buffer, nCopy); - name[nCopy] = '\0'; - bRet = (size_t)pStrValue->length < len; - } - rtl_string_release(pStrValue); - } - } - rtl_uString_release(pName); - } - return bRet; -} - -oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, - oslSecurity Security) -{ - int Flags; - size_t len; - struct sockaddr_un addr; - - sal_Char name[PATH_MAX + 1]; - size_t nNameLength = 0; - int bNameTooLong = 0; - oslPipe pPipe; - - if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0) - { - strncpy(name, PIPEDEFAULTPATH, sizeof(name)); - } - else if (access(PIPEALTERNATEPATH, R_OK|W_OK) == 0) - { - strncpy(name, PIPEALTERNATEPATH, sizeof(name)); - } - else if (!cpyBootstrapSocketPath (name, sizeof (name))) - { - return NULL; - } - name[sizeof(name) - 1] = '\0'; // ensure the string is NULL-terminated - nNameLength = strlen(name); - bNameTooLong = nNameLength > sizeof(name) - 2; - - if (!bNameTooLong) - { - size_t nRealLength = 0; - - strcat(name, "/"); - ++nNameLength; - - if (Security) - { - sal_Char Ident[256]; - - Ident[0] = '\0'; - - OSL_VERIFY(osl_psz_getUserIdent(Security, Ident, sizeof(Ident))); - - nRealLength = snprintf(&name[nNameLength], sizeof(name) - nNameLength, SECPIPENAMEMASK, Ident, pszPipeName); - } - else - { - nRealLength = snprintf(&name[nNameLength], sizeof(name) - nNameLength, PIPENAMEMASK, pszPipeName); - } - - bNameTooLong = nRealLength > sizeof(name) - nNameLength - 1; - } - - if (bNameTooLong) - { - OSL_TRACE("osl_createPipe: pipe name too long"); - return NULL; - } - - /* alloc memory */ - pPipe = __osl_createPipeImpl(); - - if (pPipe == NULL) - { - OSL_TRACE("__osl_createPipe socket failed"); - return NULL; - } - - /* create socket */ - pPipe->m_Socket = socket(AF_UNIX, SOCK_STREAM, 0); - if ( pPipe->m_Socket < 0 ) - { - OSL_TRACE("osl_createPipe socket failed. Errno: %d; %s",errno, strerror(errno)); - __osl_destroyPipeImpl(pPipe); - return NULL; - } - -/* OSL_TRACE("osl_createPipe : new Pipe on fd %i\n",pPipe->m_Socket);*/ - - /* set close-on-exec flag */ - if ((Flags = fcntl(pPipe->m_Socket, F_GETFD, 0)) != -1) - { - Flags |= FD_CLOEXEC; - if (fcntl(pPipe->m_Socket, F_SETFD, Flags) == -1) - { - OSL_TRACE("osl_createPipe failed changing socket flags. Errno: %d; %s",errno,strerror(errno)); - } - } - - memset(&addr, 0, sizeof(addr)); - - OSL_TRACE("osl_createPipe : Pipe Name '%s'",name); - - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, name, sizeof(addr.sun_path) - 1); -#if defined(FREEBSD) - len = SUN_LEN(&addr); -#else - len = sizeof(addr); -#endif - - if ( Options & osl_Pipe_CREATE ) - { - struct stat status; - - /* check if there exists an orphan filesystem entry */ - if ( ( stat(name, &status) == 0) && - ( S_ISSOCK(status.st_mode) || S_ISFIFO(status.st_mode) ) ) - { - if ( connect(pPipe->m_Socket,(struct sockaddr *)&addr,len) >= 0 ) - { - OSL_TRACE("osl_createPipe : Pipe already in use. Errno: %d; %s",errno,strerror(errno)); - close (pPipe->m_Socket); - __osl_destroyPipeImpl(pPipe); - return NULL; - } - - unlink(name); - } - - /* ok, fs clean */ - if ( bind(pPipe->m_Socket, (struct sockaddr *)&addr, len) < 0 ) - { - OSL_TRACE("osl_createPipe : failed to bind socket. Errno: %d; %s",errno,strerror(errno)); - close (pPipe->m_Socket); - __osl_destroyPipeImpl(pPipe); - return NULL; - } - - /* Only give access to all if no security handle was specified, otherwise security - depends on umask */ - - if ( !Security ) - chmod(name,S_IRWXU | S_IRWXG |S_IRWXO); - - strncpy(pPipe->m_Name, name, sizeof(pPipe->m_Name) - 1); - - if ( listen(pPipe->m_Socket, 5) < 0 ) - { - OSL_TRACE("osl_createPipe failed to listen. Errno: %d; %s",errno,strerror(errno)); - unlink(name); /* remove filesystem entry */ - close (pPipe->m_Socket); - __osl_destroyPipeImpl(pPipe); - return NULL; - } - - return (pPipe); - } - else - { /* osl_pipe_OPEN */ - if ( access(name, F_OK) != -1 ) - { - if ( connect( pPipe->m_Socket, (struct sockaddr *)&addr, len) >= 0 ) - { - return (pPipe); - } - - OSL_TRACE("osl_createPipe failed to connect. Errno: %d; %s",errno,strerror(errno)); - } - - close (pPipe->m_Socket); - __osl_destroyPipeImpl(pPipe); - return NULL; - } -} - -void SAL_CALL osl_acquirePipe( oslPipe pPipe ) -{ - osl_atomic_increment( &(pPipe->m_nRefCount) ); -} - -void SAL_CALL osl_releasePipe( oslPipe pPipe ) -{ - - if( 0 == pPipe ) - return; - - if( 0 == osl_atomic_decrement( &(pPipe->m_nRefCount) ) ) - { - if( ! pPipe->m_bClosed ) - osl_closePipe( pPipe ); - - __osl_destroyPipeImpl( pPipe ); - } -} - -void SAL_CALL osl_closePipe( oslPipe pPipe ) -{ - int nRet; -#if defined(LINUX) - size_t len; - struct sockaddr_un addr; - int fd; -#endif - int ConnFD; - - if( ! pPipe ) - { - return; - } - - if( pPipe->m_bClosed ) - { - return; - } - - ConnFD = pPipe->m_Socket; - - /* - Thread does not return from accept on linux, so - connect to the accepting pipe - */ -#if defined(LINUX) - if ( pPipe->m_bIsAccepting ) - { - pPipe->m_bIsInShutdown = sal_True; - pPipe->m_Socket = -1; - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if ( fd < 0 ) - { - OSL_TRACE("socket in osl_destroyPipe failed with error: %s", strerror(errno)); - return; - } - memset(&addr, 0, sizeof(addr)); - - OSL_TRACE("osl_destroyPipe : Pipe Name '%s'",pPipe->m_Name); - - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, pPipe->m_Name, sizeof(addr.sun_path) - 1); - len = sizeof(addr); - - nRet = connect( fd, (struct sockaddr *)&addr, len); - if ( nRet < 0 ) - { - OSL_TRACE("connect in osl_destroyPipe failed with error: %s", strerror(errno)); - } - close(fd); - } -#endif /* LINUX */ - - nRet = shutdown(ConnFD, 2); - if ( nRet < 0 ) - { - OSL_TRACE("shutdown in destroyPipe failed : '%s'",strerror(errno)); - } - - nRet = close(ConnFD); - if ( nRet < 0 ) - { - OSL_TRACE("close in destroyPipe failed : '%s'",strerror(errno)); - } - /* remove filesystem entry */ - if ( strlen(pPipe->m_Name) > 0 ) - { - unlink(pPipe->m_Name); - } - pPipe->m_bClosed = sal_True; - -/* OSL_TRACE("Out osl_destroyPipe"); */ -} - -oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe) -{ - int s, flags; - oslPipe pAcceptedPipe; - - OSL_ASSERT(pPipe); - if ( pPipe == 0 ) - { - return NULL; - } - - OSL_ASSERT(strlen(pPipe->m_Name) > 0); - -#if defined(LINUX) - pPipe->m_bIsAccepting = sal_True; -#endif - - s = accept(pPipe->m_Socket, NULL, NULL); - -#if defined(LINUX) - pPipe->m_bIsAccepting = sal_False; -#endif - - if (s < 0) - { - OSL_TRACE("osl_acceptPipe : accept error '%s'", strerror(errno)); - return NULL; - } - -#if defined(LINUX) - if ( pPipe->m_bIsInShutdown ) - { - close(s); - return NULL; - } -#endif /* LINUX */ - else - { - /* alloc memory */ - pAcceptedPipe = __osl_createPipeImpl(); - - OSL_ASSERT(pAcceptedPipe); - if(pAcceptedPipe==NULL) - { - close(s); - return NULL; - } - - /* set close-on-exec flag */ - if (!((flags = fcntl(s, F_GETFD, 0)) < 0)) - { - flags |= FD_CLOEXEC; - if (fcntl(s, F_SETFD, flags) < 0) - { - OSL_TRACE("osl_acceptPipe: error changing socket flags. " - "Errno: %d; %s",errno,strerror(errno)); - } - } - - pAcceptedPipe->m_Socket = s; - } - - return pAcceptedPipe; -} - -sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe, - void* pBuffer, - sal_Int32 BytesToRead) -{ - int nRet = 0; - - OSL_ASSERT(pPipe); - - if ( pPipe == 0 ) - { - OSL_TRACE("osl_receivePipe : Invalid socket"); - errno=EINVAL; - return -1; - } - - nRet = recv(pPipe->m_Socket, - (sal_Char*)pBuffer, - BytesToRead, 0); - - if ( nRet < 0 ) - { - OSL_TRACE("osl_receivePipe failed : %i '%s'",nRet,strerror(errno)); - } - - return nRet; -} - -sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe, - const void* pBuffer, - sal_Int32 BytesToSend) -{ - int nRet=0; - - OSL_ASSERT(pPipe); - - if ( pPipe == 0 ) - { - OSL_TRACE("osl_sendPipe : Invalid socket"); - errno=EINVAL; - return -1; - } - - nRet = send(pPipe->m_Socket, - (sal_Char*)pBuffer, - BytesToSend, 0); - - if ( nRet <= 0 ) - { - OSL_TRACE("osl_sendPipe failed : %i '%s'",nRet,strerror(errno)); - } - - return nRet; -} - -oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe) -{ - (void) pPipe; /* unused */ - return ERROR_FROM_NATIVE(errno); -} - -sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n ) -{ - /* loop until all desired bytes were send or an error occurred */ - sal_Int32 BytesSend= 0; - sal_Int32 BytesToSend= n; - - OSL_ASSERT(pPipe); - while (BytesToSend > 0) - { - sal_Int32 RetVal; - - RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend); - - /* error occurred? */ - if(RetVal <= 0) - { - break; - } - - BytesToSend -= RetVal; - BytesSend += RetVal; - pBuffer= (sal_Char*)pBuffer + RetVal; - } - - return BytesSend; -} - -sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n ) -{ - /* loop until all desired bytes were read or an error occurred */ - sal_Int32 BytesRead= 0; - sal_Int32 BytesToRead= n; - - OSL_ASSERT( pPipe ); - while (BytesToRead > 0) - { - sal_Int32 RetVal; - RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead); - - /* error occurred? */ - if(RetVal <= 0) - { - break; - } - - BytesToRead -= RetVal; - BytesRead += RetVal; - pBuffer= (sal_Char*)pBuffer + RetVal; - } - return BytesRead; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/unx/pipe.cxx b/sal/osl/unx/pipe.cxx new file mode 100644 index 000000000000..ec78c2aee446 --- /dev/null +++ b/sal/osl/unx/pipe.cxx @@ -0,0 +1,612 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "system.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "sockimpl.h" +#include "secimpl.h" + +#define PIPEDEFAULTPATH "/tmp" +#define PIPEALTERNATEPATH "/var/tmp" + +#define PIPENAMEMASK "OSL_PIPE_%s" +#define SECPIPENAMEMASK "OSL_PIPE_%s_%s" + +oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, oslSecurity Security); + +static struct +{ + int errcode; + oslPipeError error; +} PipeError[]= { + { 0, osl_Pipe_E_None }, /* no error */ + { EPROTOTYPE, osl_Pipe_E_NoProtocol }, /* Protocol wrong type for socket */ + { ENOPROTOOPT, osl_Pipe_E_NoProtocol }, /* Protocol not available */ + { EPROTONOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol not supported */ + { ESOCKTNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Socket type not supported */ + { EPFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Protocol family not supported */ + { EAFNOSUPPORT, osl_Pipe_E_NoProtocol }, /* Address family not supported by */ + /* protocol family */ + { ENETRESET, osl_Pipe_E_NetworkReset }, /* Network dropped connection because */ + /* of reset */ + { ECONNABORTED, osl_Pipe_E_ConnectionAbort }, /* Software caused connection abort */ + { ECONNRESET, osl_Pipe_E_ConnectionReset }, /* Connection reset by peer */ + { ENOBUFS, osl_Pipe_E_NoBufferSpace }, /* No buffer space available */ + { ETIMEDOUT, osl_Pipe_E_TimedOut }, /* Connection timed out */ + { ECONNREFUSED, osl_Pipe_E_ConnectionRefused }, /* Connection refused */ + { -1, osl_Pipe_E_invalidError } +}; + +/* map */ +/* mfe: NOT USED + static int osl_NativeFromPipeError(oslPipeError errorCode) + { + int i = 0; + + while ((PipeError[i].error != osl_Pipe_E_invalidError) && + (PipeError[i].error != errorCode)) i++; + + return PipeError[i].errcode; + + } +*/ + +/* reverse map */ +static oslPipeError osl_PipeErrorFromNative(int nativeType) +{ + int i = 0; + + while ((PipeError[i].error != osl_Pipe_E_invalidError) && + (PipeError[i].errcode != nativeType)) i++; + + return PipeError[i].error; +} + +/* macros */ +#define ERROR_FROM_NATIVE(y) osl_PipeErrorFromNative(y) + +oslPipe __osl_createPipeImpl(void) +{ + oslPipe pPipeImpl; + + pPipeImpl = (oslPipe)calloc(1, sizeof(struct oslPipeImpl)); + if (pPipeImpl == NULL) + return NULL; + pPipeImpl->m_nRefCount =1; + pPipeImpl->m_bClosed = sal_False; +#if defined(LINUX) + pPipeImpl->m_bIsInShutdown = sal_False; + pPipeImpl->m_bIsAccepting = sal_False; +#endif + return pPipeImpl; +} + +void __osl_destroyPipeImpl(oslPipe pImpl) +{ + if (pImpl != NULL) + free(pImpl); +} + +oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options, oslSecurity Security) +{ + oslPipe pPipe=0; + rtl_String* strPipeName=0; + sal_Char* pszPipeName=0; + + if ( ustrPipeName != 0 ) + { + rtl_uString2String( &strPipeName, + rtl_uString_getStr(ustrPipeName), + rtl_uString_getLength(ustrPipeName), + osl_getThreadTextEncoding(), + OUSTRING_TO_OSTRING_CVTFLAGS ); + pszPipeName = rtl_string_getStr(strPipeName); + pPipe = osl_psz_createPipe(pszPipeName, Options, Security); + + if ( strPipeName != 0 ) + { + rtl_string_release(strPipeName); + } + } + + return pPipe; + +} + +static bool +cpyBootstrapSocketPath(sal_Char *name, size_t len) +{ + bool bRet = false; + rtl_uString *pName = 0, *pValue = 0; + + rtl_uString_newFromAscii(&pName, "OSL_SOCKET_PATH"); + + if (rtl_bootstrap_get(pName, &pValue, NULL)) + { + if (pValue && pValue->length > 0) + { + rtl_String *pStrValue = 0; + + rtl_uString2String(&pStrValue, pValue->buffer, + pValue->length, RTL_TEXTENCODING_UTF8, + OUSTRING_TO_OSTRING_CVTFLAGS); + if (pStrValue) + { + if (pStrValue->length > 0) + { + size_t nCopy = (len-1 < (size_t)pStrValue->length) ? len-1 : (size_t)pStrValue->length; + strncpy (name, pStrValue->buffer, nCopy); + name[nCopy] = '\0'; + bRet = (size_t)pStrValue->length < len; + } + rtl_string_release(pStrValue); + } + } + rtl_uString_release(pName); + } + return bRet; +} + +oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, + oslSecurity Security) +{ + int Flags; + size_t len; + struct sockaddr_un addr; + + sal_Char name[PATH_MAX + 1]; + size_t nNameLength = 0; + bool bNameTooLong = false; + oslPipe pPipe; + + if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0) + { + strncpy(name, PIPEDEFAULTPATH, sizeof(name)); + } + else if (access(PIPEALTERNATEPATH, R_OK|W_OK) == 0) + { + strncpy(name, PIPEALTERNATEPATH, sizeof(name)); + } + else if (!cpyBootstrapSocketPath (name, sizeof (name))) + { + return NULL; + } + name[sizeof(name) - 1] = '\0'; // ensure the string is NULL-terminated + nNameLength = strlen(name); + bNameTooLong = nNameLength > sizeof(name) - 2; + + if (!bNameTooLong) + { + size_t nRealLength = 0; + + strcat(name, "/"); + ++nNameLength; + + if (Security) + { + sal_Char Ident[256]; + + Ident[0] = '\0'; + + OSL_VERIFY(osl_psz_getUserIdent(Security, Ident, sizeof(Ident))); + + nRealLength = snprintf(&name[nNameLength], sizeof(name) - nNameLength, SECPIPENAMEMASK, Ident, pszPipeName); + } + else + { + nRealLength = snprintf(&name[nNameLength], sizeof(name) - nNameLength, PIPENAMEMASK, pszPipeName); + } + + bNameTooLong = nRealLength > sizeof(name) - nNameLength - 1; + } + + if (bNameTooLong) + { + OSL_TRACE("osl_createPipe: pipe name too long"); + return NULL; + } + + /* alloc memory */ + pPipe = __osl_createPipeImpl(); + + if (pPipe == NULL) + { + OSL_TRACE("__osl_createPipe socket failed"); + return NULL; + } + + /* create socket */ + pPipe->m_Socket = socket(AF_UNIX, SOCK_STREAM, 0); + if ( pPipe->m_Socket < 0 ) + { + OSL_TRACE("osl_createPipe socket failed. Errno: %d; %s",errno, strerror(errno)); + __osl_destroyPipeImpl(pPipe); + return NULL; + } + +/* OSL_TRACE("osl_createPipe : new Pipe on fd %i\n",pPipe->m_Socket);*/ + + /* set close-on-exec flag */ + if ((Flags = fcntl(pPipe->m_Socket, F_GETFD, 0)) != -1) + { + Flags |= FD_CLOEXEC; + if (fcntl(pPipe->m_Socket, F_SETFD, Flags) == -1) + { + OSL_TRACE("osl_createPipe failed changing socket flags. Errno: %d; %s",errno,strerror(errno)); + } + } + + memset(&addr, 0, sizeof(addr)); + + OSL_TRACE("osl_createPipe : Pipe Name '%s'",name); + + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, name, sizeof(addr.sun_path) - 1); +#if defined(FREEBSD) + len = SUN_LEN(&addr); +#else + len = sizeof(addr); +#endif + + if ( Options & osl_Pipe_CREATE ) + { + struct stat status; + + /* check if there exists an orphan filesystem entry */ + if ( ( stat(name, &status) == 0) && + ( S_ISSOCK(status.st_mode) || S_ISFIFO(status.st_mode) ) ) + { + if ( connect(pPipe->m_Socket,(struct sockaddr *)&addr,len) >= 0 ) + { + OSL_TRACE("osl_createPipe : Pipe already in use. Errno: %d; %s",errno,strerror(errno)); + close (pPipe->m_Socket); + __osl_destroyPipeImpl(pPipe); + return NULL; + } + + unlink(name); + } + + /* ok, fs clean */ + if ( bind(pPipe->m_Socket, (struct sockaddr *)&addr, len) < 0 ) + { + OSL_TRACE("osl_createPipe : failed to bind socket. Errno: %d; %s",errno,strerror(errno)); + close (pPipe->m_Socket); + __osl_destroyPipeImpl(pPipe); + return NULL; + } + + /* Only give access to all if no security handle was specified, otherwise security + depends on umask */ + + if ( !Security ) + chmod(name,S_IRWXU | S_IRWXG |S_IRWXO); + + strncpy(pPipe->m_Name, name, sizeof(pPipe->m_Name) - 1); + + if ( listen(pPipe->m_Socket, 5) < 0 ) + { + OSL_TRACE("osl_createPipe failed to listen. Errno: %d; %s",errno,strerror(errno)); + unlink(name); /* remove filesystem entry */ + close (pPipe->m_Socket); + __osl_destroyPipeImpl(pPipe); + return NULL; + } + + return (pPipe); + } + else + { /* osl_pipe_OPEN */ + if ( access(name, F_OK) != -1 ) + { + if ( connect( pPipe->m_Socket, (struct sockaddr *)&addr, len) >= 0 ) + { + return (pPipe); + } + + OSL_TRACE("osl_createPipe failed to connect. Errno: %d; %s",errno,strerror(errno)); + } + + close (pPipe->m_Socket); + __osl_destroyPipeImpl(pPipe); + return NULL; + } +} + +void SAL_CALL osl_acquirePipe( oslPipe pPipe ) +{ + osl_atomic_increment( &(pPipe->m_nRefCount) ); +} + +void SAL_CALL osl_releasePipe( oslPipe pPipe ) +{ + + if( 0 == pPipe ) + return; + + if( 0 == osl_atomic_decrement( &(pPipe->m_nRefCount) ) ) + { + if( ! pPipe->m_bClosed ) + osl_closePipe( pPipe ); + + __osl_destroyPipeImpl( pPipe ); + } +} + +void SAL_CALL osl_closePipe( oslPipe pPipe ) +{ + int nRet; +#if defined(LINUX) + size_t len; + struct sockaddr_un addr; + int fd; +#endif + int ConnFD; + + if( ! pPipe ) + { + return; + } + + if( pPipe->m_bClosed ) + { + return; + } + + ConnFD = pPipe->m_Socket; + + /* + Thread does not return from accept on linux, so + connect to the accepting pipe + */ +#if defined(LINUX) + if ( pPipe->m_bIsAccepting ) + { + pPipe->m_bIsInShutdown = sal_True; + pPipe->m_Socket = -1; + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if ( fd < 0 ) + { + OSL_TRACE("socket in osl_destroyPipe failed with error: %s", strerror(errno)); + return; + } + memset(&addr, 0, sizeof(addr)); + + OSL_TRACE("osl_destroyPipe : Pipe Name '%s'",pPipe->m_Name); + + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, pPipe->m_Name, sizeof(addr.sun_path) - 1); + len = sizeof(addr); + + nRet = connect( fd, (struct sockaddr *)&addr, len); + if ( nRet < 0 ) + { + OSL_TRACE("connect in osl_destroyPipe failed with error: %s", strerror(errno)); + } + close(fd); + } +#endif /* LINUX */ + + nRet = shutdown(ConnFD, 2); + if ( nRet < 0 ) + { + OSL_TRACE("shutdown in destroyPipe failed : '%s'",strerror(errno)); + } + + nRet = close(ConnFD); + if ( nRet < 0 ) + { + OSL_TRACE("close in destroyPipe failed : '%s'",strerror(errno)); + } + /* remove filesystem entry */ + if ( strlen(pPipe->m_Name) > 0 ) + { + unlink(pPipe->m_Name); + } + pPipe->m_bClosed = sal_True; + +/* OSL_TRACE("Out osl_destroyPipe"); */ +} + +oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe) +{ + int s, flags; + oslPipe pAcceptedPipe; + + OSL_ASSERT(pPipe); + if ( pPipe == 0 ) + { + return NULL; + } + + OSL_ASSERT(strlen(pPipe->m_Name) > 0); + +#if defined(LINUX) + pPipe->m_bIsAccepting = sal_True; +#endif + + s = accept(pPipe->m_Socket, NULL, NULL); + +#if defined(LINUX) + pPipe->m_bIsAccepting = sal_False; +#endif + + if (s < 0) + { + OSL_TRACE("osl_acceptPipe : accept error '%s'", strerror(errno)); + return NULL; + } + +#if defined(LINUX) + if ( pPipe->m_bIsInShutdown ) + { + close(s); + return NULL; + } +#endif /* LINUX */ + else + { + /* alloc memory */ + pAcceptedPipe = __osl_createPipeImpl(); + + OSL_ASSERT(pAcceptedPipe); + if(pAcceptedPipe==NULL) + { + close(s); + return NULL; + } + + /* set close-on-exec flag */ + if (!((flags = fcntl(s, F_GETFD, 0)) < 0)) + { + flags |= FD_CLOEXEC; + if (fcntl(s, F_SETFD, flags) < 0) + { + OSL_TRACE("osl_acceptPipe: error changing socket flags. " + "Errno: %d; %s",errno,strerror(errno)); + } + } + + pAcceptedPipe->m_Socket = s; + } + + return pAcceptedPipe; +} + +sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe, + void* pBuffer, + sal_Int32 BytesToRead) +{ + int nRet = 0; + + OSL_ASSERT(pPipe); + + if ( pPipe == 0 ) + { + OSL_TRACE("osl_receivePipe : Invalid socket"); + errno=EINVAL; + return -1; + } + + nRet = recv(pPipe->m_Socket, + (sal_Char*)pBuffer, + BytesToRead, 0); + + if ( nRet < 0 ) + { + OSL_TRACE("osl_receivePipe failed : %i '%s'",nRet,strerror(errno)); + } + + return nRet; +} + +sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe, + const void* pBuffer, + sal_Int32 BytesToSend) +{ + int nRet=0; + + OSL_ASSERT(pPipe); + + if ( pPipe == 0 ) + { + OSL_TRACE("osl_sendPipe : Invalid socket"); + errno=EINVAL; + return -1; + } + + nRet = send(pPipe->m_Socket, + (sal_Char*)pBuffer, + BytesToSend, 0); + + if ( nRet <= 0 ) + { + OSL_TRACE("osl_sendPipe failed : %i '%s'",nRet,strerror(errno)); + } + + return nRet; +} + +oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe) +{ + (void) pPipe; /* unused */ + return ERROR_FROM_NATIVE(errno); +} + +sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n ) +{ + /* loop until all desired bytes were send or an error occurred */ + sal_Int32 BytesSend= 0; + sal_Int32 BytesToSend= n; + + OSL_ASSERT(pPipe); + while (BytesToSend > 0) + { + sal_Int32 RetVal; + + RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend); + + /* error occurred? */ + if(RetVal <= 0) + { + break; + } + + BytesToSend -= RetVal; + BytesSend += RetVal; + pBuffer= (sal_Char*)pBuffer + RetVal; + } + + return BytesSend; +} + +sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n ) +{ + /* loop until all desired bytes were read or an error occurred */ + sal_Int32 BytesRead= 0; + sal_Int32 BytesToRead= n; + + OSL_ASSERT( pPipe ); + while (BytesToRead > 0) + { + sal_Int32 RetVal; + RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead); + + /* error occurred? */ + if(RetVal <= 0) + { + break; + } + + BytesToRead -= RetVal; + BytesRead += RetVal; + pBuffer= (sal_Char*)pBuffer + RetVal; + } + return BytesRead; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit