summaryrefslogtreecommitdiff
path: root/sal/osl
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl')
-rw-r--r--sal/osl/all/debugbase.cxx161
-rw-r--r--sal/osl/all/filepath.c123
-rw-r--r--sal/osl/all/loadmodulerelative.cxx71
-rw-r--r--sal/osl/all/makefile.mk76
-rwxr-xr-xsal/osl/all/utility.cxx103
-rw-r--r--sal/osl/os2/conditn.c124
-rw-r--r--sal/osl/os2/debug.c2152
-rw-r--r--sal/osl/os2/diagnose.c178
-rw-r--r--sal/osl/os2/dllentry.c75
-rw-r--r--sal/osl/os2/except.c1059
-rw-r--r--sal/osl/os2/file.cxx3129
-rw-r--r--sal/osl/os2/file_error_transl.cxx252
-rw-r--r--sal/osl/os2/file_error_transl.h70
-rw-r--r--sal/osl/os2/file_path_helper.cxx377
-rw-r--r--sal/osl/os2/file_path_helper.h292
-rw-r--r--sal/osl/os2/file_path_helper.hxx296
-rw-r--r--sal/osl/os2/file_url.cxx1626
-rw-r--r--sal/osl/os2/file_url.h183
-rw-r--r--sal/osl/os2/helpers/debug.h1779
-rw-r--r--sal/osl/os2/helpers/dosh.h49
-rw-r--r--sal/osl/os2/helpers/except.h255
-rw-r--r--sal/osl/os2/helpers/setup.h147
-rw-r--r--sal/osl/os2/interlck.c51
-rw-r--r--sal/osl/os2/libutil.c52
-rw-r--r--sal/osl/os2/makefile.mk118
-rw-r--r--sal/osl/os2/module.c281
-rw-r--r--sal/osl/os2/mutex.c167
-rw-r--r--sal/osl/os2/nlsupport.c445
-rw-r--r--sal/osl/os2/path_helper.cxx116
-rw-r--r--sal/osl/os2/path_helper.h70
-rw-r--r--sal/osl/os2/path_helper.hxx73
-rw-r--r--sal/osl/os2/pipe.cxx555
-rw-r--r--sal/osl/os2/pipeimpl.cxx755
-rw-r--r--sal/osl/os2/pipeimpl.h82
-rw-r--r--sal/osl/os2/process.c1013
-rw-r--r--sal/osl/os2/process_impl.cxx371
-rw-r--r--sal/osl/os2/procimpl.h52
-rw-r--r--sal/osl/os2/profile.c2295
-rw-r--r--sal/osl/os2/salinit.cxx120
-rw-r--r--sal/osl/os2/secimpl.h50
-rw-r--r--sal/osl/os2/security.c317
-rw-r--r--sal/osl/os2/semaphor.c190
-rw-r--r--sal/osl/os2/signal.c249
-rw-r--r--sal/osl/os2/socket.c3097
-rw-r--r--sal/osl/os2/sockimpl.h80
-rw-r--r--sal/osl/os2/system.h514
-rw-r--r--sal/osl/os2/tempfile.c359
-rw-r--r--sal/osl/os2/thread.c772
-rw-r--r--sal/osl/os2/time.c269
-rw-r--r--sal/osl/os2/util.c37
-rw-r--r--sal/osl/os2/uunxapi.cxx86
-rw-r--r--sal/osl/os2/uunxapi.h86
-rw-r--r--sal/osl/os2/uunxapi.hxx106
-rw-r--r--sal/osl/unx/asm/interlck_sparc.s267
-rw-r--r--sal/osl/unx/asm/interlck_x86.s92
-rwxr-xr-xsal/osl/unx/backtrace.c359
-rwxr-xr-xsal/osl/unx/backtrace.h99
-rw-r--r--sal/osl/unx/conditn.c350
-rw-r--r--sal/osl/unx/diagnose.c332
-rw-r--r--sal/osl/unx/file.cxx1397
-rw-r--r--sal/osl/unx/file_error_transl.cxx255
-rw-r--r--sal/osl/unx/file_error_transl.h70
-rw-r--r--sal/osl/unx/file_impl.hxx54
-rw-r--r--sal/osl/unx/file_misc.cxx1101
-rw-r--r--sal/osl/unx/file_path_helper.cxx350
-rw-r--r--sal/osl/unx/file_path_helper.h247
-rw-r--r--sal/osl/unx/file_path_helper.hxx247
-rw-r--r--sal/osl/unx/file_stat.cxx492
-rw-r--r--sal/osl/unx/file_url.cxx962
-rw-r--r--sal/osl/unx/file_url.h69
-rw-r--r--sal/osl/unx/file_volume.cxx1155
-rw-r--r--sal/osl/unx/interlck.c170
-rw-r--r--sal/osl/unx/makefile.mk189
-rw-r--r--sal/osl/unx/module.c242
-rw-r--r--sal/osl/unx/mutex.c221
-rw-r--r--sal/osl/unx/nlsupport.c949
-rw-r--r--sal/osl/unx/osxlocale.cxx129
-rw-r--r--sal/osl/unx/pipe.c592
-rw-r--r--sal/osl/unx/process.c1536
-rw-r--r--sal/osl/unx/process_impl.cxx412
-rw-r--r--sal/osl/unx/procimpl.h50
-rw-r--r--sal/osl/unx/profile.c2221
-rw-r--r--sal/osl/unx/salinit.cxx43
-rw-r--r--sal/osl/unx/secimpl.h47
-rw-r--r--sal/osl/unx/security.c862
-rw-r--r--sal/osl/unx/semaphor.c314
-rw-r--r--sal/osl/unx/signal.c1093
-rw-r--r--sal/osl/unx/socket.c3062
-rw-r--r--sal/osl/unx/sockimpl.h78
-rw-r--r--sal/osl/unx/system.c599
-rw-r--r--sal/osl/unx/system.h495
-rw-r--r--sal/osl/unx/tempfile.c370
-rw-r--r--sal/osl/unx/thread.c1035
-rw-r--r--sal/osl/unx/time.c269
-rw-r--r--sal/osl/unx/util.c350
-rw-r--r--sal/osl/unx/uunxapi.cxx130
-rw-r--r--sal/osl/unx/uunxapi.h86
-rw-r--r--sal/osl/unx/uunxapi.hxx98
-rw-r--r--sal/osl/w32/MAKEFILE.MK118
-rw-r--r--sal/osl/w32/conditn.c141
-rw-r--r--sal/osl/w32/diagnose.c188
-rw-r--r--sal/osl/w32/dllentry.c370
-rw-r--r--sal/osl/w32/file.cxx1194
-rw-r--r--sal/osl/w32/file_dirvol.cxx1867
-rw-r--r--sal/osl/w32/file_error.c151
-rw-r--r--sal/osl/w32/file_error.h51
-rw-r--r--sal/osl/w32/file_url.cxx1143
-rw-r--r--sal/osl/w32/file_url.h96
-rw-r--r--sal/osl/w32/interlck.c142
-rw-r--r--sal/osl/w32/libutil.c54
-rw-r--r--sal/osl/w32/module.cxx480
-rw-r--r--sal/osl/w32/mutex.c206
-rw-r--r--sal/osl/w32/nlsupport.c231
-rw-r--r--sal/osl/w32/path_helper.cxx118
-rw-r--r--sal/osl/w32/path_helper.h70
-rw-r--r--sal/osl/w32/path_helper.hxx118
-rw-r--r--sal/osl/w32/pipe.c636
-rw-r--r--sal/osl/w32/pipeimpl.cxx785
-rw-r--r--sal/osl/w32/pipeimpl.h88
-rw-r--r--sal/osl/w32/process.cxx620
-rw-r--r--sal/osl/w32/procimpl.cxx606
-rw-r--r--sal/osl/w32/procimpl.h47
-rw-r--r--sal/osl/w32/profile.cxx2707
-rw-r--r--sal/osl/w32/salinit.cxx82
-rw-r--r--sal/osl/w32/secimpl.h54
-rw-r--r--sal/osl/w32/security.c991
-rw-r--r--sal/osl/w32/semaphor.c111
-rw-r--r--sal/osl/w32/signal.cxx436
-rw-r--r--sal/osl/w32/socket.cxx2190
-rw-r--r--sal/osl/w32/sockimpl.h108
-rw-r--r--sal/osl/w32/system.h126
-rw-r--r--sal/osl/w32/tempfile.cxx274
-rw-r--r--sal/osl/w32/thread.c593
-rw-r--r--sal/osl/w32/time.c216
-rw-r--r--sal/osl/w32/util.c37
135 files changed, 66390 insertions, 0 deletions
diff --git a/sal/osl/all/debugbase.cxx b/sal/osl/all/debugbase.cxx
new file mode 100644
index 000000000000..10679cb45ccb
--- /dev/null
+++ b/sal/osl/all/debugbase.cxx
@@ -0,0 +1,161 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "rtl/strbuf.hxx"
+#include "rtl/string.hxx"
+#include "rtl/ustring.hxx"
+#include "osl/process.h"
+#include "osl/diagnose.hxx"
+#include "boost/bind.hpp"
+#include <vector>
+
+// define own ones, independent of OSL_DEBUG_LEVEL:
+#define DEBUGBASE_ENSURE_(c, f, l, m) \
+ do \
+ { \
+ if (!(c) && _OSL_GLOBAL osl_assertFailedLine(f, l, m)) \
+ _OSL_GLOBAL osl_breakDebug(); \
+ } while (0)
+#define DEBUGBASE_ENSURE(c, m) DEBUGBASE_ENSURE_(c, OSL_THIS_FILE, __LINE__, m)
+
+namespace {
+
+typedef std::vector<rtl::OString, rtl::Allocator<rtl::OString> > OStringVec;
+
+struct StaticDebugBaseAddressFilter
+ : rtl::StaticWithInit<OStringVec const, StaticDebugBaseAddressFilter> {
+ OStringVec const operator()() const {
+ OStringVec vec;
+ rtl_uString * pStr = 0;
+ rtl::OUString const name(
+ RTL_CONSTASCII_USTRINGPARAM("OSL_DEBUGBASE_STORE_ADDRESSES") );
+ if (osl_getEnvironment( name.pData, &pStr ) == osl_Process_E_None) {
+ rtl::OUString const str(pStr);
+ rtl_uString_release(pStr);
+ sal_Int32 nIndex = 0;
+ do {
+ vec.push_back( rtl::OUStringToOString(
+ str.getToken( 0, ';', nIndex ),
+ RTL_TEXTENCODING_ASCII_US ) );
+ }
+ while (nIndex >= 0);
+ }
+ return vec;
+ }
+};
+
+inline bool isSubStr( char const* pStr, rtl::OString const& subStr )
+{
+ return rtl_str_indexOfStr( pStr, subStr.getStr() ) >= 0;
+}
+
+struct DebugBaseMutex : ::rtl::Static<osl::Mutex, DebugBaseMutex> {};
+
+} // anon namespace
+
+extern "C" {
+
+osl::Mutex & SAL_CALL osl_detail_ObjectRegistry_getMutex()
+ SAL_THROW_EXTERN_C()
+{
+ return DebugBaseMutex::get();
+}
+
+bool SAL_CALL osl_detail_ObjectRegistry_storeAddresses( char const* pName )
+ SAL_THROW_EXTERN_C()
+{
+ OStringVec const& rVec = StaticDebugBaseAddressFilter::get();
+ if (rVec.empty())
+ return false;
+ // check for "all":
+ rtl::OString const& rFirst = rVec[0];
+ if (rtl_str_compare_WithLength( rFirst.getStr(), rFirst.getLength(),
+ RTL_CONSTASCII_STRINGPARAM("all") ) == 0)
+ return true;
+ OStringVec::const_iterator const iEnd( rVec.end() );
+ return std::find_if( rVec.begin(), iEnd,
+ boost::bind( &isSubStr, pName, _1 ) ) != iEnd;
+}
+
+bool SAL_CALL osl_detail_ObjectRegistry_checkObjectCount(
+ osl::detail::ObjectRegistryData const& rData, std::size_t nExpected )
+ SAL_THROW_EXTERN_C()
+{
+ std::size_t nSize;
+ if (rData.m_bStoreAddresses)
+ nSize = rData.m_addresses.size();
+ else
+ nSize = static_cast<std::size_t>(rData.m_nCount);
+
+ bool const bRet = (nSize == nExpected);
+ if (! bRet) {
+ rtl::OStringBuffer buf;
+ buf.append( RTL_CONSTASCII_STRINGPARAM("unexpected number of ") );
+ buf.append( rData.m_pName );
+ buf.append( RTL_CONSTASCII_STRINGPARAM(": ") );
+ buf.append( static_cast<sal_Int64>(nSize) );
+ DEBUGBASE_ENSURE( false, buf.makeStringAndClear().getStr() );
+ }
+ return bRet;
+}
+
+void SAL_CALL osl_detail_ObjectRegistry_registerObject(
+ osl::detail::ObjectRegistryData & rData, void const* pObj )
+ SAL_THROW_EXTERN_C()
+{
+ if (rData.m_bStoreAddresses) {
+ osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() );
+ std::pair<osl::detail::VoidPointerSet::iterator, bool> const insertion(
+ rData.m_addresses.insert(pObj) );
+ DEBUGBASE_ENSURE( insertion.second, "### insertion failed!?" );
+ static_cast<void>(insertion);
+ }
+ else {
+ osl_incrementInterlockedCount(&rData.m_nCount);
+ }
+}
+
+void SAL_CALL osl_detail_ObjectRegistry_revokeObject(
+ osl::detail::ObjectRegistryData & rData, void const* pObj )
+ SAL_THROW_EXTERN_C()
+{
+ if (rData.m_bStoreAddresses) {
+ osl::MutexGuard const guard( osl_detail_ObjectRegistry_getMutex() );
+ std::size_t const n = rData.m_addresses.erase(pObj);
+ DEBUGBASE_ENSURE( n == 1, "erased more than 1 entry!?" );
+ static_cast<void>(n);
+ }
+ else {
+ osl_decrementInterlockedCount(&rData.m_nCount);
+ }
+}
+
+} // extern "C"
+
diff --git a/sal/osl/all/filepath.c b/sal/osl/all/filepath.c
new file mode 100644
index 000000000000..e9461a538840
--- /dev/null
+++ b/sal/osl/all/filepath.c
@@ -0,0 +1,123 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <osl/file.h>
+#include <rtl/ustring.h>
+
+static sal_uInt32 SAL_CALL osl_defCalcTextWidth( rtl_uString *ustrText )
+{
+ return ustrText ? ustrText->length : 0;
+}
+
+
+oslFileError SAL_CALL osl_abbreviateSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrCompacted, sal_uInt32 uMaxWidth, oslCalcTextWidthFunc pfnCalcWidth )
+{
+ oslFileError error = osl_File_E_None;
+ rtl_uString *ustrPath = NULL;
+ rtl_uString *ustrFile = NULL;
+ sal_uInt32 uPathWidth, uFileWidth;
+
+ if ( !pfnCalcWidth )
+ pfnCalcWidth = osl_defCalcTextWidth;
+
+ {
+ sal_Int32 iLastSlash = rtl_ustr_lastIndexOfChar_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, SAL_PATHDELIMITER );
+
+ if ( iLastSlash >= 0 )
+ {
+ rtl_uString_newFromStr_WithLength( &ustrPath, ustrSystemPath->buffer, iLastSlash );
+ rtl_uString_newFromStr_WithLength( &ustrFile, &ustrSystemPath->buffer[iLastSlash], ustrSystemPath->length - iLastSlash );
+ }
+ else
+ {
+ rtl_uString_new( &ustrPath );
+ rtl_uString_newFromString( &ustrFile, ustrSystemPath );
+ }
+ }
+
+ uPathWidth = pfnCalcWidth( ustrPath );
+ uFileWidth = pfnCalcWidth( ustrFile );
+
+ /* First abbreviate the directory component of the path */
+
+ while ( uPathWidth + uFileWidth > uMaxWidth )
+ {
+ if ( ustrPath->length > 3 )
+ {
+ ustrPath->length--;
+ ustrPath->buffer[ustrPath->length-3] = '.';
+ ustrPath->buffer[ustrPath->length-2] = '.';
+ ustrPath->buffer[ustrPath->length-1] = '.';
+ ustrPath->buffer[ustrPath->length] = 0;
+
+ uPathWidth = pfnCalcWidth( ustrPath );
+ }
+ else
+ break;
+ }
+
+ /* Now abbreviate file component */
+
+ while ( uPathWidth + uFileWidth > uMaxWidth )
+ {
+ if ( ustrFile->length > 4 )
+ {
+ ustrFile->length--;
+ ustrFile->buffer[ustrFile->length-3] = '.';
+ ustrFile->buffer[ustrFile->length-2] = '.';
+ ustrFile->buffer[ustrFile->length-1] = '.';
+ ustrFile->buffer[ustrFile->length] = 0;
+
+ uFileWidth = pfnCalcWidth( ustrFile );
+ }
+ else
+ break;
+ }
+
+ rtl_uString_newConcat( pustrCompacted, ustrPath, ustrFile );
+
+ /* Event now if path was compacted to ".../..." it can be to large */
+
+ uPathWidth += uFileWidth;
+
+ while ( uPathWidth > uMaxWidth )
+ {
+ (*pustrCompacted)->length--;
+ (*pustrCompacted)->buffer[(*pustrCompacted)->length] = 0;
+ uPathWidth = pfnCalcWidth( *pustrCompacted );
+ }
+
+ if ( ustrPath )
+ rtl_uString_release( ustrPath );
+
+ if ( ustrFile )
+ rtl_uString_release( ustrFile );
+
+ return error;
+}
+
+
diff --git a/sal/osl/all/loadmodulerelative.cxx b/sal/osl/all/loadmodulerelative.cxx
new file mode 100644
index 000000000000..39bea770e8a1
--- /dev/null
+++ b/sal/osl/all/loadmodulerelative.cxx
@@ -0,0 +1,71 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "sal/config.h"
+
+#include <cstddef>
+
+#include "osl/diagnose.h"
+#include "osl/module.h"
+#include "osl/module.hxx"
+#include "osl/thread.h"
+#include "rtl/malformeduriexception.hxx"
+#include "rtl/uri.hxx"
+#include "rtl/ustring.h"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+extern "C" {
+
+oslModule SAL_CALL osl_loadModuleRelative(
+ oslGenericFunction const baseModule, rtl_uString * const relativePath,
+ sal_Int32 const mode)
+{
+ ::rtl::OUString base;
+ if (!::osl::Module::getUrlFromAddress(baseModule, base)) {
+ OSL_TRACE("osl::Module::getUrlFromAddress failed");
+ return NULL;
+ }
+ ::rtl::OUString abs;
+ try {
+ abs = ::rtl::Uri::convertRelToAbs(base, relativePath);
+ } catch (::rtl::MalformedUriException & e) {
+ (void) e; // avoid warnings
+ OSL_TRACE(
+ "rtl::MalformedUriException <%s>",
+ rtl::OUStringToOString(e.getMessage(), osl_getThreadTextEncoding()).
+ getStr());
+ //TODO: let some OSL_TRACE variant take care of text conversion?
+ return NULL;
+ }
+ return ::osl_loadModule(abs.pData, mode);
+}
+
+}
diff --git a/sal/osl/all/makefile.mk b/sal/osl/all/makefile.mk
new file mode 100644
index 000000000000..0d105906effb
--- /dev/null
+++ b/sal/osl/all/makefile.mk
@@ -0,0 +1,76 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=sal
+TARGET=oslall
+ENABLE_EXCEPTIONS=TRUE
+USE_LDUMP2=TRUE
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=cont_pch
+PROJECTPCHSOURCE=cont_pch
+
+MULTITHREAD_OBJ=TRUE
+
+.IF "$(GUI)" == "OS2"
+STL_OS2_BUILDING=1
+.ENDIF
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+CFLAGS+= $(LFS_CFLAGS)
+CXXFLAGS+= $(LFS_CFLAGS)
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= \
+ $(SLO)$/utility.obj\
+ $(SLO)$/filepath.obj\
+ $(SLO)$/debugbase.obj\
+ $(SLO)$/loadmodulerelative.obj
+
+# $(SLO)$/readline.obj\
+
+#.IF "$(UPDATER)"=="YES"
+OBJFILES= \
+ $(OBJ)$/utility.obj\
+ $(OBJ)$/filepath.obj\
+ $(OBJ)$/debugbase.obj\
+ $(OBJ)$/loadmodulerelative.obj
+
+# $(OBJ)$/readline.obj\
+#.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+
diff --git a/sal/osl/all/utility.cxx b/sal/osl/all/utility.cxx
new file mode 100755
index 000000000000..21c392ba1793
--- /dev/null
+++ b/sal/osl/all/utility.cxx
@@ -0,0 +1,103 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+
+#include "rtl/ustring.hxx"
+#include "osl/time.h"
+#include <stdio.h>
+
+
+/*
+ * mfe : maybe it would be wishful to include initialization
+ * of the global timer in dllmain or _init directly.
+ * But noneoftheless this (should) work too.
+ */
+namespace osl
+{
+
+class OGlobalTimer
+{
+
+public:
+
+ OGlobalTimer() {
+ getTime();
+ }
+
+ sal_uInt32 getTime()
+ {
+ return osl_getGlobalTimer();
+ }
+
+
+};
+
+static OGlobalTimer aGlobalTimer;
+
+}
+
+
+extern "C"
+{
+void debug_ustring(rtl_uString* ustr)
+{
+ sal_Char* psz=0;
+ rtl_String* str=0;
+
+ if ( ustr != 0 )
+ {
+ rtl_uString2String( &str,
+ rtl_uString_getStr(ustr),
+ rtl_uString_getLength(ustr),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ psz = rtl_string_getStr(str);
+ }
+
+ fprintf(stderr,"'%s'\n",psz);
+
+ if ( str != 0 )
+ {
+ rtl_string_release(str);
+ }
+
+ return;
+}
+
+}
+
+void debug_oustring(rtl::OUString& ustr)
+{
+
+ debug_ustring(ustr.pData);
+
+ return;
+}
diff --git a/sal/osl/os2/conditn.c b/sal/osl/os2/conditn.c
new file mode 100644
index 000000000000..9ad2459fd851
--- /dev/null
+++ b/sal/osl/os2/conditn.c
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/conditn.h>
+#include <osl/diagnose.h>
+#include <osl/time.h>
+
+
+
+/*
+ under WIN32, we use the void* oslCondition
+ as a WIN32 HANDLE (which is also a 32-bit value)
+*/
+
+/*****************************************************************************/
+/* osl_createCondition */
+/*****************************************************************************/
+oslCondition SAL_CALL osl_createCondition()
+{
+ HEV hevCondition;
+ APIRET rc;
+
+ rc = DosCreateEventSem( NULL, /* unnamed semaphore */
+ &hevCondition, /* pointer to variable */
+ /* for the sem-handle */
+ DC_SEM_SHARED, /* shared semaphore */
+ FALSE ); /* initial state is posted */
+
+ if( rc == NO_ERROR )
+ return (oslCondition)hevCondition;
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_destroyCondition */
+/*****************************************************************************/
+void SAL_CALL osl_destroyCondition(oslCondition Condition)
+{
+ if( Condition )
+ DosCloseEventSem( (HEV) Condition );
+}
+
+/*****************************************************************************/
+/* osl_setCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setCondition(oslCondition Condition)
+{
+ OSL_ASSERT(Condition);
+
+ return DosPostEventSem((HEV)Condition) == NO_ERROR;
+}
+
+/*****************************************************************************/
+/* osl_resetCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_resetCondition(oslCondition Condition)
+{
+ ULONG ulPostCount;
+
+ OSL_ASSERT(Condition);
+
+ return DosResetEventSem((HEV)Condition, &ulPostCount) == NO_ERROR;
+}
+
+/*****************************************************************************/
+/* osl_waitCondition */
+/*****************************************************************************/
+oslConditionResult SAL_CALL osl_waitCondition(oslCondition Condition, const TimeValue * pTimeout )
+{
+ long nTimeout;
+ APIRET rc;
+ OSL_ASSERT(Condition);
+
+ if( pTimeout )
+ nTimeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000;
+ else
+ nTimeout = SEM_INDEFINITE_WAIT;
+
+ rc = DosWaitEventSem((HEV)Condition, nTimeout );
+ if( rc == ERROR_TIMEOUT )
+ return osl_cond_result_timeout;
+ if( rc != NO_ERROR )
+ return osl_cond_result_error;
+
+ return osl_cond_result_ok;
+}
+
+/*****************************************************************************/
+/* osl_checkCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_checkCondition(oslCondition Condition)
+{
+ OSL_ASSERT(Condition);
+
+ return( DosWaitEventSem((HEV)Condition, SEM_IMMEDIATE_RETURN) == NO_ERROR);
+}
+
diff --git a/sal/osl/os2/debug.c b/sal/osl/os2/debug.c
new file mode 100644
index 000000000000..f2d0f915f375
--- /dev/null
+++ b/sal/osl/os2/debug.c
@@ -0,0 +1,2152 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*
+ *@@sourcefile debug.c:
+ * this file contains debugging functions for the
+ * exception handlers in except.c.
+ *
+ * This code is capable of unwinding the stack from
+ * a given address and trying to get function names
+ * and source line numbers, either from the respective
+ * module's debug code (if present) or from a SYM file,
+ * which is searched for in the directory of the module
+ * or in ?:\OS2\PDPSI\PMDF\WARP4.
+ *
+ * This file incorporates code from the following:
+ * -- Marc Fiammante, John Currier, Kim Rasmussen,
+ * Anthony Cruise (EXCEPT3.ZIP package for a generic
+ * exception handling DLL, available at Hobbes).
+ *
+ * Usage: All OS/2 programs.
+ *
+ * Note: Version numbering in this file relates to XWorkplace version
+ * numbering.
+ *
+ *@@changed V0.9.0 [umoeller]: made some declarations C++-compatible
+ *@@changed V0.9.1 (2000-01-30) [umoeller]: greatly cleaned up this file
+ *
+ *@@header "helpers\debug.h"
+ */
+
+/*
+ * This file Copyright (C) 1992-99 Ulrich M�ller,
+ * Kim Rasmussen,
+ * Marc Fiammante,
+ * John Currier,
+ * Anthony Cruise.
+ * This file is part of the "XWorkplace helpers" source package.
+ *
+ * 2009-06-15 published under LGPL3 with Ulrich M�ller permission.
+ *
+ */
+
+//#define DEBUG_SYMDUMP // enable to dump sym file to log
+
+//YD commented, since we need unsigned char BYTE!
+//#define OS2EMX_PLAIN_CHAR
+//Also gcc char is signed, while most structures requires unsigned data!
+//Raised limits for all fields!
+
+ // this is needed for "os2emx.h"; if this is defined,
+ // emx will define PSZ as _signed_ char, otherwise
+ // as unsigned char
+
+#define INCL_DOSPROCESS
+#define INCL_DOSMODULEMGR
+#define INCL_DOSMISC
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define DONT_REPLACE_MALLOC
+#include "helpers\setup.h" // code generation and debugging options
+
+#include "helpers\debug.h"
+#include "helpers\dosh.h"
+
+#pragma hdrstop
+
+#include <fcntl.h>
+#ifdef __EMX__
+ #include <sys\types.h> // required for sys\stat.h; UM 99-10-22
+#endif
+#include <sys\stat.h>
+#include <share.h>
+#include <io.h>
+
+#ifndef DWORD
+#define DWORD unsigned long
+#endif
+#ifndef WORD
+#define WORD unsigned short
+#endif
+
+#pragma stack16(512)
+#define HF_STDERR 2
+
+/*
+ *@@category: Helpers\Control program helpers\Exceptions/debugging
+ * See except.c and debug.c.
+ */
+
+/* ******************************************************************
+ *
+ * Global variables
+ *
+ ********************************************************************/
+
+// this specifies whether we're dealing with 32-bit code;
+// this gets changed whenever 16-bit count is detected
+static BOOL f32bit = TRUE;
+
+/*
+ * Global variables for Read32PmDebug:
+ *
+ */
+
+ULONG func_ofs;
+ULONG pubfunc_ofs;
+//YD 17/07/06 c++ namespace can generate really long
+//YD names, use a large buffer!
+char func_name[16*1024];
+ULONG var_ofs = 0;
+
+struct {
+ BYTE name[128];
+ ULONG stack_offset;
+ USHORT type_idx;
+} autovar_def[1024];
+
+#pragma pack(1)
+
+BYTE *type_name[] =
+{
+ "8 bit signed ",
+ "16 bit signed ",
+ "32 bit signed ",
+ "Unknown (0x83) ",
+ "8 bit unsigned ",
+ "16 bit unsigned ",
+ "32 bit unsigned ",
+ "Unknown (0x87) ",
+ "32 bit real ",
+ "64 bit real ",
+ "80 bit real ",
+ "Unknown (0x8B) ",
+ "64 bit complex ",
+ "128 bit complex ",
+ "160 bit complex ",
+ "Unknown (0x8F) ",
+ "8 bit boolean ",
+ "16 bit boolean ",
+ "32 bit boolean ",
+ "Unknown (0x93) ",
+ "8 bit character ",
+ "16 bit characters ",
+ "32 bit characters ",
+ "void ",
+ "15 bit unsigned ",
+ "24 bit unsigned ",
+ "31 bit unsigned ",
+ "Unknown (0x9B) ",
+ "Unknown (0x9C) ",
+ "Unknown (0x9D) ",
+ "Unknown (0x9E) ",
+ "Unknown (0x9F) ",
+ "near pointer to 8 bit signed ",
+ "near pointer to 16 bit signed ",
+ "near pointer to 32 bit signed ",
+ "Unknown (0xA3) ",
+ "near pointer to 8 bit unsigned ",
+ "near pointer to 16 bit unsigned ",
+ "near pointer to 32 bit unsigned ",
+ "Unknown (0xA7) ",
+ "near pointer to 32 bit real ",
+ "near pointer to 64 bit real ",
+ "near pointer to 80 bit real ",
+ "Unknown (0xAB) ",
+ "near pointer to 64 bit complex ",
+ "near pointer to 128 bit complex ",
+ "near pointer to 160 bit complex ",
+ "Unknown (0xAF) ",
+ "near pointer to 8 bit boolean ",
+ "near pointer to 16 bit boolean ",
+ "near pointer to 32 bit boolean ",
+ "Unknown (0xB3) ",
+ "near pointer to 8 bit character ",
+ "near pointer to 16 bit characters",
+ "near pointer to 32 bit characters",
+ "near pointer to void ",
+ "near pointer to 15 bit unsigned ",
+ "near pointer to 24 bit unsigned ",
+ "near pointer to 31 bit unsigned ",
+ "Unknown (0xBB) ",
+ "Unknown (0xBC) ",
+ "Unknown (0xBD) ",
+ "Unknown (0xBE) ",
+ "Unknown (0xBF) ",
+ "far pointer to 8 bit signed ",
+ "far pointer to 16 bit signed ",
+ "far pointer to 32 bit signed ",
+ "Unknown (0xC3) ",
+ "far pointer to 8 bit unsigned ",
+ "far pointer to 16 bit unsigned ",
+ "far pointer to 32 bit unsigned ",
+ "Unknown (0xC7) ",
+ "far pointer to 32 bit real ",
+ "far pointer to 64 bit real ",
+ "far pointer to 80 bit real ",
+ "Unknown (0xCB) ",
+ "far pointer to 64 bit complex ",
+ "far pointer to 128 bit complex ",
+ "far pointer to 160 bit complex ",
+ "Unknown (0xCF) ",
+ "far pointer to 8 bit boolean ",
+ "far pointer to 16 bit boolean ",
+ "far pointer to 32 bit boolean ",
+ "Unknown (0xD3) ",
+ "far pointer to 8 bit character ",
+ "far pointer to 16 bit characters ",
+ "far pointer to 32 bit characters ",
+ "far pointer to void ",
+ "far pointer to 15 bit unsigned ",
+ "far pointer to 24 bit unsigned ",
+ "far pointer to 31 bit unsigned ",
+};
+
+// Thanks to John Currier:
+// Do not call 16 bit code in myHandler function to prevent call
+// to __EDCThunkProlog and problems is guard page exception handling
+// Also reduce the stack size to 1K for true 16 bit calls.
+// 16 bit calls thunk will now only occur on fatal exceptions
+#pragma stack16(1024)
+
+// ------------------------------------------------------------------
+// Last 8 bytes of 16:16 file when CODEVIEW debugging info is present
+#pragma pack(1)
+struct _eodbug
+{
+ unsigned short dbug; // 'NB' signature
+ unsigned short ver; // version
+ unsigned long dfaBase; // size of codeview info
+} G_eodbug;
+
+#define DBUGSIG 0x424E
+#define SSTMODULES 0x0101
+#define SSTPUBLICS 0x0102
+#define SSTTYPES 0x0103
+#define SSTSYMBOLS 0x0104
+#define SSTSRCLINES 0x0105
+#define SSTLIBRARIES 0x0106
+#define SSTSRCLINES2 0x0109
+#define SSTSRCLINES32 0x010B
+
+typedef struct _SYMBASE
+{
+ unsigned short dbug; // 'NB' signature
+ unsigned short ver; // version
+ unsigned long lfoDir; // file offset to dir entries
+} SYMBASE;
+
+typedef struct _SSDIR
+{
+ unsigned short sst; // SubSection Type
+ unsigned short modindex; // Module index number
+ unsigned long lfoStart; // Start of section
+ unsigned short cb; // Size of section
+} SSDIR;
+
+typedef struct _SSDIR32
+{
+ unsigned short sst; // SubSection Type
+ unsigned short modindex; // Module index number
+ unsigned long lfoStart; // Start of section
+ unsigned long cb; // Size of section
+} SSDIR32;
+
+typedef struct _SSMODULE
+{
+ unsigned short csBase; // code segment base
+ unsigned short csOff; // code segment offset
+ unsigned short csLen; // code segment length
+ unsigned short ovrNum; // overlay number
+ unsigned short indxSS; // Index into sstLib or 0
+ unsigned short reserved;
+ BYTE csize; // size of prefix string
+} SSMODULE;
+
+typedef struct _SSMOD32
+{
+ unsigned short csBase; // code segment base
+ unsigned long csOff; // code segment offset
+ unsigned long csLen; // code segment length
+ unsigned long ovrNum; // overlay number
+ unsigned short indxSS; // Index into sstLib or 0
+ unsigned long reserved;
+ BYTE csize; // size of prefix string
+} SSMOD32;
+
+typedef struct _SSPUBLIC
+{
+ unsigned short offset;
+ unsigned short segment;
+ unsigned short type;
+ BYTE csize;
+} SSPUBLIC;
+
+typedef struct _SSPUBLIC32
+{
+ unsigned long offset;
+ unsigned short segment;
+ unsigned short type;
+ BYTE csize;
+} SSPUBLIC32;
+
+typedef struct _SSLINEENTRY32
+{
+ unsigned short LineNum;
+ unsigned short FileNum;
+ unsigned long Offset;
+} SSLINEENTRY32;
+
+typedef struct _FIRSTLINEENTRY32
+{
+ unsigned short LineNum;
+ unsigned char entry_type;
+ unsigned char reserved;
+ unsigned short numlines;
+ unsigned short segnum;
+} FIRSTLINEENTRY32;
+
+typedef struct _SSFILENUM32
+{
+ unsigned long first_displayable; // Not used
+ unsigned long number_displayable; // Not used
+ unsigned long file_count; // number of source files
+} SSFILENUM32;
+
+/*
+ *@@ XDEBUGINFO:
+ * buffers for Read... funcs.
+ *
+ *@@added V0.9.4 (2000-06-15) [umoeller]
+ */
+
+typedef struct _XDEBUGINFO
+{
+ char szNrFile[300]; // receives source file
+ char szNrLine[300]; // receives line number
+ //YD 17/07/06 c++ namespace can generate really long
+ //YD names, use a large buffer!
+ char szNrPub[16*1024]; // receives function name
+
+ struct new_seg *pseg;
+ struct o32_obj *pobj; // flat .EXE object table entry
+
+ SYMBASE base;
+
+ SSDIR *pDirTab;
+ SSDIR32 *pDirTab32;
+ unsigned char *pEntTab;
+ unsigned long lfaBase;
+ SSMOD32 ssmod32;
+ SSPUBLIC32 sspub32;
+
+ SSMODULE ssmod;
+ SSPUBLIC sspub;
+} XDEBUGINFO, *PXDEBUGINFO;
+
+
+USHORT _THUNK_FUNCTION (Dos16SizeSeg) ();
+//APIRET16 APIENTRY16 DOS16SIZESEG(USHORT Seg, PULONG16 Size);
+USHORT DosSizeSeg (USHORT Seg, PULONG16 Size)
+{
+ return ((USHORT)
+ (_THUNK_PROLOG (2+4);
+ _THUNK_SHORT (Seg);
+ _THUNK_FLAT (Size);
+ _THUNK_CALL (Dos16SizeSeg)));
+}
+
+#pragma pack()
+
+/* ******************************************************************
+ *
+ * PART 1: ANALYZE DEBUG CODE
+ *
+ ********************************************************************/
+
+static int Read16CodeView(FILE *LogFile, PXDEBUGINFO pxdi, int fh, int TrapSeg, int TrapOff, CHAR *FileName);
+static int Read32PmDebug(FILE *LogFile, PXDEBUGINFO pxdi, int fh, int TrapSeg, int TrapOff, CHAR *FileName);
+
+/*
+ *@@ WriteAddressInfo:
+ * formats and writes a line into the trap log
+ * file.
+ *
+ * This gets called for each line from the
+ * stack dump. At this point, the line in the
+ * trap log already has:
+ *
+ + CS:EIP : 000109FF XMLVIEW :0
+ + ^^^ and we write here
+ * After this call, we have.
+ *
+ + CS:EIP : 000109FF XMLVIEW :0 xxx.c 123 ConfirmCreate__Fv
+ + ^^^ and we write here
+ *
+ *@@added V0.9.12 (2001-05-12) [umoeller]
+ */
+
+static VOID WriteDebugInfo(FILE *LogFile, // in: open log file
+ PXDEBUGINFO pxdi) // in: debug info
+{
+ fprintf(LogFile,
+ "%s%s%s",
+ pxdi->szNrFile,
+ pxdi->szNrLine,
+ pxdi->szNrPub);
+}
+
+/*
+ *@@ dbgPrintDebugInfo:
+ * this is the main entry point into analyzing debug
+ * code.
+ *
+ * This analyzes a given address and tries to find
+ * debug code descriptions for this address. If found,
+ * the information is written to the given log file.
+ *
+ * Gets called from dbgPrintStack.
+ *
+ * This returns NO_ERROR if the could was successfully
+ * analyzed or something != 0 if we failed.
+ *
+ * New with V0.84.
+ */
+
+APIRET dbgPrintDebugInfo(FILE *LogFile, // out: log file to write to
+ CHAR *FileName, // in: EXE/DLL module file name
+ ULONG Object, // in: trapping object (from DosQueryModFromEIP)
+ ULONG TrapOffset) // in: trapping address (from DosQueryModFromEIP)
+{
+ APIRET rc = 0;
+ int ModuleFile = 0;
+ static struct exe_hdr OldExeHeader;
+ static struct new_exe NewExeHeader;
+
+ ULONG ulSegment = Object + 1; // segment no. is object no. + 1
+
+ XDEBUGINFO xdi;
+ memset(&xdi, 0, sizeof(xdi));
+
+ // open the module file for reading to analyze the code
+ ModuleFile = sopen(FileName, O_RDONLY | O_BINARY, SH_DENYNO);
+
+ if (ModuleFile != -1)
+ {
+ // file found:
+ // read old Exe header
+ if (read(ModuleFile, (void*)&OldExeHeader, 64) == -1L)
+ {
+ fprintf(LogFile, "errno %d reading old exe header\n", errno);
+ close(ModuleFile);
+ return 2;
+ }
+ // seek to new Exe header
+ if (lseek(ModuleFile, (long)E_LFANEW(OldExeHeader), SEEK_SET) == -1L)
+ {
+ fprintf(LogFile, "errno %d seeking to new exe header\n", errno);
+ close(ModuleFile);
+ return 3;
+ }
+ if (read(ModuleFile, (void *)&NewExeHeader, 64) == -1L)
+ {
+ fprintf(LogFile, "errno %d reading new exe header\n", errno);
+ close(ModuleFile);
+ return 4;
+ }
+
+ // check EXE signature
+ if (NE_MAGIC(NewExeHeader) == E32MAGIC)
+ {
+ /*
+ * flat 32 executable:
+ *
+ */
+
+ // do analysis for 32-bit code
+ if (!(rc = Read32PmDebug(LogFile,
+ &xdi, // output
+ ModuleFile,
+ ulSegment,
+ TrapOffset,
+ FileName)))
+ WriteDebugInfo(LogFile, &xdi);
+
+ close(ModuleFile);
+
+ // rc !=0 try with DBG file
+ if (rc != 0)
+ {
+ strcpy(FileName + strlen(FileName) - 3, "DBG"); // Build DBG File name
+ ModuleFile = sopen(FileName, O_RDONLY | O_BINARY, SH_DENYNO);
+ if (ModuleFile != -1)
+ {
+ if (!(rc = Read32PmDebug(LogFile,
+ &xdi,
+ ModuleFile,
+ ulSegment,
+ TrapOffset,
+ FileName)))
+ WriteDebugInfo(LogFile, &xdi);
+
+ close(ModuleFile);
+ }
+ }
+
+ return rc;
+ }
+ else
+ {
+ if (NE_MAGIC(NewExeHeader) == NEMAGIC)
+ {
+ /*
+ * 16:16 executable:
+ *
+ */
+
+ if ((xdi.pseg = (struct new_seg *)calloc(NE_CSEG(NewExeHeader),
+ sizeof(struct new_seg)))
+ == NULL)
+ {
+ fprintf(LogFile, "Out of memory!");
+ close(ModuleFile);
+ return -1;
+ }
+ if ( lseek(ModuleFile,
+ E_LFANEW(OldExeHeader) + NE_SEGTAB(NewExeHeader),
+ SEEK_SET) == -1L)
+ {
+ fprintf(LogFile, "Error %u seeking segment table in %s\n", errno, FileName);
+ free(xdi.pseg);
+ close(ModuleFile);
+ return 9;
+ }
+
+ if (read(ModuleFile,
+ (void *)xdi.pseg,
+ NE_CSEG(NewExeHeader) * sizeof(struct new_seg))
+ == -1)
+ {
+ fprintf(LogFile, "Error %u reading segment table from %s\n", errno, FileName);
+ free(xdi.pseg);
+ close(ModuleFile);
+ return 10;
+ }
+
+ if (!(rc = Read16CodeView(LogFile,
+ &xdi,
+ ModuleFile,
+ ulSegment,
+ TrapOffset,
+ FileName)))
+ WriteDebugInfo(LogFile, &xdi);
+
+ free(xdi.pseg);
+ close(ModuleFile);
+
+ // rc !=0 try with DBG file
+ if (rc != 0)
+ {
+ strcpy(FileName + strlen(FileName) - 3, "DBG"); // Build DBG File name
+ ModuleFile = sopen(FileName,
+ O_RDONLY | O_BINARY, SH_DENYNO);
+ if (ModuleFile != -1)
+ {
+ if (!(rc = Read16CodeView(LogFile,
+ &xdi,
+ ModuleFile,
+ ulSegment,
+ TrapOffset,
+ FileName)))
+ WriteDebugInfo(LogFile, &xdi);
+
+ close(ModuleFile);
+ }
+ }
+ return rc;
+ }
+ else
+ {
+ /*
+ * Unknown executable:
+ *
+ */
+
+ fprintf(LogFile, "Error, could not find exe signature");
+ close(ModuleFile);
+ return 11;
+ }
+ }
+ } // end if (ModuleFile != -1)
+ else
+ {
+ fprintf(LogFile, "Error %d opening module file %s", errno, FileName);
+ return 1;
+ } // endif
+
+ // return 0; we never get here
+}
+
+char fname[256],
+ ModName[80];
+char ename[256],
+ dummy[256];
+
+#define MAX_USERDEFS 300 // raised from 150 V0.9.1 (2000-01-30) [umoeller]
+#define MAX_POINTERS 300 // raised from 150 V0.9.1 (2000-01-30) [umoeller]
+
+USHORT userdef_count;
+USHORT pointer_count;
+
+struct one_userdef_rec
+{
+ USHORT idx;
+ USHORT type_index;
+ BYTE name[33];
+} one_userdef[MAX_USERDEFS];
+
+struct one_pointer_rec
+{
+ USHORT idx;
+ USHORT type_index;
+ BYTE type_qual;
+ BYTE name[33];
+} one_pointer[MAX_POINTERS];
+
+/*
+ * Read32PmDebug:
+ * parses 32-bit debug code.
+ * Called from dbgPrintDebugInfo for 32-bit modules.
+ */
+
+static int Read32PmDebug(FILE *LogFile, // in: text log file to write to
+ PXDEBUGINFO pxdi,
+ int ModuleFile, // in: module file opened with sopen()
+ int TrapSeg,
+ int TrapOff,
+ CHAR *FileName)
+{
+ static unsigned int CurrSymSeg, NrSymbol,
+ /* offset, */ NrPublic,
+ NrFile, NrLine, /* NrEntry */
+ numdir, namelen,
+ numlines /* , line */;
+ static int ModIndex;
+ static int bytesread, i, j;
+ static SSLINEENTRY32 LineEntry;
+ static SSFILENUM32 FileInfo;
+ static FIRSTLINEENTRY32 FirstLine;
+ static BYTE dump_vars = FALSE;
+ static USHORT idx;
+ static BOOL read_types;
+ static LONG lSize;
+
+ ModIndex = 0;
+ // See if any CODEVIEW info
+ if (lseek(ModuleFile, -8L, SEEK_END) == -1)
+ {
+ fprintf(LogFile, "Error %u seeking CodeView table in %s\n", errno, FileName);
+ return (18);
+ }
+
+ if (read(ModuleFile,
+ (void *)&G_eodbug, 8)
+ == -1)
+ {
+ fprintf(LogFile, "Error %u reading debug info from %s\n", errno, FileName);
+ return (19);
+ }
+ if (G_eodbug.dbug != DBUGSIG)
+ {
+ // fprintf(LogFile,"\nNo CodeView information stored.\n");
+ return (100);
+ }
+
+ if ( (pxdi->lfaBase = lseek(ModuleFile,
+ -(LONG)G_eodbug.dfaBase,
+ SEEK_END))
+ == -1L)
+ {
+ fprintf(LogFile, "Error %u seeking base codeview data in %s\n", errno, FileName);
+ return (20);
+ }
+
+ if (read(ModuleFile,
+ (void *)&pxdi->base, 8)
+ == -1)
+ {
+ fprintf(LogFile, "Error %u reading base codeview data in %s\n", errno, FileName);
+ return (21);
+ }
+
+ if (lseek(ModuleFile,
+ pxdi->base.lfoDir - 8 + 4,
+ SEEK_CUR)
+ == -1)
+ {
+ fprintf(LogFile, "Error %u seeking dir codeview data in %s\n", errno, FileName);
+ return (22);
+ }
+
+ if (read(ModuleFile,
+ (void *)&numdir, 4)
+ == -1)
+ {
+ fprintf(LogFile, "Error %u reading dir codeview data in %s\n", errno, FileName);
+ return (23);
+ }
+
+ // Read dir table into buffer
+ if ( (pxdi->pDirTab32 = (SSDIR32*)calloc(numdir,
+ sizeof(SSDIR32)))
+ == NULL)
+ {
+ fprintf(LogFile, "Out of memory!");
+ return (-1);
+ }
+
+ if (read(ModuleFile,
+ (void*)pxdi->pDirTab32,
+ numdir * sizeof(SSDIR32))
+ == -1)
+ {
+ fprintf(LogFile, "Error %u reading codeview dir table from %s\n", errno, FileName);
+ free(pxdi->pDirTab32);
+ return (24);
+ }
+
+ i = 0;
+ while (i < numdir)
+ {
+ if (pxdi->pDirTab32[i].sst != SSTMODULES)
+ {
+ i++;
+ continue;
+ }
+
+ NrPublic = 0x0;
+ NrSymbol = 0;
+ NrLine = 0x0;
+ NrFile = 0x0;
+ CurrSymSeg = 0;
+ // point to subsection
+ lseek(ModuleFile,
+ pxdi->pDirTab32[i].lfoStart + pxdi->lfaBase,
+ SEEK_SET);
+ read(ModuleFile,
+ (void*)&pxdi->ssmod32.csBase,
+ sizeof(SSMOD32));
+ read(ModuleFile,
+ (void*)ModName,
+ (unsigned)pxdi->ssmod32.csize);
+ ModIndex = pxdi->pDirTab32[i].modindex;
+ ModName[pxdi->ssmod32.csize] = '\0';
+ i++;
+
+ read_types = FALSE;
+
+ while ( (pxdi->pDirTab32[i].modindex == ModIndex)
+ && (i < numdir)
+ )
+ {
+ // point to subsection
+ lseek(ModuleFile,
+ pxdi->pDirTab32[i].lfoStart + pxdi->lfaBase,
+ SEEK_SET);
+
+ switch (pxdi->pDirTab32[i].sst)
+ {
+ case SSTPUBLICS:
+ bytesread = 0;
+ while (bytesread < pxdi->pDirTab32[i].cb)
+ {
+ bytesread += read(ModuleFile,
+ (void *)&pxdi->sspub32.offset,
+ sizeof(pxdi->sspub32));
+ bytesread += read(ModuleFile,
+ (void*)ename,
+ (unsigned)pxdi->sspub32.csize);
+ ename[pxdi->sspub32.csize] = '\0';
+ if ( (pxdi->sspub32.segment == TrapSeg)
+ && (pxdi->sspub32.offset <= TrapOff)
+ && (pxdi->sspub32.offset >= NrPublic)
+ )
+ {
+ NrPublic = pubfunc_ofs = pxdi->sspub32.offset;
+ read_types = TRUE;
+ sprintf(pxdi->szNrPub,
+ "%s %s (%s)\n",
+ (pxdi->sspub32.type == 1)
+ ? " Abs"
+ : " ",
+ ename,
+ ModName
+ );
+ // but continue, because there might be a
+ // symbol that comes closer
+ }
+ }
+ break;
+
+ // Read symbols, so we can dump the variables on the stack
+ case SSTSYMBOLS:
+ if (TrapSeg != pxdi->ssmod32.csBase)
+ break;
+
+ bytesread = 0;
+ while (bytesread < pxdi->pDirTab32[i].cb)
+ {
+ static USHORT usLength;
+ static USHORT usLengthSym;
+ static BYTE b1,
+ b2;
+ static BYTE bType;
+ // *ptr;
+ static ULONG ofs;
+ // static ULONG last_addr = 0;
+ //YD 17/07/06 c++ namespace can generate really long
+ //YD names, use a large buffer!
+ static BYTE str[16*1024];
+ static struct symseg_rec symseg;
+ static struct symauto_rec symauto;
+ static struct symproc_rec symproc;
+
+ // Read the length of this subentry
+ bytesread += read(ModuleFile, &b1, 1);
+ if (b1 & 0x80)
+ {
+ bytesread += read(ModuleFile, &b2, 1);
+ usLength = ((b1 & 0x7F) << 8) + b2;
+ }
+ else
+ usLength = b1;
+
+ ofs = tell(ModuleFile);
+
+ bytesread += read(ModuleFile, &bType, 1);
+
+ switch (bType)
+ {
+ case SYM_CHANGESEG:
+ read(ModuleFile, &symseg, sizeof(symseg));
+ CurrSymSeg = symseg.seg_no;
+ break;
+
+ case SYM_PROC:
+ case SYM_CPPPROC:
+ read(ModuleFile, &symproc, sizeof(symproc));
+ if (symproc.name_len & 0x80)
+ {
+ read(ModuleFile, &b2, 1);
+ usLengthSym = ((symproc.name_len & 0x7F) << 8) + b2;
+ }
+ else
+ {
+ usLengthSym = symproc.name_len;
+ }
+ read(ModuleFile, str, usLengthSym);
+ str[usLengthSym] = 0;
+
+ if ((CurrSymSeg == TrapSeg) &&
+ (symproc.offset <= TrapOff) &&
+ (symproc.offset >= NrSymbol))
+ {
+
+ dump_vars = TRUE;
+ var_ofs = 0;
+ NrSymbol = symproc.offset;
+ func_ofs = symproc.offset;
+
+ strcpy(func_name, str);
+ }
+ else
+ {
+ dump_vars = FALSE;
+ }
+ break;
+
+ case SYM_AUTO:
+ if (!dump_vars)
+ break;
+
+ read(ModuleFile, &symauto, sizeof(symauto));
+ read(ModuleFile, str, symauto.name_len);
+ if (symauto.name_len==0x80)
+ printf("symauto.name_len==0x80\n");
+ str[symauto.name_len] = 0;
+
+ strcpy(autovar_def[var_ofs].name, str);
+ autovar_def[var_ofs].stack_offset = symauto.stack_offset;
+ autovar_def[var_ofs].type_idx = symauto.type_idx;
+ var_ofs++;
+ break;
+
+ }
+
+ bytesread += usLength;
+
+ lseek(ModuleFile, ofs + usLength, SEEK_SET);
+ }
+ break;
+
+ case SSTTYPES:
+ // if (ModIndex != TrapSeg)
+ if (!read_types)
+ break;
+
+ bytesread = 0;
+ idx = 0x200;
+ userdef_count = 0;
+ pointer_count = 0;
+ while (bytesread < pxdi->pDirTab32[i].cb)
+ {
+ static struct type_rec type;
+ static struct type_userdefrec udef;
+ static struct type_pointerrec point;
+ static ULONG ofs;
+ static BYTE str[256];
+
+ // Read the length of this subentry
+ ofs = tell(ModuleFile);
+
+ read(ModuleFile, &type, sizeof(type));
+ bytesread += sizeof(type);
+
+ switch (type.type)
+ {
+ case TYPE_USERDEF:
+ if (userdef_count >= MAX_USERDEFS)
+ break;
+
+ read(ModuleFile, &udef, sizeof(udef));
+ read(ModuleFile, str, udef.name_len);
+ str[udef.name_len] = 0;
+
+ // Insert userdef in table
+ one_userdef[userdef_count].idx = idx;
+ one_userdef[userdef_count].type_index = udef.type_index;
+ memcpy(one_userdef[userdef_count].name,
+ str,
+ _min(udef.name_len + 1, 32));
+ one_userdef[userdef_count].name[32] = 0;
+ userdef_count++;
+ break;
+
+ case TYPE_POINTER:
+ if (pointer_count >= MAX_POINTERS)
+ break;
+
+ read(ModuleFile, &point, sizeof(point));
+ read(ModuleFile, str, point.name_len);
+ str[point.name_len] = 0;
+
+ // Insert userdef in table
+ one_pointer[pointer_count].idx = idx;
+ one_pointer[pointer_count].type_index = point.type_index;
+ memcpy(one_pointer[pointer_count].name,
+ str,
+ _min(point.name_len + 1, 32));
+ one_pointer[pointer_count].name[32] = 0;
+ one_pointer[pointer_count].type_qual = type.type_qual;
+ pointer_count++;
+ break;
+ }
+
+ ++idx;
+
+ bytesread += type.length;
+
+ lseek(ModuleFile, ofs + type.length + 2, SEEK_SET);
+ }
+ break;
+
+ case SSTSRCLINES32:
+ if (TrapSeg != pxdi->ssmod32.csBase)
+ break;
+
+ // read first line
+ do
+ {
+ read(ModuleFile, (void *)&FirstLine, sizeof(FirstLine));
+
+ if (FirstLine.LineNum != 0)
+ {
+ fprintf(LogFile, "Missing Line table information\n");
+ break;
+ } // endif
+ numlines = FirstLine.numlines;
+ // Other type of data skip 4 more bytes
+ if (FirstLine.entry_type < 4)
+ {
+ read(ModuleFile, (void *)&lSize, 4);
+ if (FirstLine.entry_type == 3)
+ lseek(ModuleFile, lSize, SEEK_CUR);
+ }
+ }
+ while (FirstLine.entry_type == 3);
+
+ for (j = 0; j < numlines; j++)
+ {
+ switch (FirstLine.entry_type)
+ {
+ case 0:
+ read(ModuleFile, (void *)&LineEntry, sizeof(LineEntry));
+ // Changed by Kim Rasmussen 26/06 1996 to ignore linenumber 0
+ // if (LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) {
+ if ( (LineEntry.LineNum)
+ && (LineEntry.Offset + pxdi->ssmod32.csOff
+ <= TrapOff)
+ && (LineEntry.Offset + pxdi->ssmod32.csOff >= NrLine)
+ )
+ {
+ NrLine = LineEntry.Offset;
+ NrFile = LineEntry.FileNum;
+ /*pOffset =sprintf(szNrLine,"%04X:%08X line #%hu ",
+ * ssmod32.csBase,LineEntry.Offset,
+ * LineEntry.LineNum); */
+ sprintf(pxdi->szNrLine, "% 6hu", LineEntry.LineNum);
+ }
+ break;
+
+ case 1:
+ lseek(ModuleFile, sizeof(struct linlist_rec), SEEK_CUR);
+ break;
+
+ case 2:
+ lseek(ModuleFile, sizeof(struct linsourcelist_rec), SEEK_CUR);
+ break;
+
+ case 3:
+ lseek(ModuleFile, sizeof(struct filenam_rec), SEEK_CUR);
+ break;
+
+ case 4:
+ lseek(ModuleFile, sizeof(struct pathtab_rec), SEEK_CUR);
+ break;
+
+ }
+ }
+
+ if (NrFile != 0)
+ {
+ // file found:
+ read(ModuleFile, (void*)&FileInfo, sizeof(FileInfo));
+ namelen = 0;
+ for (j = 1; j <= FileInfo.file_count; j++)
+ {
+ namelen = 0;
+ read(ModuleFile, (void *)&namelen, 1);
+ read(ModuleFile, (void *)ename, namelen);
+ if (j == NrFile)
+ break;
+ }
+ ename[namelen] = '\0';
+ // pOffset=sprintf(szNrLine+pOffset," (%s) (%s)\n",ename,ModName);
+ sprintf(pxdi->szNrFile, "%11.11s ", ename);
+ }
+ else
+ {
+ // strcat(szNrLine,"\n"); avoid new line for empty name fill
+ strcpy(pxdi->szNrFile, "file? ");
+ } // endif
+ break;
+ } // end switch
+
+ i++;
+ } // end while modindex
+ } // End While i < numdir
+ free(pxdi->pDirTab32);
+ return (0);
+}
+
+/*
+ * Read16CodeView:
+ * parses 16-bit debug code.
+ * Called from dbgPrintDebugInfo for 16-bit modules.
+ */
+
+static int Read16CodeView(FILE *LogFile, // in: text log file to write to
+ PXDEBUGINFO pxdi,
+ int fh,
+ int TrapSeg,
+ int TrapOff,
+ CHAR *FileName)
+{
+ static unsigned short int offset,
+ NrPublic, NrLine,
+ numdir,
+ namelen, numlines,
+ line;
+ static int ModIndex;
+ static int bytesread, i, j;
+
+ ModIndex = 0;
+ // See if any CODEVIEW info
+ if (lseek(fh, -8L, SEEK_END) == -1)
+ {
+ fprintf(LogFile, "Error %u seeking CodeView table in %s\n", errno, FileName);
+ return (18);
+ }
+
+ if (read(fh, (void *)&G_eodbug, 8) == -1)
+ {
+ fprintf(LogFile, "Error %u reading debug info from %s\n", errno, FileName);
+ return (19);
+ }
+ if (G_eodbug.dbug != DBUGSIG)
+ {
+ // fprintf(LogFile,"\nNo CodeView information stored.\n");
+ return (100);
+ }
+
+ if ((pxdi->lfaBase = lseek(fh, -(LONG)G_eodbug.dfaBase, SEEK_END)) == -1L)
+ {
+ fprintf(LogFile, "Error %u seeking base codeview data in %s\n", errno, FileName);
+ return (20);
+ }
+
+ if (read(fh, (void *)&pxdi->base, 8) == -1)
+ {
+ fprintf(LogFile, "Error %u reading base codeview data in %s\n", errno, FileName);
+ return (21);
+ }
+
+ if (lseek(fh, pxdi->base.lfoDir - 8, SEEK_CUR) == -1)
+ {
+ fprintf(LogFile, "Error %u seeking dir codeview data in %s\n", errno, FileName);
+ return (22);
+ }
+
+ if (read(fh, (void *)&numdir, 2) == -1)
+ {
+ fprintf(LogFile, "Error %u reading dir codeview data in %s\n", errno, FileName);
+ return (23);
+ }
+
+ // Read dir table into buffer
+ if ((pxdi->pDirTab = (SSDIR*)calloc(numdir, sizeof(SSDIR))) == NULL)
+ {
+ fprintf(LogFile, "Out of memory!");
+ return (-1);
+ }
+
+ if (read(fh, (void*)pxdi->pDirTab, numdir * sizeof(SSDIR)) == -1)
+ {
+ fprintf(LogFile, "Error %u reading codeview dir table from %s\n", errno, FileName);
+ free(pxdi->pDirTab);
+ return (24);
+ }
+
+ i = 0;
+ while (i < numdir)
+ {
+ if (pxdi->pDirTab[i].sst != SSTMODULES)
+ {
+ i++;
+ continue;
+ }
+ NrPublic = 0x0;
+ NrLine = 0x0;
+ // point to subsection
+ lseek(fh, pxdi->pDirTab[i].lfoStart + pxdi->lfaBase, SEEK_SET);
+ read(fh, (void *)&pxdi->ssmod.csBase, sizeof(SSMODULE));
+ read(fh, (void *)ModName, (unsigned)pxdi->ssmod.csize);
+ ModIndex = pxdi->pDirTab[i].modindex;
+ ModName[pxdi->ssmod.csize] = '\0';
+ i++;
+ while (pxdi->pDirTab[i].modindex == ModIndex && i < numdir)
+ {
+ // point to subsection
+ lseek(fh, pxdi->pDirTab[i].lfoStart + pxdi->lfaBase, SEEK_SET);
+ switch (pxdi->pDirTab[i].sst)
+ {
+ case SSTPUBLICS:
+ bytesread = 0;
+ while (bytesread < pxdi->pDirTab[i].cb)
+ {
+ bytesread += read(fh, (void *)&pxdi->sspub.offset, sizeof(pxdi->sspub));
+ bytesread += read(fh, (void *)ename, (unsigned)pxdi->sspub.csize);
+ ename[pxdi->sspub.csize] = '\0';
+ if ((pxdi->sspub.segment == TrapSeg) &&
+ (pxdi->sspub.offset <= TrapOff) &&
+ (pxdi->sspub.offset >= NrPublic))
+ {
+ NrPublic = pxdi->sspub.offset;
+ sprintf(pxdi->szNrPub, "%s %s (%s) %04hX:%04hX\n",
+ (pxdi->sspub.type == 1) ? " Abs" : " ", ename,
+ ModName, // ()
+ pxdi->sspub.segment,
+ pxdi->sspub.offset
+ );
+ }
+ }
+ break;
+
+ case SSTSRCLINES2:
+ case SSTSRCLINES:
+ if (TrapSeg != pxdi->ssmod.csBase)
+ break;
+ namelen = 0;
+ read(fh, (void *)&namelen, 1);
+ read(fh, (void *)ename, namelen);
+ ename[namelen] = '\0';
+ // skip 2 zero bytes
+ if (pxdi->pDirTab[i].sst == SSTSRCLINES2)
+ read(fh, (void *)&numlines, 2);
+ read(fh, (void *)&numlines, 2);
+ for (j = 0; j < numlines; j++)
+ {
+ read(fh, (void *)&line, 2);
+ read(fh, (void *)&offset, 2);
+ if (offset <= TrapOff && offset >= NrLine)
+ {
+ NrLine = offset;
+ sprintf(pxdi->szNrFile, "% 12.12s ", ename);
+ sprintf(pxdi->szNrLine, "% 6hu", line);
+ /*sprintf(szNrLine,"%04hX:%04hX line #%hu (%s) (%s)\n",
+ * ssmod.csBase,offset,line,ModName,ename); */
+ }
+ }
+ break;
+ } // end switch
+ i++;
+ } // end while modindex
+ } // End While i < numdir
+ free(pxdi->pDirTab);
+ return (0);
+}
+
+/* ******************************************************************
+ *
+ * PART 2: ANALYZE VARIABLES
+ *
+ ********************************************************************/
+
+/*
+ * var_value:
+ * writes a description of a variable type to
+ * the specified buffer, depending on "type".
+ *
+ *@@changed V0.9.1 (2000-01-30) [umoeller]: changed prototype to use external buffer
+ */
+
+static VOID var_value(void *varptr, // in: address of the variable on the stack
+ char *pszBuf, // out: information
+ BYTE type) // in: type; if >= 32, we'll call DosQueryMem
+{
+ ULONG Size = 1,
+ Attr = 0;
+
+ if (DosQueryMem(varptr, &Size, &Attr) != NO_ERROR)
+ {
+ sprintf(pszBuf, "type %d, DosQueryMem failed", type);
+ return;
+ }
+
+ if ((Attr & PAG_READ) == 0)
+ {
+ sprintf(pszBuf, "type %d, read-access to value denied", type);
+ return;
+ }
+
+ if (type == 0)
+ sprintf(pszBuf, "%hd", *(signed char*)varptr);
+ else if (type == 1)
+ sprintf(pszBuf, "%hd", *(signed short*)varptr);
+ else if (type == 2)
+ sprintf(pszBuf, "%ld", *(signed long*)varptr);
+ else if (type == 4)
+ sprintf(pszBuf, "%hu", *(BYTE*) varptr);
+ else if (type == 5)
+ sprintf(pszBuf, "%hu", *(USHORT*)varptr);
+ else if (type == 6)
+ sprintf(pszBuf, "0x%lX (%lu)", *((ULONG*)varptr), *((ULONG*)varptr));
+ else if (type == 8)
+ sprintf(pszBuf, "%f", *(float*)varptr);
+ else if (type == 9)
+ sprintf(pszBuf, "%f", *(double*)varptr);
+ else if (type == 10)
+ sprintf(pszBuf, "%f", (double)(*(long double*)varptr));
+ else if (type == 16)
+ sprintf(pszBuf, "%s", *(char*)varptr ? "TRUE" : "FALSE");
+ else if (type == 17)
+ sprintf(pszBuf, "%s", *(short*)varptr ? "TRUE" : "FALSE");
+ else if (type == 18)
+ sprintf(pszBuf, "%s", *(long*)varptr ? "TRUE" : "FALSE");
+ else if (type == 20)
+ sprintf(pszBuf, "%c", *(char*)varptr);
+ else if (type == 21)
+ sprintf(pszBuf, "%hd", (*(short*)varptr));
+ else if (type == 22)
+ sprintf(pszBuf, "%ld", *(long*)varptr);
+ else if (type == 23)
+ sprintf(pszBuf, "void");
+ else if (type >= 32)
+ {
+ sprintf(pszBuf, "0x%p", (void*)(*(ULONG*)varptr));
+ if (Attr & PAG_FREE)
+ {
+ strcat(pszBuf, " unallocated memory");
+ }
+ else
+ {
+ if ((Attr & PAG_COMMIT) == 0x0U)
+ {
+ strcat(pszBuf, " uncommitted");
+ } // endif
+ if ((Attr & PAG_WRITE) == 0x0U)
+ {
+ strcat(pszBuf, " unwritable");
+ } // endif
+ if ((Attr & PAG_READ) == 0x0U)
+ {
+ strcat(pszBuf, " unreadable");
+ } // endif
+ } // endif
+ } // endif
+ else
+ sprintf(pszBuf, "Unknown type %d", type);
+}
+
+/*
+ * search_userdefs:
+ * searches the table of userdef's-
+ * Return TRUE if found.
+ */
+
+static BOOL search_userdefs(FILE *LogFile, // in: text log file to write to
+ ULONG stackofs,
+ USHORT var_no)
+{
+ USHORT pos;
+
+ for (pos = 0;
+ pos < userdef_count;
+ pos++)
+ {
+ if (one_userdef[pos].idx == autovar_def[var_no].type_idx)
+ {
+ if ( (one_userdef[pos].type_index >= 0x80)
+ // && (one_userdef[pos].type_index <= 0xDA)
+ )
+ {
+ static char sszVar3[500] = "complex";
+ if (one_userdef[pos].type_index <= 0xDA)
+ var_value((void*)(stackofs + autovar_def[var_no].stack_offset),
+ sszVar3,
+ one_userdef[pos].type_index - 0x80);
+
+ fprintf(LogFile,
+ " %- 6ld %- 20.20s %- 33.33s %s (user)\n",
+ autovar_def[var_no].stack_offset, // stack offset
+ autovar_def[var_no].name, // identifier
+ one_userdef[pos].name, // type name
+ sszVar3 // composed by var_value
+ );
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * search_pointers:
+ *
+ */
+
+static BOOL search_pointers(FILE *LogFile, // in: text log file to write to
+ ULONG stackofs,
+ USHORT var_no)
+{
+ USHORT pos, upos;
+ static BYTE str[35];
+ static char sszVar[500];
+
+ // BYTE type_index;
+
+ for (pos = 0;
+ ( (pos < pointer_count)
+ && (one_pointer[pos].idx != autovar_def[var_no].type_idx)
+ );
+ pos++);
+
+ if (pos < pointer_count)
+ {
+ if ( (one_pointer[pos].type_index >= 0x80)
+ && (one_pointer[pos].type_index <= 0xDA)
+ )
+ {
+ strcpy(str, type_name[one_pointer[pos].type_index - 0x80]);
+ strcat(str, " *");
+ var_value((void*)(stackofs + autovar_def[var_no].stack_offset),
+ sszVar,
+ 32);
+ fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr1)\n",
+ autovar_def[var_no].stack_offset,
+ autovar_def[var_no].name,
+ str,
+ sszVar);
+ return TRUE;
+ }
+ else
+ {
+ // If the result isn't a simple type, look for it in the other lists
+ for (upos = 0;
+ ( (upos < userdef_count)
+ && (one_userdef[upos].idx != one_pointer[pos].type_index)
+ );
+ upos++)
+ ;
+
+ if (upos < userdef_count)
+ {
+ strcpy(str, one_userdef[upos].name);
+ strcat(str, " *");
+ var_value((void *)(stackofs + autovar_def[var_no].stack_offset),
+ sszVar,
+ 32);
+ fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr2)\n",
+ autovar_def[var_no].stack_offset,
+ autovar_def[var_no].name,
+ str,
+ sszVar);
+ return TRUE;
+ }
+ else
+ {
+ // if it isn't a userdef, for now give up and just print
+ // as much as we know
+ sprintf(str, "Pointer to type 0x%X", one_pointer[pos].type_index);
+
+ var_value((void *)(stackofs + autovar_def[var_no].stack_offset),
+ sszVar,
+ 32);
+ fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr3)\n",
+ autovar_def[var_no].stack_offset,
+ autovar_def[var_no].name,
+ str,
+ sszVar);
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ *@@ dbgPrintVariables:
+ * Dumps variables for the specified stack offset
+ * to the specified log file.
+ *
+ * New with V0.84.
+ */
+
+void dbgPrintVariables(FILE *LogFile, // in: text log file to write to
+ ULONG stackofs)
+{
+ USHORT n; // , pos;
+ BOOL AutoVarsFound = FALSE;
+
+ if (/* 1 || */ func_ofs == pubfunc_ofs)
+ {
+ for (n = 0;
+ n < var_ofs;
+ n++)
+ {
+ if (AutoVarsFound == FALSE)
+ {
+ AutoVarsFound = TRUE;
+ fprintf(LogFile, " List of auto variables at EBP %p in %s:\n",
+ (PVOID)stackofs,
+ func_name);
+ fprintf(LogFile, " Offset Name Type Value \n");
+ fprintf(LogFile, " ������ �������������������� ��������������������������������� �����������������\n");
+ }
+
+ // If it's one of the simple types
+ if ( (autovar_def[n].type_idx >= 0x80)
+ && (autovar_def[n].type_idx <= 0xDA)
+ )
+ {
+ static char sszVar2[500];
+
+ var_value((void *)(stackofs + autovar_def[n].stack_offset),
+ sszVar2,
+ autovar_def[n].type_idx - 0x80);
+
+ fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (simple)\n",
+ autovar_def[n].stack_offset,
+ autovar_def[n].name,
+ type_name[autovar_def[n].type_idx - 0x80],
+ sszVar2);
+ }
+ else
+ { // Complex type, check if we know what it is
+ if (!search_userdefs(LogFile, stackofs, n))
+ {
+ if (!search_pointers(LogFile, stackofs, n))
+ {
+ fprintf(LogFile, " %- 6ld %-20.20s 0x%X (unknown)\n",
+ autovar_def[n].stack_offset,
+ autovar_def[n].name,
+ autovar_def[n].type_idx);
+ }
+ }
+ }
+ }
+ /* if (AutoVarsFound == FALSE)
+ {
+ fprintf(LogFile, " No auto variables found in %s.\n", func_name);
+ } */
+ fprintf(LogFile, "\n");
+ }
+}
+
+/* ******************************************************************
+ *
+ * PART 3: ANALYZE SYMBOL (.SYM) FILE
+ *
+ ********************************************************************/
+
+/*
+ *@@ dbgPrintSYMInfo:
+ * this gets called by dbgPrintStack if dbgPrintDebugInfo
+ * failed (because no debug code was found) to check if
+ * maybe a SYM file with the same filename exists and try
+ * to get the info from there.
+ *
+ * This gets called for every line of the stack
+ * walk, but only if getting the information from
+ * the debug code failed, e.g. because no debug code
+ * was available for an address.
+ *
+ * The file pointer is in the "Source file" column
+ * every time this gets called.
+ *
+ * New with V0.84.
+ *
+ * Returns 0 if reading the SYM file was successful.
+ *
+ *@@changed V0.9.1 (2000-01-30) [umoeller]: added return code; this used to be VOID
+ */
+
+int dbgPrintSYMInfo(FILE *LogFile, // in: text log file to write to
+ CHAR *SymFileName, // in: SYM file name (can be fully q'fied)
+ ULONG Object,
+ ULONG TrapOffset)
+{
+ static FILE *SymFile;
+ static MAPDEF MapDef;
+ static SEGDEF SegDef;
+ static SYMDEF32 SymDef32;
+ static SYMDEF16 SymDef16;
+ static char Buffer[256];
+ static int SegNum, SymNum, LastVal;
+ static unsigned long int SegOffset,
+ SymOffset, SymPtrOffset;
+
+ // open .SYM file
+#ifdef DEBUG_SYMDUMP
+ fprintf(LogFile,"Dump of '%s' for object %d\n",SymFileName,Object);
+#endif
+ SymFile = fopen(SymFileName, "rb");
+ if (SymFile == 0)
+ return (2);
+
+ // read in first map definition
+ fread(&MapDef, sizeof(MAPDEF), 1, SymFile);
+#ifdef DEBUG_SYMDUMP
+ Buffer[0] = MapDef.achModName[0];
+ fread(&Buffer[1], 1, MapDef.cbModName-1, SymFile);
+ Buffer[MapDef.cbModName] = 0x00;
+ fprintf(LogFile,"Module name '%s'\n",Buffer);
+#endif
+
+ SegOffset = SEGDEFOFFSET(MapDef);
+#ifdef DEBUG_SYMDUMP
+ fprintf(LogFile,"SegOffset %0x\n",SegOffset);
+#endif
+
+ // go thru all segments
+ for (SegNum = 0;
+ SegNum < MapDef.cSegs;
+ SegNum++)
+ {
+#ifdef DEBUG_SYMDUMP
+ fprintf(LogFile,"Scanning segment #%d Offset %08X\n",SegNum,SegOffset);
+#endif
+ if (fseek(SymFile, SegOffset, SEEK_SET))
+ // seek error
+ return (3);
+
+ // read in segment definition
+ fread(&SegDef, sizeof(SEGDEF), 1, SymFile);
+#ifdef DEBUG_SYMDUMP
+ Buffer[0] = 0x00;
+ if (SegDef.cbSegName>0) {
+ Buffer[0] = SegDef.achSegName[0];
+ fread(&Buffer[1], 1, SegDef.cbSegName-1, SymFile);
+ Buffer[SegDef.cbSegName] = 0x00;
+ }
+ fprintf(LogFile,"Segment name '%s', number %d, flags %02x\n",Buffer,SegNum,SegDef.bFlags);
+#endif
+
+ if (SegNum == Object)
+ {
+ // stack object found:
+ Buffer[0] = 0x00;
+ LastVal = 0;
+
+ // go thru all symbols in this object
+#ifdef DEBUG_SYMDUMP
+ fprintf(LogFile,"Scanning #%d symbols\n",SegDef.cSymbols);
+#endif
+ for (SymNum = 0; SymNum < SegDef.cSymbols; SymNum++)
+ {
+ SymPtrOffset=SYMDEFOFFSET(SegOffset,SegDef,SymNum);
+ fseek(SymFile,SymPtrOffset,SEEK_SET);
+ fread(&SymOffset,sizeof(unsigned short int),1,SymFile);
+ fseek(SymFile,SymOffset+SegOffset,SEEK_SET);
+ if (SegDef.bFlags & 0x01)
+ {
+ // 32-bit symbol:
+ fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile);
+ if (SymDef32.wSymVal > TrapOffset)
+ {
+ // symbol found
+ fprintf(LogFile,
+ "between %s + 0x%lX ",
+ Buffer,
+ TrapOffset - LastVal);
+ /* fprintf(LogFile, "(ppLineDef: 0x%lX) ",
+ LINEDEFOFFSET(SegDef)
+ ); */
+ fprintf(LogFile, "\n");
+ }
+
+ LastVal = SymDef32.wSymVal;
+ Buffer[0] = SymDef32.achSymName[0];
+ fread(&Buffer[1], 1, SymDef32.cbSymName-1, SymFile);
+ Buffer[SymDef32.cbSymName] = 0x00;
+#ifdef DEBUG_SYMDUMP
+ fprintf(LogFile,"32 Bit Symbol Address %08p <%s> \n",SymDef32.wSymVal,Buffer);
+#endif
+
+ if (SymDef32.wSymVal > TrapOffset)
+ {
+ // symbol found, as above
+ fprintf(LogFile,
+ " "
+ "and %s - 0x%lX ",
+ Buffer,
+ LastVal - TrapOffset);
+ fprintf(LogFile, "\n");
+ break;
+ }
+ }
+ else
+ {
+ // 16-bit symbol:
+ fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile);
+ if (SymDef16.wSymVal > TrapOffset)
+ {
+ fprintf(LogFile,
+ "between %s + %lX\n",
+ Buffer,
+ TrapOffset - LastVal);
+ }
+ LastVal = SymDef16.wSymVal;
+ Buffer[0] = SymDef16.achSymName[0];
+ fread(&Buffer[1], 1, SymDef16.cbSymName-1, SymFile);
+ Buffer[SymDef16.cbSymName] = 0x00;
+ if (SymDef16.wSymVal > TrapOffset)
+ {
+ fprintf(LogFile,
+ " "
+ "and %s - %lX\n",
+ Buffer,
+ LastVal - TrapOffset);
+ break;
+ }
+#ifdef DEBUG_SYMDUMP
+ fprintf(LogFile,"16 Bit Symbol <%s> Address %p\n",Buffer,SymDef16.wSymVal);
+#endif
+ } // endif
+ }
+ break;
+ } // endif
+ SegOffset = NEXTSEGDEFOFFSET(SegDef);
+ } // endwhile
+ fclose(SymFile);
+ return (0); // no error
+}
+
+/* ******************************************************************
+ *
+ * PART 4: dbgPrintStack
+ *
+ ********************************************************************/
+
+/*
+ *@@ dbgPrintStackFrame:
+ * parses and dumps one stack frame.
+ * Called from excPrintStackFrame.
+ *
+ * This calls dbgPrintDebugInfo and, if
+ * that fails, dbgPrintSYMInfo.
+ *
+ *@@added V0.9.2 (2000-03-10) [umoeller]
+ *@@changed V0.9.3 (2000-04-10) [umoeller]: added support for non-Warp 4 SYM files
+ *@@changed V0.9.3 (2000-04-26) [umoeller]: this broke Warp 4 FP 13, fixed
+ */
+
+BOOL dbgPrintStackFrame(FILE *LogFile,
+ PSZ pszModuleName, // in: module name (fully q'fied)
+ ULONG ulObject,
+ ULONG ulOffset)
+{
+ APIRET arc = 0;
+ // "Source file"... columns
+
+//YD do not use debug info
+#define ENABLE_DEBUG_INFO
+#ifdef ENABLE_DEBUG_INFO
+ // first attempt to analyze the debug code
+ arc = dbgPrintDebugInfo(LogFile,
+ pszModuleName,
+ ulObject,
+ ulOffset);
+#else
+ arc = 1;
+#endif
+
+ // if no debug code is available, analyze
+ // the SYM file instead
+ if (arc != NO_ERROR)
+ {
+ CHAR szSymName[CCHMAXPATH];
+ strcpy(szSymName, pszModuleName);
+ strcpy(szSymName + strlen(szSymName) - 3, "SYM");
+ arc = dbgPrintSYMInfo(LogFile,
+ szSymName,
+ ulObject,
+ ulOffset);
+ if (arc != 0)
+ {
+ // SYM file not found in current directory:
+ // check the SYM files in the \OS2 directory,
+ // depending on the OS/2 version level:
+ CHAR szSymFile2[CCHMAXPATH];
+ PSZ pszFilename = strrchr(szSymName, '\\');
+ if (pszFilename)
+ {
+ PSZ pszVersionDir = "WARP4";
+ ULONG aulBuf[3];
+
+ DosQuerySysInfo(QSV_VERSION_MAJOR, // 11
+ QSV_VERSION_MINOR, // 12
+ &aulBuf, sizeof(aulBuf));
+ // Warp 3 is reported as 20.30
+ // Warp 4 is reported as 20.40
+ // Aurora is reported as 20.45
+
+ if (aulBuf[0] == 20)
+ {
+ if (aulBuf[1] == 30)
+ // Warp 3:
+ pszVersionDir = "WARP3";
+ else if (aulBuf[1] >= 40)
+ // Warp 4 or higher:
+ // (NOTE: Warp 4 FP 13 now returns 45 also,
+ // but the SYM files are still in the WARP4 directory...)
+ // V0.9.3 (2000-04-26) [umoeller]
+ pszVersionDir = "WARP4";
+ }
+
+ pszFilename++;
+ sprintf(szSymFile2,
+ "%c:\\OS2\\PDPSI\\PMDF\\%s\\%s",
+ doshQueryBootDrive(),
+ pszVersionDir,
+ pszFilename);
+ arc = dbgPrintSYMInfo(LogFile,
+ szSymFile2,
+ ulObject,
+ ulOffset);
+
+ // V0.9.3 (2000-04-26) [umoeller]
+ if ( (arc != 0) // still not found
+ && (aulBuf[1] == 45) // and running Aurora or Warp 4 FP13?
+ )
+ {
+ // Warp Server for e-Business (aka Warp 4.5):
+ // we use the SYM files for the UNI kernel,
+ // I have found no way to find out whether
+ // we're running on an SMP kernel
+ sprintf(szSymFile2,
+ "%c:\\OS2\\PDPSI\\PMDF\\%s\\%s",
+ doshQueryBootDrive(),
+ "WARP45_U",
+ pszFilename);
+ arc = dbgPrintSYMInfo(LogFile,
+ szSymFile2,
+ ulObject,
+ ulOffset);
+ }
+ }
+ }
+
+ if (arc == 2) // file not found
+ fprintf(LogFile,
+ "Cannot find symbol file %s\n",
+ szSymName);
+ else if (arc != 0)
+ fprintf(LogFile,
+ "Error %lu reading symbol file %s\n",
+ arc,
+ szSymName);
+ }
+
+ return (arc == NO_ERROR);
+}
+
+/*
+ *@@ dbgPrintStack:
+ * this takes stack data from the TIB and
+ * context record data structures and tries
+ * to analyse what the different stack frames
+ * point to.
+ *
+ * For each stack frame, this calls dbgPrintDebugInfo,
+ * and, if that fails, dbgPrintSYMInfo.
+ *
+ * New with V0.84.
+ *
+ *@@changed V0.9.2 (2000-03-08) [umoeller]: now searching OS2\PDPSI\PMDF for SYM files also
+ */
+
+VOID dbgPrintStack(FILE *LogFile, // in: text log file to write to
+ PUSHORT StackBottom,
+ PUSHORT StackTop,
+ PUSHORT Ebp,
+ PUSHORT ExceptionAddress)
+{
+ PUSHORT RetAddr = 0;
+ PUSHORT LastEbp = 0;
+ APIRET rc = 0;
+ ULONG Size = 0,
+ Attr = 0;
+ USHORT Cs = 0,
+ Ip = 0,
+ // Bp,
+ Sp = 0;
+ static char Name[CCHMAXPATH];
+ HMODULE hMod = 0;
+ ULONG ObjNum = 0;
+ ULONG Offset = 0;
+ BOOL fExceptionAddress = TRUE; // Use Exception Addr 1st time thru
+
+ // Note: we can't handle stacks bigger than 64K for now...
+ Sp = (USHORT) (((ULONG) StackBottom) >> 16);
+ // Bp = ;
+
+ if (!f32bit)
+ Ebp = (PUSHORT) MAKEULONG(((USHORT)(ULONG)Ebp), Sp);
+
+ fprintf(LogFile, "\n\nCall stack:\n");
+ fprintf(LogFile, " Source Line Nearest\n");
+ fprintf(LogFile, " EBP Address Module Obj# File Numbr Public Symbol\n");
+ fprintf(LogFile, " �������� ��������- �������� ���� ������������ ����� ������������-\n");
+
+ do
+ {
+ Size = 10;
+ rc = DosQueryMem((PVOID) (Ebp + 2), &Size, &Attr);
+ if (rc != NO_ERROR)
+ {
+ fprintf(LogFile, "Invalid EBP %8.8lX (DosQueryMem returned %lu)\n", (ULONG)Ebp, rc);
+ break;
+ }
+ if (!(Attr & PAG_COMMIT))
+ {
+ fprintf(LogFile, "Invalid EBP %8.8lX (not committed)\n", (ULONG)Ebp);
+ break;
+ }
+ if (Size < 10)
+ {
+ fprintf(LogFile, "Invalid EBP %8.8lX (mem block size < 10)\n", (ULONG)Ebp);
+ break;
+ }
+
+ if (fExceptionAddress)
+ RetAddr = ExceptionAddress;
+ else
+ RetAddr = (PUSHORT) (*((PULONG) (Ebp + 2)));
+
+ if (RetAddr == (PUSHORT) 0x00000053)
+ {
+ // For some reason there's a "return address" of 0x53 following
+ // EBP on the stack and we have to adjust EBP by 44 bytes to get
+ // at the real return address. This has something to do with
+ // thunking from 32bits to 16bits...
+ // Serious kludge, and it's probably dependent on versions of C(++)
+ // runtime or OS, but it works for now!
+ Ebp += 22;
+ RetAddr = (PUSHORT) (*((PULONG) (Ebp + 2)));
+ }
+
+ // Get the (possibly) 16bit CS and IP
+ if (fExceptionAddress)
+ {
+ Cs = (USHORT) (((ULONG) ExceptionAddress) >> 16);
+ Ip = (USHORT) (ULONG) ExceptionAddress;
+ }
+ else
+ {
+ Cs = *(Ebp + 2);
+ Ip = *(Ebp + 1);
+ }
+
+ // if the return address points to the stack then it's really just
+ // a pointer to the return address (UGH!).
+ if ( (USHORT) (((ULONG) RetAddr) >> 16) == Sp
+ )
+ RetAddr = (PUSHORT) (*((PULONG) RetAddr));
+
+ if (Ip == 0 && *Ebp == 0)
+ {
+ // End of the stack so these are both shifted by 2 bytes:
+ Cs = *(Ebp + 3);
+ Ip = *(Ebp + 2);
+ }
+
+ // 16bit programs have on the stack:
+ // BP:IP:CS
+ // where CS may be thunked
+ //
+ // in dump swapped
+ // BP IP CS BP CS IP
+ // 4677 53B5 F7D0 7746 D0F7 B553
+ //
+ // 32bit programs have:
+ // EBP:EIP
+ // and you'd have something like this (with SP added) (not
+ // accurate values)
+ //
+ // in dump swapped
+ // EBP EIP EBP EIP
+ // 4677 2900 53B5 F7D0 0029 7746 D0F7 B553
+ //
+ // So the basic difference is that 32bit programs have a 32bit
+ // EBP and we can attempt to determine whether we have a 32bit
+ // EBP by checking to see if its 'selector' is the same as SP.
+ // Note that this technique limits us to checking stacks < 64K.
+ //
+ // Soooo, if IP (which maps into the same USHORT as the swapped
+ // stack page in EBP) doesn't point to the stack (i.e. it could
+ // be a 16bit IP) then see if CS is valid (as is or thunked).
+ //
+ // Note that there's the possibility of a 16bit return address
+ // that has an offset that's the same as SP so we'll think it's
+ // a 32bit return address and won't be able to successfully resolve
+ // its details.
+ if (Ip != Sp)
+ {
+ if (DosSizeSeg(Cs, &Size) == NO_ERROR)
+ {
+ RetAddr = (USHORT * _Seg16) MAKEULONG(Ip, Cs);
+ f32bit = FALSE;
+ }
+ else if (DosSizeSeg((Cs << 3) + 7, &Size) == NO_ERROR)
+ {
+ Cs = (Cs << 3) + 7;
+ RetAddr = (USHORT * _Seg16) MAKEULONG(Ip, Cs);
+ f32bit = FALSE;
+ }
+ else
+ f32bit = TRUE;
+ }
+ else
+ f32bit = TRUE;
+
+
+ // "EBP" column
+ if (fExceptionAddress)
+ fprintf(LogFile, " Trap -> ");
+ else
+ fprintf(LogFile, " %8.8lX ", (ULONG)Ebp);
+
+ // "Address" column
+ if (f32bit)
+ fprintf(LogFile, ":%8.8lX ", (ULONG)RetAddr);
+ else
+ fprintf(LogFile, "%04.04X:%04.04X ", Cs, Ip);
+
+ // Version check omitted; the following requires
+ // OS/2 2.10 or later (*UM)
+ // if (Version[0] >= 20 && Version[1] >= 10)
+ {
+ // Make a 'tick' sound to let the user know we're still alive
+ DosBeep(2000, 10);
+
+ Size = 10; // Inserted by Kim Rasmussen 26/06 1996 to avoid error 87 when Size is 0
+
+ // "Module"/"Object" columns
+ rc = DosQueryMem((PVOID) RetAddr, &Size, &Attr);
+ if (rc != NO_ERROR || !(Attr & PAG_COMMIT))
+ {
+ fprintf(LogFile, "Invalid RetAddr: %8.8lX\n", (ULONG)RetAddr);
+ break; // avoid infinite loops
+ }
+ else
+ {
+ rc = DosQueryModFromEIP(&hMod,
+ &ObjNum,
+ sizeof(Name), Name,
+ &Offset,
+ (PVOID)RetAddr);
+ if ( (rc == NO_ERROR)
+ // && (ObjNum != -1)
+ )
+ {
+ // static char szJunk[_MAX_FNAME];
+ static char szName[_MAX_FNAME];
+
+ DosQueryModuleName(hMod, sizeof(Name), Name);
+ // _splitpath(Name, szJunk, szJunk, szName, szJunk);
+
+ // print module and object
+ fprintf(LogFile, "%-8s %04lX ", szName, ObjNum + 1);
+
+ if (strlen(Name) > 3)
+ {
+ dbgPrintStackFrame(LogFile,
+ Name,
+ ObjNum,
+ Offset);
+ }
+ }
+ else
+ fprintf(LogFile,
+ "DosQueryModFromEIP failed, returned %lu\n",
+ rc);
+ }
+ }
+
+ if ( ((*Ebp) == 0)
+ && ((*Ebp + 1) == 0)
+ )
+ {
+ fprintf(LogFile, "End of call stack\n");
+ break;
+ }
+
+ if (!fExceptionAddress)
+ {
+ LastEbp = Ebp;
+#if 0
+ Ebp = (PUSHORT) MAKEULONG(Bp, Sp);
+#else // Inserted by Kim Rasmussen 26/06 1996 to allow big stacks
+ if (f32bit)
+ Ebp = (PUSHORT) *(PULONG) LastEbp;
+ else
+ Ebp = (PUSHORT) MAKEULONG((*Ebp), Sp);
+#endif
+ if (f32bit)
+ {
+ dbgPrintVariables(LogFile, (ULONG) Ebp);
+ } // endif
+
+ if (Ebp < LastEbp)
+ {
+ fprintf(LogFile, "... lost stack chain - new EBP below previous\n");
+ break;
+ }
+ }
+ else
+ fExceptionAddress = FALSE;
+
+ Size = 4;
+ rc = DosQueryMem((PVOID) Ebp, &Size, &Attr);
+ if ((rc != NO_ERROR) || (Size < 4))
+ {
+ fprintf(LogFile, "... lost stack chain - invalid EBP: %8.8lX\n", (ULONG)Ebp);
+ break;
+ }
+ } while (TRUE);
+
+ fprintf(LogFile, "\n");
+}
+
+/*
+ *@@ doshQueryBootDrive:
+ * returns the letter of the boot drive as a
+ * single (capital) character, which is useful for
+ * constructing file names using sprintf and such.
+ *
+ *@@changed V0.9.16 (2002-01-13) [umoeller]: optimized
+ */
+
+CHAR doshQueryBootDrive(VOID)
+{
+ // this can never change, so query this only once
+ // V0.9.16 (2002-01-13) [umoeller]
+ static CHAR cBootDrive = '\0';
+
+ if (!cBootDrive)
+ {
+ ULONG ulBootDrive;
+ DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
+ &ulBootDrive,
+ sizeof(ulBootDrive));
+ cBootDrive = (CHAR)ulBootDrive + 'A' - 1;
+ }
+
+ return (cBootDrive);
+}
diff --git a/sal/osl/os2/diagnose.c b/sal/osl/os2/diagnose.c
new file mode 100644
index 000000000000..4921e20fd5af
--- /dev/null
+++ b/sal/osl/os2/diagnose.c
@@ -0,0 +1,178 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+
+BYTE oslTraceEnv[] = "OSL_TRACE_TO_FILE";
+
+typedef pfunc_osl_printDebugMessage oslDebugMessageFunc;
+static oslDebugMessageFunc volatile g_pDebugMessageFunc = 0;
+
+typedef pfunc_osl_printDetailedDebugMessage oslDetailedDebugMessageFunc;
+static oslDetailedDebugMessageFunc volatile g_pDetailedDebugMessageFunc = 0;
+
+/*----------------------------------------------------------------------------*/
+
+void SAL_CALL osl_breakDebug()
+{
+ __asm__("int $3\n");
+}
+
+/************************************************************************/
+/* osl_trace */
+/************************************************************************/
+/* comment this define to stop output thread identifier*/
+#define OSL_TRACE_THREAD 1
+void SAL_CALL osl_trace (
+ const sal_Char* lpszFormat, ...)
+{
+ va_list args;
+
+#if defined(OSL_PROFILING)
+ fprintf(stderr, "Time: %06lu : ", osl_getGlobalTimer() );
+#else
+#if defined(OSL_TRACE_THREAD)
+ fprintf(stderr,"Thread: %6d :",osl_getThreadIdentifier(NULL));
+#else
+ fprintf(stderr, "Trace Message: ");
+#endif
+#endif
+
+ va_start(args, lpszFormat);
+ vfprintf(stderr, lpszFormat, args);
+ va_end(args);
+
+ fprintf(stderr,"\n");
+ fflush(stderr);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void SAL_CALL osl_trace__yd_os2(const sal_Char* lpszFormat, ...)
+{
+
+ int nBuf;
+ sal_Char szBuffer[512];
+ sal_Char szPID[ 12 ];
+ va_list args;
+ FILE* pFile;
+ PID pid;
+ PSZ pszOslTraceFile;
+
+ /* if environment variable not set, do nothing */
+ if(DosScanEnv(oslTraceEnv, (PSZ*)&pszOslTraceFile))
+ {
+ return;
+ }
+
+ va_start(args, lpszFormat);
+
+ nBuf = vsprintf(szBuffer, lpszFormat, args);
+ OSL_ASSERT(nBuf < sizeof(szBuffer));
+
+ va_end(args);
+
+ /* get process ID */
+ {
+ PTIB pptib = NULL;
+ PPIB pppib = NULL;
+
+ DosGetInfoBlocks( &pptib, &pppib );
+ pid = pppib->pib_ulpid;
+ }
+
+ pFile = fopen( (const char*)pszOslTraceFile, "a+" );
+ fputs(_itoa( pid, szPID, 10 ), pFile );
+ fputs( ": ", pFile );
+ fputs(szBuffer, pFile);
+ fclose( pFile );
+
+}
+
+/*----------------------------------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_assertFailedLine( const sal_Char* pszFileName, sal_Int32 nLine, const sal_Char* pszMessage)
+{
+ sal_Char szMessage[512];
+
+ /* get app name or NULL if unknown (don't call assert) */
+ sal_Char* lpszAppName = "OSL";
+
+ /* format message into buffer */
+ sprintf(szMessage, "Assertion Failed: %s: File %s, Line %d:\n",
+ lpszAppName, pszFileName, nLine);
+ if(pszMessage != 0)
+ strcat( szMessage, pszMessage );
+
+ szMessage[sizeof(szMessage)-1] = '\0';
+
+ fputs(szMessage, stderr);
+
+ return sal_True; /* abort */
+}
+
+/*----------------------------------------------------------------------------*/
+
+sal_Int32 SAL_CALL osl_reportError(sal_uInt32 nType, const sal_Char* pszMessage)
+{
+ fputs(pszMessage, stderr);
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+
+
+/************************************************************************/
+/* osl_setDebugMessageFunc */
+/************************************************************************/
+oslDebugMessageFunc SAL_CALL osl_setDebugMessageFunc (
+ oslDebugMessageFunc pNewFunc)
+{
+ oslDebugMessageFunc pOldFunc = g_pDebugMessageFunc;
+ g_pDebugMessageFunc = pNewFunc;
+ return pOldFunc;
+}
+
+/************************************************************************/
+/* osl_setDetailedDebugMessageFunc */
+/************************************************************************/
+pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc (
+ pfunc_osl_printDetailedDebugMessage pNewFunc)
+{
+ oslDetailedDebugMessageFunc pOldFunc = g_pDetailedDebugMessageFunc;
+ g_pDetailedDebugMessageFunc = pNewFunc;
+ return pOldFunc;
+}
diff --git a/sal/osl/os2/dllentry.c b/sal/osl/os2/dllentry.c
new file mode 100644
index 000000000000..494119599f8b
--- /dev/null
+++ b/sal/osl/os2/dllentry.c
@@ -0,0 +1,75 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+#include "sockimpl.h"
+#include "secimpl.h"
+//#include "daemimpl.h"
+
+#include <osl/diagnose.h>
+
+#ifndef GCC
+sal_uInt32 _System _DLL_InitTerm( sal_uInt32 nModule,
+ sal_uInt32 nFlag )
+{
+ switch( nFlag )
+ {
+ case 0:
+ {
+ /* initialize C runtime library */
+ _CRT_init();
+ {
+ LONG fhToAdd = 0;
+ ULONG fhOld = 0;
+ ULONG ngLastError = DosSetRelMaxFH(&fhToAdd, &fhOld);
+ if (fhOld < 200)
+ ngLastError = DosSetMaxFH(200);
+ }
+
+ /* turn off hardware-errors and exception popups */
+ DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
+
+ break;
+ }
+
+ case 1:
+ {
+ /* unload libs (sockets) */
+ ImplFreeTCPIP();
+
+ /* unload libs (security) */
+ ImplFreeUPM();
+
+ break;
+ }
+ }
+
+ return (sal_True);
+}
+#endif
+
+
diff --git a/sal/osl/os2/except.c b/sal/osl/os2/except.c
new file mode 100644
index 000000000000..29962889fb01
--- /dev/null
+++ b/sal/osl/os2/except.c
@@ -0,0 +1,1059 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*
+ *@@sourcefile except.c:
+ * this file contains powerful exception handlers.
+ * except.h also defines easy-to-use macros for them.
+ *
+ * Usage: All OS/2 programs, PM or text mode.
+ *
+ * <B>Introduction</B>
+ *
+ * OS/2 exception handlers are a mess to program and,
+ * if installed wrongly, almost impossible to debug.
+ * The problem is that for any program that does a bit
+ * more than showing a message box, using exception
+ * handlers is a must to avoid system hangs. This
+ * especially applies to multi-thread programs using
+ * mutex semaphores (more on that below). The functions
+ * and macros in here are designed to make that more
+ * simple.
+ *
+ * The macros in except.h automatically insert code for
+ * properly registering and deregistering the handlers
+ * in except.c. You should ALWAYS use these macros
+ * instead of directly registering the handlers to avoid
+ * accidentally forgetting to deregister them. If you
+ * forget to deregister an exception handler, this can
+ * lead to really strange errors (crashes, hangs) which
+ * are nearly impossible to debug because the thread's
+ * stack probably got completely messed up.
+ *
+ * The general idea of these macros is to define
+ * TRY / CATCH blocks similar to C++. If an exception
+ * occurs in the TRY block, execution is transferred to
+ * the CATCH block. (This works in both C and C++, by the
+ * way.)
+ *
+ * The "OnKill" function that was added with V0.9.0 has
+ * been removed again with V0.9.7.
+ *
+ * The general usage is like this:
+ *
+ + int your_protected_func(int ...)
+ + {
+ + TRY_LOUD(excptid) // or: TRY_QUIET(excptid)
+ + {
+ + char *p = NULL;
+ +
+ + .... // the stuff in here is protected by
+ + // the excHandlerLoud or excHandlerQuiet
+ + // exception handler
+ + *p = "A";
+ + }
+ + CATCH(excptid)
+ + {
+ + .... // exception occured: react here
+ + } END_CATCH(); // always needed!
+ + } // end of your_func
+ *
+ * TRY_LOUD is for installing excHandlerLoud.
+ * TRY_QUIET is for installing excHandlerQuiet.
+ * CATCH / END_CATCH are the same for the two. This
+ * is where the exception handler jumps to if an
+ * exception occurs.
+ * The CATCH block is _required_ even if you do nothing
+ * in there, because the CATCH() macro will deregister
+ * the handler.
+ *
+ * "excptid" can be any C identifier which is not used in
+ * your current variable scope, e.g. "excpt1". This
+ * is used for creating an EXCEPTSTRUCT variable of
+ * that name on the stack. The "excptid"'s in TRY_* and
+ * CATCH must match, since this is where the macros
+ * store the exception handler data.
+ *
+ * These macros may be nested if you use different
+ * "excptid"'s for sub-macros.
+ *
+ * Inside the TRY and CATCH blocks, you must not use
+ * "goto" (to a location outside the block) or "return",
+ * because this will not deregister the handler.
+ *
+ * Keep in mind that all the code in the TRY_* block is
+ * protected by the handler, including all functions that
+ * get called. So if you enclose your main() code in a
+ * TRY_* block, your entire application is protected.
+ * If any subfunction fails, execution is transferred to
+ * the closest CATCH() that was installed (as with C++
+ * try and catch).
+ *
+ * <B>Asynchronous exceptions</B>
+ *
+ * The exception handlers in this file (which are installed
+ * with the TRY/CATCH mechanism) only intercept synchronous
+ * exceptions, most importantly, XCPT_ACCESS_VIOLATION (see
+ * excHandlerLoud for a list). They do not protect your code
+ * against asynchronous exceptions.
+ *
+ * OS/2 defines asynchronous exceptions to be those that
+ * can be delayed. With OS/2, there are only three of these:
+ *
+ * -- XCPT_PROCESS_TERMINATE
+ * -- XCPT_ASYNC_PROCESS_TERMINATE
+ * -- XCPT_SIGNAL (thread 1 only)
+ *
+ * To protect yourself against these also, put the section
+ * in question in a DosEnterMustComplete/DosExitMustComplete
+ * block as well.
+ *
+ * <B>Mutex semaphores</B>
+ *
+ * The problem with OS/2 mutex semaphores is that they are
+ * sometimes not automatically released when a thread terminates.
+ * If there are several mutexes involved and they are released
+ * in improper order, you can get zombie threads on exit.
+ * Even worse, if this happens to a PM thread, this will hang
+ * the system.
+ *
+ * As a result, you should protect any section of code which
+ * requests a semaphore with the exception handlers.
+ *
+ * So _whenever_ you request a mutex semaphore, enclose
+ * the block with TRY/CATCH in case the code crashes.
+ * Besides, enclose the TRY/CATCH block in a must-complete
+ * section, like this:
+ *
+ + HMTX hmtx = ...
+ +
+ + int your_func(int)
+ + {
+ + BOOL fSemOwned = FALSE;
+ +
+ + TRY_QUIET(excpt1) // or TRY_LOUD
+ + {
+ + if (fSemOwned = !DosRequestMutexSem(hmtx, ...))
+ + { ... // work on your protected data
+ + }
+ + // mutex gets released below
+ + }
+ + CATCH(excpt1) { } END_CATCH(); // always needed!
+ +
+ + if (fSemOwned)
+ + // this gets executed always, even if an exception occured
+ + DosReleaseMutexSem(hmtx);
+ + } // end of your_func
+ *
+ * This way your mutex semaphore gets released in every
+ * possible condition.
+ *
+ * <B>Customizing</B>
+ *
+ * As opposed to versions before 0.9.0, this code is now
+ * completely independent of XWorkplace. This file now
+ * contains "pure" exception handlers only.
+ *
+ * However, you can customize these exception handlers by
+ * calling excRegisterHooks. This is what XWorkplace does now.
+ * This should be done upon initialization of your application.
+ * If excRegisterHooks is not called, the following safe
+ * defaults are used:
+ *
+ * -- the trap log file is TRAP.LOG in the root
+ * directory of your boot drive.
+ *
+ * For details on the provided exception handlers, refer
+ * to excHandlerLoud and excHandlerQuiet.
+ *
+ * More useful debug information can be found in the "OS/2 Debugging
+ * Handbook", which is now available in INF format on the IBM
+ * DevCon site ("http://service2.boulder.ibm.com/devcon/").
+ * This book shows worked examples of how to unwind a stack dump.
+ *
+ * This file incorporates code from the following:
+ * -- Monte Copeland, IBM Boca Ration, Florida, USA (1993)
+ * -- Roman Stangl, from the Program Commander/2 sources
+ * (1997-98)
+ * -- Marc Fiammante, John Currier, Kim Rasmussen,
+ * Anthony Cruise (EXCEPT3.ZIP package for a generic
+ * exception handling DLL, available at Hobbes).
+ *
+ * If not explicitly stated otherwise, the code has been written
+ * by me, Ulrich M�ller.
+ *
+ * Note: Version numbering in this file relates to XWorkplace version
+ * numbering.
+ *
+ *@@header "helpers\except.h"
+ */
+
+/*
+ * This file Copyright (C) 1992-99 Ulrich M�ller,
+ * Monte Copeland,
+ * Roman Stangl,
+ * Kim Rasmussen,
+ * Marc Fiammante,
+ * John Currier,
+ * Anthony Cruise.
+ * This file is part of the "XWorkplace helpers" source package.
+ *
+ * 2009-06-15 published under LGPL3 with Ulrich M�ller permission.
+ *
+ */
+
+#define OS2EMX_PLAIN_CHAR
+ // this is needed for "os2emx.h"; if this is defined,
+ // emx will define PSZ as _signed_ char, otherwise
+ // as unsigned char
+
+#define INCL_DOSMODULEMGR
+#define INCL_DOSEXCEPTIONS
+#define INCL_DOSPROCESS
+#define INCL_DOSMISC
+#define INCL_DOSERRORS
+#include <os2.h>
+
+// C library headers
+#include <stdio.h> // needed for except.h
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <setjmp.h> // needed for except.h
+#include <assert.h> // needed for except.h
+
+#define DONT_REPLACE_MALLOC
+#include "helpers\setup.h" // code generation and debugging options
+
+// headers in /helpers
+#include "helpers\dosh.h" // Control Program helper routines
+#include "helpers\except.h" // exception handling
+#include "helpers\debug.h" // symbol/debug code analysis
+
+#pragma hdrstop
+
+/* ******************************************************************
+ *
+ * Global variables
+ *
+ ********************************************************************/
+
+// hooks to be registered using excRegisterHooks
+PFNEXCOPENFILE G_pfnExcOpenFile = 0;
+PFNEXCHOOK G_pfnExcHook = 0;
+PFNEXCHOOKERROR G_pfnExcHookError = 0;
+// beep flag for excHandlerLoud
+BOOL G_fBeepOnException = TRUE;
+
+ULONG G_ulExplainExceptionRunning = 0;
+ // global flag which is != 0 if some exception handler
+ // is inside excExplainException, so that XShutdown can
+ // wait until the trap log is done;
+ // this is exported thru except.h
+ // V0.9.13 (2001-06-19) [umoeller]
+
+/*
+ *@@category: Helpers\Control program helpers\Exceptions/debugging
+ * See except.c.
+ */
+
+/* ******************************************************************
+ *
+ * Exception helper routines
+ *
+ ********************************************************************/
+
+/*
+ *@@ excDescribePage:
+ *
+ */
+
+VOID excDescribePage(FILE *file, ULONG ulCheck)
+{
+ APIRET arc;
+ ULONG ulCountPages = 1;
+ ULONG ulFlagsPage = 0;
+ arc = DosQueryMem((PVOID)ulCheck, &ulCountPages, &ulFlagsPage);
+
+ if (arc == NO_ERROR)
+ {
+ fprintf(file, "valid, flags: ");
+ if (ulFlagsPage & PAG_READ)
+ fprintf(file, "read ");
+ if (ulFlagsPage & PAG_WRITE)
+ fprintf(file, "write ");
+ if (ulFlagsPage & PAG_EXECUTE)
+ fprintf(file, "execute ");
+ if (ulFlagsPage & PAG_GUARD)
+ fprintf(file, "guard ");
+ if (ulFlagsPage & PAG_COMMIT)
+ fprintf(file, "committed ");
+ if (ulFlagsPage & PAG_SHARED)
+ fprintf(file, "shared ");
+ if (ulFlagsPage & PAG_FREE)
+ fprintf(file, "free ");
+ if (ulFlagsPage & PAG_BASE)
+ fprintf(file, "base ");
+ }
+ else if (arc == ERROR_INVALID_ADDRESS)
+ fprintf(file, "invalid");
+}
+
+/*
+ *@@ excPrintStackFrame:
+ * wrapper for dbgPrintStackFrame to format
+ * output stuff right.
+ *
+ *@@added V0.9.2 (2000-03-10) [umoeller]
+ *@@changed V0.9.12 (2001-05-12) [umoeller]: added seg:ofs to output always
+ */
+
+VOID excPrintStackFrame(FILE *file, // in: output log file
+ PSZ pszDescription, // in: description for stack frame (should be eight chars)
+ ULONG ulAddress) // in: address to debug
+{
+ APIRET arc = NO_ERROR;
+ HMODULE hmod1 = NULLHANDLE;
+ CHAR szMod1[2*CCHMAXPATH] = "unknown";
+ ULONG ulObject = 0,
+ ulOffset = 0;
+ fprintf(file,
+ " %-8s: %08lX ",
+ pszDescription,
+ ulAddress);
+ arc = DosQueryModFromEIP(&hmod1,
+ &ulObject,
+ sizeof(szMod1), szMod1,
+ &ulOffset,
+ ulAddress);
+
+ if (arc != NO_ERROR)
+ {
+ // error:
+ fprintf(file,
+ " %-8s Error: DosQueryModFromEIP returned %lu\n",
+ szMod1,
+ arc);
+ }
+ else
+ {
+ CHAR szFullName[2*CCHMAXPATH];
+
+ fprintf(file,
+ " %-8s %02lX:%08lX\n ",
+ szMod1,
+ ulObject + 1, // V0.9.12 (2001-05-12) [umoeller]
+ ulOffset); // V0.9.12 (2001-05-12) [umoeller]
+
+ DosQueryModuleName(hmod1, sizeof(szFullName), szFullName);
+ dbgPrintStackFrame(file,
+ szFullName,
+ ulObject,
+ ulOffset);
+
+ fprintf(file, "\n");
+
+ // make a 'tick' sound to let the user know we're still alive
+ DosBeep(2000, 10);
+ }
+}
+
+/*
+ *@@ excDumpStackFrames:
+ * called from excExplainException to dump the
+ * thread's stack frames. This calls excPrintStackFrame
+ * for each stack frame found.
+ *
+ *@@added V0.9.4 (2000-06-15) [umoeller]
+ */
+
+VOID excDumpStackFrames(FILE *file, // in: logfile from fopen()
+ PTIB ptib,
+ PCONTEXTRECORD pContextRec) // in: excpt info
+{
+ PULONG pulStackWord = 0;
+
+ fprintf(file, "\n\nStack frames:\n Address Module seg:ofs\n");
+
+ // first the trapping address itself
+ excPrintStackFrame(file,
+ "CS:EIP ",
+ pContextRec->ctx_RegEip);
+
+
+ pulStackWord = (PULONG)pContextRec->ctx_RegEbp;
+ /* if (pContextRec->ctx_RegEbp < pContextRec->ctx_RegEsp)
+ pulStackWord = (PULONG)(pContextRec->ctx_RegEbp & 0xFFFFFFF0);
+ else
+ pulStackWord = (PULONG)(pContextRec->ctx_RegEsp & 0xFFFFFFF0); */
+
+ while ( (pulStackWord != 0)
+ && (pulStackWord < (PULONG)ptib->tib_pstacklimit)
+ )
+ {
+ CHAR szAddress[20];
+
+ if (((ULONG)pulStackWord & 0x00000FFF) == 0x00000000)
+ {
+ // we're on a page boundary: check access
+ ULONG ulCountPages = 0x1000;
+ ULONG ulFlagsPage = 0;
+ APIRET arc = DosQueryMem((void *)pulStackWord,
+ &ulCountPages,
+ &ulFlagsPage);
+ if ( (arc != NO_ERROR)
+ || ( (arc == NO_ERROR)
+ && ( !( ((ulFlagsPage & (PAG_COMMIT|PAG_READ))
+ == (PAG_COMMIT|PAG_READ)
+ )
+ )
+ )
+ )
+ )
+ {
+ fprintf(file, "\n %08lX: ", (ULONG)pulStackWord);
+ fprintf(file, "Page inaccessible");
+ pulStackWord += 0x1000;
+ continue; // for
+ }
+ }
+
+ sprintf(szAddress, "%08lX",
+ (ULONG)pulStackWord);
+ excPrintStackFrame(file,
+ szAddress,
+ *(pulStackWord+1));
+ pulStackWord = (PULONG)*(pulStackWord);
+
+ if (pulStackWord == 0)
+ fprintf(file, "\n pulStackWord == 0");
+ else if (pulStackWord >= (PULONG)ptib->tib_pstacklimit)
+ fprintf(file, "\n pulStackWord >= (PULONG)ptib->tib_pstacklimit");
+ } // end while
+}
+
+/*
+ *@@ excExplainException:
+ * used by the exception handlers below to write
+ * LOTS of information about the exception into a logfile.
+ *
+ * This calls excPrintStackFrame for each stack frame.
+ *
+ *@@changed V0.9.0 [umoeller]: added support for application hook
+ *@@changed V0.9.0 (99-11-02) [umoeller]: added TID to dump
+ *@@changed V0.9.2 (2000-03-10) [umoeller]: now using excPrintStackFrame
+ *@@changed V0.9.3 (2000-05-03) [umoeller]: fixed crashes
+ *@@changed V0.9.6 (2000-11-06) [umoeller]: added more register dumps
+ *@@changed V0.9.13 (2001-06-19) [umoeller]: added global flag for whether this is running
+ *@@changed V0.9.16 (2001-11-02) [pr]: make object display signed
+ *@@changed V0.9.19 (2002-03-28) [umoeller]: added thread ordinal
+ */
+
+VOID excExplainException(FILE *file, // in: logfile from fopen()
+ PSZ pszHandlerName, // in: descriptive string
+ PEXCEPTIONREPORTRECORD pReportRec, // in: excpt info
+ PCONTEXTRECORD pContextRec) // in: excpt info
+{
+ ULONG aulBuf[3];
+ const char *pcszVersion = "unknown";
+
+ PTIB ptib = NULL;
+ PPIB ppib = NULL;
+ HMODULE hMod1, hMod2;
+ CHAR szMod1[CCHMAXPATH] = "unknown",
+ szMod2[CCHMAXPATH] = "unknown";
+ ULONG ulObjNum,
+ ulOffset;
+ ULONG ul;
+
+ ULONG ulOldPriority = 0x0100; // regular, delta 0
+
+ // raise global flag for whether this func is running
+ // V0.9.13 (2001-06-19) [umoeller]
+ G_ulExplainExceptionRunning++;
+
+ // raise this thread's priority, because this
+ // might take some time
+ if (DosGetInfoBlocks(&ptib, &ppib) == NO_ERROR)
+ if (ptib)
+ if (ptib->tib_ptib2)
+ {
+ ulOldPriority = ptib->tib_ptib2->tib2_ulpri;
+ DosSetPriority(PRTYS_THREAD,
+ PRTYC_REGULAR,
+ PRTYD_MAXIMUM,
+ 0); // current thread
+ }
+
+ // make some noise
+#ifndef __NOEXCEPTIONBEEPS__ // V0.9.19 (2002-04-17) [umoeller]
+ if (G_fBeepOnException)
+ {
+ DosBeep( 250, 30);
+ DosBeep( 500, 30);
+ DosBeep(1000, 30);
+ DosBeep(2000, 30);
+ DosBeep(4000, 30);
+ DosBeep(2000, 30);
+ DosBeep(1000, 30);
+ DosBeep( 500, 30);
+ DosBeep( 250, 30);
+ }
+#endif
+
+ // generic exception info
+ DosQuerySysInfo(QSV_VERSION_MAJOR, // 11
+ QSV_VERSION_MINOR, // 12
+ &aulBuf, sizeof(aulBuf));
+ // Warp 3 is reported as 20.30
+ // Warp 4 is reported as 20.40
+ // Aurora is reported as 20.45
+
+ if (aulBuf[0] == 20)
+ {
+ switch (aulBuf[1])
+ {
+ case 30: pcszVersion = "Warp 3"; break;
+ case 40: pcszVersion = "Warp 4"; break;
+ case 45: pcszVersion = "WSeB kernel"; break;
+ }
+ }
+ fprintf(file,
+ "Running OS/2 version: %u.%u (%s)\n",
+ aulBuf[0], // major
+ aulBuf[1],
+ pcszVersion);
+
+
+ // generic exception info
+ fprintf(file,
+ "\n%s:\n Exception type: %08lX\n Address: %08lX\n Params: ",
+ pszHandlerName,
+ pReportRec->ExceptionNum,
+ (ULONG)pReportRec->ExceptionAddress);
+ for (ul = 0; ul < pReportRec->cParameters; ul++)
+ {
+ fprintf(file, "%08lX ",
+ pReportRec->ExceptionInfo[ul]);
+ }
+
+ // now explain the exception in a bit more detail;
+ // depending on the exception, pReportRec->ExceptionInfo
+ // contains some useful data
+ switch (pReportRec->ExceptionNum)
+ {
+ case XCPT_ACCESS_VIOLATION:
+ fprintf(file, "\nXCPT_ACCESS_VIOLATION: ");
+ if (pReportRec->ExceptionInfo[0] & XCPT_READ_ACCESS)
+ fprintf(file, "Invalid read access from 0x%04lX:%08lX.\n",
+ pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]);
+ else if (pReportRec->ExceptionInfo[0] & XCPT_WRITE_ACCESS)
+ fprintf(file, "Invalid write access to 0x%04lX:%08lX.\n",
+ pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]);
+ else if (pReportRec->ExceptionInfo[0] & XCPT_SPACE_ACCESS)
+ fprintf(file, "Invalid space access at 0x%04lX.\n",
+ pReportRec->ExceptionInfo[1]);
+ else if (pReportRec->ExceptionInfo[0] & XCPT_LIMIT_ACCESS)
+ fprintf(file, "Invalid limit access occurred.\n");
+ else if (pReportRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS)
+ fprintf(file, "unknown at 0x%04lX:%08lX\n",
+ pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]);
+ fprintf(file,
+ "Explanation: An attempt was made to access a memory object which does\n"
+ " not belong to the current process. Most probable causes\n"
+ " for this are that an invalid pointer was used, there was\n"
+ " confusion with administering memory or error conditions \n"
+ " were not properly checked for.\n");
+ break;
+
+ case XCPT_INTEGER_DIVIDE_BY_ZERO:
+ fprintf(file, "\nXCPT_INTEGER_DIVIDE_BY_ZERO.\n");
+ fprintf(file,
+ "Explanation: An attempt was made to divide an integer value by zero,\n"
+ " which is not defined.\n");
+ break;
+
+ case XCPT_ILLEGAL_INSTRUCTION:
+ fprintf(file, "\nXCPT_ILLEGAL_INSTRUCTION.\n");
+ fprintf(file,
+ "Explanation: An attempt was made to execute an instruction that\n"
+ " is not defined on this machine's architecture.\n");
+ break;
+
+ case XCPT_PRIVILEGED_INSTRUCTION:
+ fprintf(file, "\nXCPT_PRIVILEGED_INSTRUCTION.\n");
+ fprintf(file,
+ "Explanation: An attempt was made to execute an instruction that\n"
+ " is not permitted in the current machine mode or that\n"
+ " the program had no permission to execute.\n");
+ break;
+
+ case XCPT_INTEGER_OVERFLOW:
+ fprintf(file, "\nXCPT_INTEGER_OVERFLOW.\n");
+ fprintf(file,
+ "Explanation: An integer operation generated a carry-out of the most\n"
+ " significant bit. This is a sign of an attempt to store\n"
+ " a value which does not fit into an integer variable.\n");
+ break;
+
+ default:
+ fprintf(file, "\nUnknown OS/2 exception number %d.\n", pReportRec->ExceptionNum);
+ fprintf(file, "Look this up in the OS/2 header files.\n");
+ break;
+ }
+
+ // V0.9.16 (2001-11-02) [pr]: We already got this info. above - this overwrites the
+ // original values before the priority change, which is rather confusing.
+ // if (DosGetInfoBlocks(&ptib, &ppib) == NO_ERROR)
+ {
+ /*
+ * process info:
+ *
+ */
+
+ if ((ptib) && (ppib)) // (99-11-01) [umoeller]
+ {
+ if (pContextRec->ContextFlags & CONTEXT_CONTROL)
+ {
+ // get the main module
+ hMod1 = ppib->pib_hmte;
+ DosQueryModuleName(hMod1,
+ sizeof(szMod1),
+ szMod1);
+
+ // get the trapping module
+ DosQueryModFromEIP(&hMod2,
+ &ulObjNum,
+ sizeof(szMod2),
+ szMod2,
+ &ulOffset,
+ pContextRec->ctx_RegEip);
+ DosQueryModuleName(hMod2,
+ sizeof(szMod2),
+ szMod2);
+ }
+
+ fprintf(file,
+ "\nProcess information:"
+ "\n Process ID: 0x%lX"
+ "\n Process module: 0x%lX (%s)"
+ "\n Trapping module: 0x%lX (%s)"
+ "\n Object: %ld\n", // V0.9.16 (2001-11-02) [pr]: make this display signed
+ ppib->pib_ulpid,
+ hMod1, szMod1,
+ hMod2, szMod2,
+ ulObjNum);
+
+ fprintf(file,
+ "\nTrapping thread information:"
+ "\n Thread ID: 0x%lX (%lu)"
+ "\n Thread slot ID: 0x%lX (%lu)" // added V0.9.19 (2002-03-28) [umoeller]
+ "\n Priority: 0x%lX\n",
+ ptib->tib_ptib2->tib2_ultid, ptib->tib_ptib2->tib2_ultid,
+ ptib->tib_ordinal, ptib->tib_ordinal,
+ ulOldPriority);
+ }
+ else
+ fprintf(file, "\nProcess information was not available.");
+
+ /*
+ * now call the hook, if one has been defined,
+ * so that the application can write additional
+ * information to the traplog (V0.9.0)
+ */
+
+ if (G_pfnExcHook)
+ G_pfnExcHook(file, ptib, ulOldPriority); // V0.9.16 (2001-12-02) [pr]
+
+ // *** registers
+
+ fprintf(file, "\nRegisters:");
+ if (pContextRec->ContextFlags & CONTEXT_INTEGER)
+ {
+ // DS the following 4 added V0.9.6 (2000-11-06) [umoeller]
+ fprintf(file, "\n DS = %08lX ", pContextRec->ctx_SegDs);
+ excDescribePage(file, pContextRec->ctx_SegDs);
+ // ES
+ fprintf(file, "\n ES = %08lX ", pContextRec->ctx_SegEs);
+ excDescribePage(file, pContextRec->ctx_SegEs);
+ // FS
+ fprintf(file, "\n FS = %08lX ", pContextRec->ctx_SegFs);
+ excDescribePage(file, pContextRec->ctx_SegFs);
+ // GS
+ fprintf(file, "\n GS = %08lX ", pContextRec->ctx_SegGs);
+ excDescribePage(file, pContextRec->ctx_SegGs);
+
+ // EAX
+ fprintf(file, "\n EAX = %08lX ", pContextRec->ctx_RegEax);
+ excDescribePage(file, pContextRec->ctx_RegEax);
+ // EBX
+ fprintf(file, "\n EBX = %08lX ", pContextRec->ctx_RegEbx);
+ excDescribePage(file, pContextRec->ctx_RegEbx);
+ // ECX
+ fprintf(file, "\n ECX = %08lX ", pContextRec->ctx_RegEcx);
+ excDescribePage(file, pContextRec->ctx_RegEcx);
+ // EDX
+ fprintf(file, "\n EDX = %08lX ", pContextRec->ctx_RegEdx);
+ excDescribePage(file, pContextRec->ctx_RegEdx);
+ // ESI
+ fprintf(file, "\n ESI = %08lX ", pContextRec->ctx_RegEsi);
+ excDescribePage(file, pContextRec->ctx_RegEsi);
+ // EDI
+ fprintf(file, "\n EDI = %08lX ", pContextRec->ctx_RegEdi);
+ excDescribePage(file, pContextRec->ctx_RegEdi);
+ fprintf(file, "\n");
+ }
+ else
+ fprintf(file, " not available\n");
+
+ if (pContextRec->ContextFlags & CONTEXT_CONTROL)
+ {
+
+ // *** instruction
+
+ fprintf(file, "Instruction pointer (where exception occured):\n CS:EIP = %04lX:%08lX ",
+ pContextRec->ctx_SegCs,
+ pContextRec->ctx_RegEip);
+ excDescribePage(file, pContextRec->ctx_RegEip);
+
+ // *** CPU flags
+
+ fprintf(file, "\n EFLAGS = %08lX", pContextRec->ctx_EFlags);
+
+ /*
+ * stack:
+ *
+ */
+
+ fprintf(file, "\nStack:\n Base: %08lX\n Limit: %08lX",
+ (ULONG)(ptib ? ptib->tib_pstack : 0),
+ (ULONG)(ptib ? ptib->tib_pstacklimit : 0));
+ fprintf(file, "\n SS:ESP = %04lX:%08lX ",
+ pContextRec->ctx_SegSs,
+ pContextRec->ctx_RegEsp);
+ excDescribePage(file, pContextRec->ctx_RegEsp);
+
+ fprintf(file, "\n EBP = %08lX ", pContextRec->ctx_RegEbp);
+ excDescribePage(file, pContextRec->ctx_RegEbp);
+
+ /*
+ * stack dump:
+ */
+
+ if (ptib != 0)
+ {
+ excDumpStackFrames(file, ptib, pContextRec);
+ }
+ }
+ }
+ fprintf(file, "\n");
+
+ // reset old priority
+ DosSetPriority(PRTYS_THREAD,
+ (ulOldPriority & 0x0F00) >> 8,
+ (UCHAR)ulOldPriority,
+ 0); // current thread
+
+ // lower global flag again V0.9.13 (2001-06-19) [umoeller]
+ G_ulExplainExceptionRunning--;
+}
+
+/* ******************************************************************
+ *
+ * Exported routines
+ *
+ ********************************************************************/
+
+/*
+ *@@ excRegisterHooks:
+ * this registers hooks which get called for
+ * exception handlers. You can set any of the
+ * hooks to NULL for safe defaults (see top of
+ * except.c for details). You can set none,
+ * one, or both of the hooks, and you can call
+ * this function several times.
+ *
+ * Both hooks get called whenever an exception
+ * occurs, so there better be no bugs in these
+ * routines. ;-) They only get called from
+ * within excHandlerLoud (because excHandlerQuiet
+ * writes no trap logs).
+ *
+ * The hooks are as follows:
+ *
+ * -- pfnExcOpenFileNew gets called to open
+ * the trap log file. This must return a FILE*
+ * pointer from fopen(). If this is not defined,
+ * ?:\TRAP.LOG is used. Use this to specify a
+ * different file and have some notes written
+ * into it before the actual exception info.
+ *
+ * -- pfnExcHookNew gets called while the trap log
+ * is being written. At this point,
+ * the following info has been written into
+ * the trap log already:
+ * -- exception type/address block
+ * -- exception explanation
+ * -- process information
+ *
+ * _After_ the hook, the exception handler
+ * continues with the "Registers" information
+ * and stack dump/analysis.
+ *
+ * Use this hook to write additional application
+ * info into the trap log, such as the state
+ * of your own threads and mutexes.
+ *
+ * -- pfnExcHookError gets called when the TRY_* macros
+ * fail to install an exception handler (when
+ * DosSetExceptionHandler fails). I've never seen
+ * this happen.
+ *
+ *@@added V0.9.0 [umoeller]
+ *@@changed V0.9.2 (2000-03-10) [umoeller]: pfnExcHookError added
+ */
+
+VOID excRegisterHooks(PFNEXCOPENFILE pfnExcOpenFileNew,
+ PFNEXCHOOK pfnExcHookNew,
+ PFNEXCHOOKERROR pfnExcHookError,
+ BOOL fBeepOnExceptionNew)
+{
+ // adjust the global variables
+ G_pfnExcOpenFile = pfnExcOpenFileNew;
+ G_pfnExcHook = pfnExcHookNew;
+ G_pfnExcHookError = pfnExcHookError;
+ G_fBeepOnException = fBeepOnExceptionNew;
+}
+
+/*
+ *@@ excHandlerLoud:
+ * this is the "sophisticated" exception handler;
+ * which gives forth a loud sequence of beeps thru the
+ * speaker, writes a trap log and then returns back
+ * to the thread to continue execution, i.e. the
+ * default OS/2 exception handler will never get
+ * called.
+ *
+ * This requires a setjmp() call on
+ * EXCEPTIONREGISTRATIONRECORD2.jmpThread before
+ * being installed. The TRY_LOUD macro will take
+ * care of this for you (see except.c).
+ *
+ * This intercepts the following exceptions (see
+ * the OS/2 Control Program Reference for details):
+ *
+ * -- XCPT_ACCESS_VIOLATION (traps 0x0d, 0x0e)
+ * -- XCPT_INTEGER_DIVIDE_BY_ZERO (trap 0)
+ * -- XCPT_ILLEGAL_INSTRUCTION (trap 6)
+ * -- XCPT_PRIVILEGED_INSTRUCTION
+ * -- XCPT_INTEGER_OVERFLOW (trap 4)
+ *
+ * For these exceptions, we call the functions in debug.c
+ * to try to find debug code or SYM file information about
+ * what source code corresponds to the error.
+ *
+ * See excRegisterHooks for the default setup of this.
+ *
+ * Note that to get meaningful debugging information
+ * in this handler's traplog, you need the following:
+ *
+ * a) have a MAP file created at link time (/MAP)
+ *
+ * b) convert the MAP to a SYM file using MAPSYM
+ *
+ * c) put the SYM file in the same directory of
+ * the module (EXE or DLL). This must have the
+ * same filestem as the module.
+ *
+ * All other exceptions are passed to the next handler
+ * in the exception handler chain. This might be the
+ * C/C++ compiler handler or the default OS/2 handler,
+ * which will probably terminate the process.
+ *
+ *@@changed V0.9.0 [umoeller]: added support for thread termination
+ *@@changed V0.9.2 (2000-03-10) [umoeller]: switched date format to ISO
+ *@@changed V0.9.19 (2002-05-07) [umoeller]: added EXCEPTIONREPORTRECORD info so that catch block can check that
+ */
+
+ULONG _System excHandlerLoud(PEXCEPTIONREPORTRECORD pReportRec,
+ PEXCEPTIONREGISTRATIONRECORD2 pRegRec2,
+ PCONTEXTRECORD pContextRec,
+ PVOID pv)
+{
+ /* From the VAC++3 docs:
+ * "The first thing an exception handler should do is check the
+ * exception flags. If EH_EXIT_UNWIND is set, meaning
+ * the thread is ending, the handler tells the operating system
+ * to pass the exception to the next exception handler. It does the
+ * same if the EH_UNWINDING flag is set, the flag that indicates
+ * this exception handler is being removed.
+ * The EH_NESTED_CALL flag indicates whether the exception
+ * occurred within an exception handler. If the handler does
+ * not check this flag, recursive exceptions could occur until
+ * there is no stack remaining."
+ * So for all these conditions, we exit immediately.
+ */
+
+ if (pReportRec->fHandlerFlags & EH_EXIT_UNWIND)
+ return (XCPT_CONTINUE_SEARCH);
+ if (pReportRec->fHandlerFlags & EH_UNWINDING)
+ return (XCPT_CONTINUE_SEARCH);
+ if (pReportRec->fHandlerFlags & EH_NESTED_CALL)
+ return (XCPT_CONTINUE_SEARCH);
+
+ switch (pReportRec->ExceptionNum)
+ {
+ case XCPT_ACCESS_VIOLATION:
+ case XCPT_INTEGER_DIVIDE_BY_ZERO:
+ case XCPT_ILLEGAL_INSTRUCTION:
+ case XCPT_PRIVILEGED_INSTRUCTION:
+ case XCPT_INVALID_LOCK_SEQUENCE:
+ case XCPT_INTEGER_OVERFLOW:
+ {
+ // "real" exceptions:
+ FILE *file;
+
+ // open traplog file;
+ if (G_pfnExcOpenFile)
+ // hook defined for this: call it
+ file = (*G_pfnExcOpenFile)();
+ else
+ {
+ CHAR szFileName[100];
+ // no hook defined: open some
+ // default traplog file in root directory of
+ // boot drive
+ sprintf(szFileName, "%c:\\trap.log", doshQueryBootDrive());
+ file = fopen(szFileName, "a");
+
+ if (file)
+ {
+ DATETIME DT;
+ DosGetDateTime(&DT);
+ fprintf(file,
+ "\nTrap message -- Date: %04d-%02d-%02d, Time: %02d:%02d:%02d\n",
+ DT.year, DT.month, DT.day,
+ DT.hours, DT.minutes, DT.seconds);
+ fprintf(file, "------------------------------------------------\n");
+
+ }
+ }
+
+ // write error log
+ excExplainException(file,
+ "excHandlerLoud",
+ pReportRec,
+ pContextRec);
+ fclose(file);
+
+ // copy report rec to user buffer
+ // V0.9.19 (2002-05-07) [umoeller]
+ memcpy(&pRegRec2->err,
+ pReportRec,
+ sizeof(EXCEPTIONREPORTRECORD));
+
+ // jump back to failing routine
+ longjmp(pRegRec2->jmpThread, pReportRec->ExceptionNum);
+ break; }
+ }
+
+ // not handled
+ return (XCPT_CONTINUE_SEARCH);
+}
+
+/*
+ *@@ excHandlerQuiet:
+ * "quiet" xcpt handler, which simply suppresses exceptions;
+ * this is useful for certain error-prone functions, where
+ * exceptions are likely to appear, for example used by
+ * wpshCheckObject to implement a fail-safe SOM object check.
+ *
+ * This does _not_ write an error log and makes _no_ sound.
+ * This simply jumps back to the trapping thread or
+ * calls EXCEPTIONREGISTRATIONRECORD2.pfnOnKill.
+ *
+ * Other than that, this behaves like excHandlerLoud.
+ *
+ * This is best registered thru the TRY_QUIET macro
+ * (new with V0.84, described in except.c), which
+ * does the necessary setup.
+ *
+ *@@changed V0.9.0 [umoeller]: added support for thread termination
+ *@@changed V0.9.19 (2002-05-07) [umoeller]: added EXCEPTIONREPORTRECORD info so that catch block can check that
+ */
+
+ULONG _System excHandlerQuiet(PEXCEPTIONREPORTRECORD pReportRec,
+ PEXCEPTIONREGISTRATIONRECORD2 pRegRec2,
+ PCONTEXTRECORD pContextRec,
+ PVOID pv)
+{
+ if (pReportRec->fHandlerFlags & EH_EXIT_UNWIND)
+ return (XCPT_CONTINUE_SEARCH);
+ if (pReportRec->fHandlerFlags & EH_UNWINDING)
+ return (XCPT_CONTINUE_SEARCH);
+ if (pReportRec->fHandlerFlags & EH_NESTED_CALL)
+ return (XCPT_CONTINUE_SEARCH);
+
+ switch (pReportRec->ExceptionNum)
+ {
+ case XCPT_ACCESS_VIOLATION:
+ case XCPT_INTEGER_DIVIDE_BY_ZERO:
+ case XCPT_ILLEGAL_INSTRUCTION:
+ case XCPT_PRIVILEGED_INSTRUCTION:
+ case XCPT_INVALID_LOCK_SEQUENCE:
+ case XCPT_INTEGER_OVERFLOW:
+ // write excpt explanation only if the
+ // resp. debugging #define is set (setup.h)
+ #ifdef DEBUG_WRITEQUIETEXCPT
+ {
+ FILE *file = excOpenTraplogFile();
+ excExplainException(file,
+ "excHandlerQuiet",
+ pReportRec,
+ pContextRec);
+ fclose(file);
+ }
+ #endif
+
+ // copy report rec to user buffer
+ // V0.9.19 (2002-05-07) [umoeller]
+ memcpy(&pRegRec2->err,
+ pReportRec,
+ sizeof(EXCEPTIONREPORTRECORD));
+
+ // jump back to failing routine
+ longjmp(pRegRec2->jmpThread, pReportRec->ExceptionNum);
+ break;
+
+ default:
+ break;
+ }
+
+ return (XCPT_CONTINUE_SEARCH);
+}
+
+
diff --git a/sal/osl/os2/file.cxx b/sal/osl/os2/file.cxx
new file mode 100644
index 000000000000..2e668d23d638
--- /dev/null
+++ b/sal/osl/os2/file.cxx
@@ -0,0 +1,3129 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+/************************************************************************
+ * ToDo
+ *
+ * Fix osl_getCanonicalName
+ *
+ * - Fix: check for corresponding struct sizes in exported functions
+ * - check size/use of oslDirectory
+ * - check size/use of oslDirectoryItem
+ * - check size/use of oslFileStatus
+ * - check size/use of oslVolumeDeviceHandle
+ * - check size/use of oslVolumeInfo
+ * - check size/use of oslFileHandle
+ ***********************************************************************/
+
+#define INCL_DOSDEVIOCTL // OS2 device definitions
+
+#include "system.h"
+#include <rtl/alloc.h>
+
+#include "osl/file.hxx"
+
+
+#include <sal/types.h>
+#include <osl/thread.h>
+#include <osl/diagnose.h>
+#include "file_error_transl.h"
+#include <osl/time.h>
+
+#ifndef _FILE_URL_H_
+#include "file_url.h"
+#endif
+
+#include "file_path_helper.hxx"
+#include "uunxapi.hxx"
+
+#ifndef _STRING_H_
+#include <string.h>
+#endif
+
+#ifndef _CTYPE_H_
+#include <ctype.h>
+#endif
+
+#ifndef _WCHAR_H_
+#include <wchar.h>
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+ extern void debug_ustring(rtl_uString*);
+#endif
+
+
+#ifdef DEBUG_OSL_FILE
+# define PERROR( a, b ) perror( a ); fprintf( stderr, b )
+#else
+# define PERROR( a, b )
+#endif
+
+extern "C" oslFileHandle osl_createFileHandleFromFD( int fd );
+
+ struct errentry errtable[] = {
+ { NO_ERROR, osl_File_E_None }, /* 0 */
+ { ERROR_INVALID_FUNCTION, osl_File_E_INVAL }, /* 1 */
+ { ERROR_FILE_NOT_FOUND, osl_File_E_NOENT }, /* 2 */
+ { ERROR_PATH_NOT_FOUND, osl_File_E_NOENT }, /* 3 */
+ { ERROR_TOO_MANY_OPEN_FILES, osl_File_E_MFILE }, /* 4 */
+ { ERROR_ACCESS_DENIED, osl_File_E_ACCES }, /* 5 */
+ { ERROR_INVALID_HANDLE, osl_File_E_BADF }, /* 6 */
+ { ERROR_ARENA_TRASHED, osl_File_E_NOMEM }, /* 7 */
+ { ERROR_NOT_ENOUGH_MEMORY, osl_File_E_NOMEM }, /* 8 */
+ { ERROR_INVALID_BLOCK, osl_File_E_NOMEM }, /* 9 */
+ { ERROR_BAD_ENVIRONMENT, osl_File_E_2BIG }, /* 10 */
+ { ERROR_BAD_FORMAT, osl_File_E_NOEXEC }, /* 11 */
+ { ERROR_INVALID_ACCESS, osl_File_E_INVAL }, /* 12 */
+ { ERROR_INVALID_DATA, osl_File_E_INVAL }, /* 13 */
+ { ERROR_INVALID_DRIVE, osl_File_E_NOENT }, /* 15 */
+ { ERROR_CURRENT_DIRECTORY, osl_File_E_ACCES }, /* 16 */
+ { ERROR_NOT_SAME_DEVICE, osl_File_E_XDEV }, /* 17 */
+ { ERROR_NO_MORE_FILES, osl_File_E_NOENT }, /* 18 */
+ { ERROR_NOT_READY, osl_File_E_NOTREADY }, /* 21 */
+ { ERROR_LOCK_VIOLATION, osl_File_E_ACCES }, /* 33 */
+ { ERROR_BAD_NETPATH, osl_File_E_NOENT }, /* 53 */
+ { ERROR_NETWORK_ACCESS_DENIED, osl_File_E_ACCES }, /* 65 */
+ { ERROR_BAD_NET_NAME, osl_File_E_NOENT }, /* 67 */
+ { ERROR_FILE_EXISTS, osl_File_E_EXIST }, /* 80 */
+ { ERROR_CANNOT_MAKE, osl_File_E_ACCES }, /* 82 */
+ { ERROR_FAIL_I24, osl_File_E_ACCES }, /* 83 */
+ { ERROR_INVALID_PARAMETER, osl_File_E_INVAL }, /* 87 */
+ { ERROR_NO_PROC_SLOTS, osl_File_E_AGAIN }, /* 89 */
+ { ERROR_DRIVE_LOCKED, osl_File_E_ACCES }, /* 108 */
+ { ERROR_BROKEN_PIPE, osl_File_E_PIPE }, /* 109 */
+ { ERROR_DISK_FULL, osl_File_E_NOSPC }, /* 112 */
+ { ERROR_INVALID_TARGET_HANDLE, osl_File_E_BADF }, /* 114 */
+ { ERROR_INVALID_HANDLE, osl_File_E_INVAL }, /* 124 */
+ { ERROR_WAIT_NO_CHILDREN, osl_File_E_CHILD }, /* 128 */
+ { ERROR_CHILD_NOT_COMPLETE, osl_File_E_CHILD }, /* 129 */
+ { ERROR_DIRECT_ACCESS_HANDLE, osl_File_E_BADF }, /* 130 */
+ { ERROR_NEGATIVE_SEEK, osl_File_E_INVAL }, /* 131 */
+ { ERROR_SEEK_ON_DEVICE, osl_File_E_ACCES }, /* 132 */
+ { ERROR_DIR_NOT_EMPTY, osl_File_E_NOTEMPTY }, /* 145 */
+ { ERROR_NOT_LOCKED, osl_File_E_ACCES }, /* 158 */
+ { ERROR_BAD_PATHNAME, osl_File_E_NOENT }, /* 161 */
+ { ERROR_MAX_THRDS_REACHED, osl_File_E_AGAIN }, /* 164 */
+ { ERROR_LOCK_FAILED, osl_File_E_ACCES }, /* 167 */
+ { ERROR_ALREADY_EXISTS, osl_File_E_EXIST }, /* 183 */
+ { ERROR_FILENAME_EXCED_RANGE, osl_File_E_NOENT }, /* 206 */
+ { ERROR_NESTING_NOT_ALLOWED, osl_File_E_AGAIN }, /* 215 */
+ { ERROR_DIRECTORY, osl_File_E_NOENT }, /* 267 */
+ //{ ERROR_NOT_ENOUGH_QUOTA, osl_File_E_NOMEM } /* 1816 */
+ };
+
+ #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
+
+ //#####################################################
+ oslFileError MapError(APIRET dwError)
+ {
+ for (int i = 0; i < ELEMENTS_OF_ARRAY(errtable); ++i )
+ {
+ if (dwError == errtable[i].oscode)
+ return static_cast<oslFileError>(errtable[i].errnocode);
+ }
+ return osl_File_E_INVAL;
+ }
+
+/******************************************************************************
+ *
+ * static members
+ *
+ *****************************************************************************/
+
+static const char * pFileLockEnvVar = (char *) -1;
+
+
+/******************************************************************************
+ *
+ * C-String Function Declarations
+ *
+ *****************************************************************************/
+
+static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask);
+static oslFileError osl_psz_removeFile(const sal_Char* pszPath);
+static oslFileError osl_psz_createDirectory(const sal_Char* pszPath);
+static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath);
+static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
+static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
+static oslFileError osl_psz_setFileTime(const sal_Char* strFilePath, const TimeValue* pCreationTime, const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime);
+
+
+/******************************************************************************
+ *
+ * Static Module Utility Function Declarations
+ *
+ *****************************************************************************/
+
+static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists);
+static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID);
+static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName);
+static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode);
+static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
+rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr);
+
+/******************************************************************************
+ *
+ * Non-Static Utility Function Declarations
+ *
+ *****************************************************************************/
+
+extern "C" int UnicodeToText( char *, size_t, const sal_Unicode *, sal_Int32 );
+extern "C" int TextToUnicode(
+ const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size);
+
+/******************************************************************************
+ *
+ * 'removeable device' aka floppy functions
+ *
+ *****************************************************************************/
+
+static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath);
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy);
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy);
+
+#ifdef DEBUG_OSL_FILE
+static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* hFloppy);
+#endif
+
+/**********************************************
+ * _osl_openLocalRoot
+ * enumerate available drives
+ *********************************************/
+static oslFileError _osl_openLocalRoot( rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
+{
+ rtl_uString *ustrSystemPath = NULL;
+ oslFileError error;
+
+ if ( !pDirectory )
+ return osl_File_E_INVAL;
+
+ *pDirectory = NULL;
+
+ error = osl_getSystemPathFromFileURL_Ex( strDirectoryPath, &ustrSystemPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ /* create and initialize impl structure */
+ DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) );
+ if( pDirImpl )
+ {
+ ULONG ulDriveNum;
+ APIRET rc;
+ pDirImpl->uType = DIRECTORYTYPE_LOCALROOT;
+ pDirImpl->ustrPath = ustrSystemPath;
+ rc = DosQueryCurrentDisk (&ulDriveNum, &pDirImpl->ulDriveMap);
+ pDirImpl->pDirStruct = 0;
+ pDirImpl->ulNextDrive = 1;
+ pDirImpl->ulNextDriveMask = 1;
+
+ // determine number of floppy-drives
+ BYTE nFloppies;
+ rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY );
+ if (nFloppies == 0) {
+ // if no floppies, start with 3rd drive (C:)
+ pDirImpl->ulNextDrive = 3;
+ pDirImpl->ulNextDriveMask <<= 2;
+ } else if (nFloppies == 1) {
+ // mask drive B (second bit) in this case
+ pDirImpl->ulDriveMap &= ~0x02;
+ }
+ *pDirectory = (oslDirectory) pDirImpl;
+ return osl_File_E_None;
+ }
+ else
+ {
+ errno = osl_File_E_NOMEM;
+ }
+
+ }
+
+ rtl_uString_release( ustrSystemPath );
+ return error;
+}
+
+/**********************************************
+ * _osl_getNextDrive
+ *********************************************/
+static oslFileError SAL_CALL _osl_getNextDrive(
+ oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
+{
+ DirectoryImpl *pDirImpl = (DirectoryImpl *)Directory;
+ DirectoryItem_Impl *pItemImpl = NULL;
+ rtl_uString * ustrDrive = NULL;
+ BOOL fSuccess;
+ char buffer[3];
+
+ uHint = uHint; /* avoid warnings */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+
+ *pItem = NULL;
+
+ if ( !pDirImpl )
+ return osl_File_E_INVAL;
+
+ while( pDirImpl->ulNextDrive <= 26)
+ {
+ // exit if bit==1 -> drive found
+ if (pDirImpl->ulDriveMap & pDirImpl->ulNextDriveMask) {
+
+ /* convert file name to unicode */
+ buffer[0] = '@' + pDirImpl->ulNextDrive;
+ buffer[1] = ':';
+ buffer[2] = 0;
+
+ pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl));
+ if ( !pItemImpl )
+ return osl_File_E_NOMEM;
+
+ memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_DRIVE;
+ pItemImpl->nRefCount = 1;
+
+ rtl_string2UString( &pItemImpl->ustrDrive, buffer, 3,
+ osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(pItemImpl->ustrDrive != 0);
+
+ /* use drive as directory item */
+ *pItem = (oslDirectoryItem) pItemImpl;
+ }
+ // scan next bit position
+ pDirImpl->ulNextDrive++;
+ pDirImpl->ulNextDriveMask <<= 1;
+
+ if (*pItem) // item assigned, return now.
+ return osl_File_E_None;
+ }
+
+ // no more items
+ return osl_File_E_NOENT;
+}
+
+/**********************************************
+ * _osl_readdir_impl_
+ *
+ * readdir wrapper, filters out "." and ".."
+ * on request
+ *********************************************/
+
+static struct dirent* _osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir)
+{
+ struct dirent* pdirent;
+
+ while ((pdirent = readdir(pdir)) != NULL)
+ {
+ if (bFilterLocalAndParentDir &&
+ ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
+ continue;
+ else
+ break;
+ }
+
+ return pdirent;
+}
+
+/*******************************************************************
+ * osl_openDirectory
+ ******************************************************************/
+
+oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory)
+{
+ rtl_uString* ustrSystemPath = NULL;
+ oslFileError eRet;
+
+ char path[PATH_MAX];
+
+ OSL_ASSERT(ustrDirectoryURL && (ustrDirectoryURL->length > 0));
+ OSL_ASSERT(pDirectory);
+
+ if (0 == ustrDirectoryURL->length )
+ return osl_File_E_INVAL;
+
+ if ( 0 == rtl_ustr_compareIgnoreAsciiCase( ustrDirectoryURL->buffer, (const sal_Unicode*)L"file:///" ) )
+ return _osl_openLocalRoot( ustrDirectoryURL, pDirectory );
+
+ /* convert file URL to system path */
+ eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False);
+
+ if( osl_File_E_None != eRet )
+ return eRet;
+
+ osl_systemPathRemoveSeparator(ustrSystemPath);
+
+ /* convert unicode path to text */
+ if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length ) )
+ {
+ // if only the drive is specified (x:), add a \ (x:\) otherwise current
+ // directory is browsed instead of root.
+ if (strlen( path) == 2 && path[1] == ':')
+ strcat( path, "\\");
+ /* open directory */
+ DIR *pdir = opendir( path );
+
+ if( pdir )
+ {
+ /* create and initialize impl structure */
+ DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) );
+
+ if( pDirImpl )
+ {
+ pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM;
+ pDirImpl->pDirStruct = pdir;
+ pDirImpl->ustrPath = ustrSystemPath;
+
+ *pDirectory = (oslDirectory) pDirImpl;
+ return osl_File_E_None;
+ }
+ else
+ {
+ errno = ENOMEM;
+ closedir( pdir );
+ }
+ }
+ else
+ /* should be removed by optimizer in product version */
+ PERROR( "osl_openDirectory", path );
+ }
+
+ rtl_uString_release( ustrSystemPath );
+
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+}
+
+
+/****************************************************************************
+ * osl_getNextDirectoryItem
+ ***************************************************************************/
+
+oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 uHint)
+{
+ DirectoryImpl* pDirImpl = (DirectoryImpl*)Directory;
+ DirectoryItem_Impl *pItemImpl = NULL;
+ rtl_uString* ustrFileName = NULL;
+ rtl_uString* ustrFilePath = NULL;
+ struct dirent* pEntry;
+
+ OSL_ASSERT(Directory);
+ OSL_ASSERT(pItem);
+
+ if ((NULL == Directory) || (NULL == pItem))
+ return osl_File_E_INVAL;
+
+ if ( pDirImpl->uType == DIRECTORYTYPE_LOCALROOT)
+ return _osl_getNextDrive( Directory, pItem, uHint );
+
+ pEntry = _osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
+
+ if (NULL == pEntry)
+ return osl_File_E_NOENT;
+
+ pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl));
+ if ( !pItemImpl )
+ return osl_File_E_NOMEM;
+
+ memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_FILE;
+ pItemImpl->nRefCount = 1;
+ pItemImpl->d_attr = pEntry->d_attr;
+
+ /* convert file name to unicode */
+ rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
+ osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(ustrFileName != 0);
+
+ osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &pItemImpl->ustrFilePath);
+ rtl_uString_release( ustrFileName );
+
+ *pItem = (oslDirectoryItem)pItemImpl;
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_closeDirectory */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
+{
+ DirectoryImpl* pDirImpl = (DirectoryImpl*) Directory;
+ oslFileError err = osl_File_E_None;
+
+ OSL_ASSERT( Directory );
+
+ if( NULL == pDirImpl )
+ return osl_File_E_INVAL;
+
+ switch ( pDirImpl->uType )
+ {
+ case DIRECTORYTYPE_FILESYSTEM:
+ if( closedir( pDirImpl->pDirStruct ) )
+ err = oslTranslateFileError(OSL_FET_ERROR, errno);
+ break;
+ case DIRECTORYTYPE_LOCALROOT:
+ err = osl_File_E_None;
+ break;
+#if 0
+ case DIRECTORYTYPE_NETROOT:
+ {
+ DWORD err = WNetCloseEnum(pDirImpl->hDirectory);
+ eError = (err == NO_ERROR) ? osl_File_E_None : MapError(err);
+ }
+ break;
+#endif
+ default:
+ OSL_ENSURE( 0, "Invalid directory type" );
+ break;
+ }
+
+ /* cleanup members */
+ rtl_uString_release( pDirImpl->ustrPath );
+
+ rtl_freeMemory( pDirImpl );
+
+ return err;
+}
+
+/****************************************************************************/
+/* osl_getDirectoryItem */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
+{
+ rtl_uString* strSysFilePath = NULL;
+ oslFileError error = osl_File_E_INVAL;
+ ULONG dwPathType;
+ PATHTYPE type = PATHTYPE_FILE;
+
+ OSL_ASSERT(ustrFileURL);
+ OSL_ASSERT(pItem);
+
+ /* Assume failure */
+ if ( !pItem )
+ return osl_File_E_INVAL;
+ *pItem = NULL;
+
+ if (0 == ustrFileURL->length || NULL == pItem)
+ return osl_File_E_INVAL;
+
+ error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &strSysFilePath, sal_False);
+
+ if (osl_File_E_None != error)
+ return error;
+
+ dwPathType = IsValidFilePath( strSysFilePath->buffer, NULL, VALIDATEPATH_NORMAL );
+
+ if ( dwPathType & PATHTYPE_IS_VOLUME )
+ type = PATHTYPE_VOLUME;
+ else if ( dwPathType & PATHTYPE_IS_SERVER )
+ type = PATHTYPE_NETSERVER;
+ else
+ type = PATHTYPE_FILE;
+
+ switch ( type )
+ {
+ case PATHTYPE_NETSERVER:
+ {
+ DirectoryItem_Impl* pItemImpl =
+ reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+
+ if ( !pItemImpl )
+ error = osl_File_E_NOMEM;
+
+ if ( osl_File_E_None == error )
+ {
+ memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_SERVER;
+ pItemImpl->nRefCount = 1;
+ rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath );
+
+ *pItem = pItemImpl;
+ }
+ }
+ break;
+ case PATHTYPE_VOLUME:
+ {
+ DirectoryItem_Impl* pItemImpl =
+ reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+
+ if ( !pItemImpl )
+ error = osl_File_E_NOMEM;
+
+ if ( osl_File_E_None == error )
+ {
+ memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_DRIVE;
+ pItemImpl->nRefCount = 1;
+ rtl_uString_assign( &pItemImpl->ustrDrive, strSysFilePath );
+
+ if ( pItemImpl->ustrDrive->buffer[pItemImpl->ustrDrive->length-1] != sal_Unicode('\\') )
+ rtl_uString_newConcat( &pItemImpl->ustrDrive,
+ pItemImpl->ustrDrive, rtl::OUString::createFromAscii( "\\" ).pData);
+
+ *pItem = pItemImpl;
+ }
+ }
+ break;
+ default:
+ case PATHTYPE_FILE:
+ {
+ if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' )
+ rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 );
+
+ if (0 == access_u(strSysFilePath, F_OK))
+ {
+ DirectoryItem_Impl *pItemImpl =
+ reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+
+ memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_FILE;
+ pItemImpl->nRefCount = 1;
+ rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath );
+
+ *pItem = pItemImpl;
+ }
+ else
+ error = oslTranslateFileError(OSL_FET_ERROR, errno);
+ }
+ break;
+ }
+
+ if ( strSysFilePath )
+ rtl_uString_release( strSysFilePath );
+
+ return error;
+}
+
+/****************************************************************************/
+/* osl_acquireDirectoryItem */
+/****************************************************************************/
+
+oslFileError osl_acquireDirectoryItem( oslDirectoryItem Item )
+{
+ OSL_ASSERT( Item );
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ pItemImpl->nRefCount++;
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_releaseDirectoryItem */
+/****************************************************************************/
+
+oslFileError osl_releaseDirectoryItem( oslDirectoryItem Item )
+{
+ OSL_ASSERT( Item );
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ if ( ! --pItemImpl->nRefCount )
+ {
+ if (pItemImpl->ustrFilePath)
+ rtl_uString_release( pItemImpl->ustrFilePath );
+ if (pItemImpl->ustrDrive)
+ rtl_uString_release( pItemImpl->ustrDrive );
+ rtl_freeMemory( pItemImpl );
+ }
+ return osl_File_E_None;
+}
+
+/****************************************************************************
+ * osl_createFileHandleFromFD
+ ***************************************************************************/
+
+oslFileHandle osl_createFileHandleFromFD( int fd )
+{
+ oslFileHandleImpl* pHandleImpl = NULL;
+
+ if ( fd >= 0 )
+ {
+ pHandleImpl = (oslFileHandleImpl*) rtl_allocateMemory( sizeof(oslFileHandleImpl) );
+
+ if( pHandleImpl )
+ {
+ pHandleImpl->ustrFilePath = NULL;
+ rtl_uString_new( &pHandleImpl->ustrFilePath );
+ pHandleImpl->fd = fd;
+
+ /* FIXME: should detect whether the file has been locked */
+ pHandleImpl->bLocked = sal_True;
+ }
+ }
+
+ return (oslFileHandle)pHandleImpl;
+}
+
+/****************************************************************************
+ * osl_openFile
+ ***************************************************************************/
+
+oslFileError osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags )
+{
+ oslFileHandleImpl* pHandleImpl = NULL;
+ oslFileError eRet;
+ rtl_uString* ustrFilePath = NULL;
+
+ char buffer[PATH_MAX];
+ int fd;
+ int mode = S_IRUSR | S_IRGRP | S_IROTH;
+ int flags = O_RDONLY;
+
+ struct flock aflock;
+
+ /* locking the complete file */
+ aflock.l_type = 0;
+ aflock.l_whence = SEEK_SET;
+ aflock.l_start = 0;
+ aflock.l_len = 0;
+
+ OSL_ASSERT( ustrFileURL );
+ OSL_ASSERT( pHandle );
+
+ if( ( 0 == ustrFileURL->length ) )
+ return osl_File_E_INVAL;
+
+ /* convert file URL to system path */
+ eRet = osl_getSystemPathFromFileURL( ustrFileURL, &ustrFilePath );
+
+ if( osl_File_E_None != eRet )
+ return eRet;
+
+ osl_systemPathRemoveSeparator(ustrFilePath);
+
+ /* convert unicode path to text */
+ if( UnicodeToText( buffer, PATH_MAX, ustrFilePath->buffer, ustrFilePath->length ) )
+ {
+ /* we do not open devices or such here */
+ if( !( uFlags & osl_File_OpenFlag_Create ) )
+ {
+ struct stat aFileStat;
+
+ if( 0 > stat( buffer, &aFileStat ) )
+ {
+ PERROR( "osl_openFile", buffer );
+ eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
+ }
+
+ else if( !S_ISREG( aFileStat.st_mode ) )
+ {
+ eRet = osl_File_E_INVAL;
+ }
+ }
+
+ if( osl_File_E_None == eRet )
+ {
+ /*
+ * set flags and mode
+ */
+
+ if ( uFlags & osl_File_OpenFlag_Write )
+ {
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ flags = O_RDWR;
+ aflock.l_type = F_WRLCK;
+ }
+
+ if ( uFlags & osl_File_OpenFlag_Create )
+ {
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ flags = O_CREAT | O_EXCL | O_RDWR;
+ }
+
+ /* open the file */
+ fd = open( buffer, flags | O_BINARY, mode);
+ if ( fd >= 0 )
+ {
+ sal_Bool bNeedsLock = ( ( uFlags & osl_File_OpenFlag_NoLock ) == 0 );
+ sal_Bool bLocked = sal_False;
+ if( bNeedsLock )
+ {
+ /* check if file lock is enabled and clear l_type member of flock otherwise */
+ if( (char *) -1 == pFileLockEnvVar )
+ {
+ /* FIXME: this is not MT safe */
+ pFileLockEnvVar = getenv("SAL_ENABLE_FILE_LOCKING");
+
+ if( NULL == pFileLockEnvVar)
+ pFileLockEnvVar = getenv("STAR_ENABLE_FILE_LOCKING");
+ }
+
+ if( NULL == pFileLockEnvVar )
+ aflock.l_type = 0;
+
+ /* lock the file if flock.l_type is set */
+ bLocked = ( F_WRLCK != aflock.l_type || -1 != fcntl( fd, F_SETLK, &aflock ) );
+ }
+
+ if ( !bNeedsLock || bLocked )
+ {
+ /* allocate memory for impl structure */
+ pHandleImpl = (oslFileHandleImpl*) rtl_allocateMemory( sizeof(oslFileHandleImpl) );
+ if( pHandleImpl )
+ {
+ pHandleImpl->ustrFilePath = ustrFilePath;
+ pHandleImpl->fd = fd;
+ pHandleImpl->bLocked = bLocked;
+
+ *pHandle = (oslFileHandle) pHandleImpl;
+
+ return osl_File_E_None;
+ }
+ else
+ {
+ errno = ENOMEM;
+ }
+ }
+
+ close( fd );
+ }
+
+ PERROR( "osl_openFile", buffer );
+ eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
+ }
+ }
+ else
+ eRet = osl_File_E_INVAL;
+
+ rtl_uString_release( ustrFilePath );
+ return eRet;
+}
+
+/****************************************************************************/
+/* osl_closeFile */
+/****************************************************************************/
+
+oslFileError osl_closeFile( oslFileHandle Handle )
+{
+ oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl *) Handle;
+ oslFileError eRet = osl_File_E_INVAL;
+
+ OSL_ASSERT( Handle );
+
+ if( pHandleImpl )
+ {
+ rtl_uString_release( pHandleImpl->ustrFilePath );
+
+ /* release file lock if locking is enabled */
+ if( pFileLockEnvVar )
+ {
+ struct flock aflock;
+
+ aflock.l_type = F_UNLCK;
+ aflock.l_whence = SEEK_SET;
+ aflock.l_start = 0;
+ aflock.l_len = 0;
+
+ if ( pHandleImpl->bLocked )
+ {
+ /* FIXME: check if file is really locked ? */
+
+ /* release the file share lock on this file */
+ if( -1 == fcntl( pHandleImpl->fd, F_SETLK, &aflock ) )
+ PERROR( "osl_closeFile", "unlock failed" );
+ }
+ }
+
+ if( 0 > close( pHandleImpl->fd ) )
+ {
+ eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
+ }
+ else
+ eRet = osl_File_E_None;
+
+ rtl_freeMemory( pHandleImpl );
+ }
+
+ return eRet;
+}
+
+/****************************************************************************/
+/* osl_isEndOfFile */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF )
+{
+ oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl *) Handle;
+ oslFileError eRet = osl_File_E_INVAL;
+
+ if ( pHandleImpl)
+ {
+ long curPos = lseek( pHandleImpl->fd, 0, SEEK_CUR );
+
+ if ( curPos >= 0 )
+ {
+ long endPos = lseek( pHandleImpl->fd, 0, SEEK_END );
+
+ if ( endPos >= 0 )
+ {
+ *pIsEOF = ( curPos == endPos );
+ curPos = lseek( pHandleImpl->fd, curPos, SEEK_SET );
+
+ if ( curPos >= 0 )
+ eRet = osl_File_E_None;
+ else
+ eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
+ }
+ else
+ eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
+ }
+ else
+ eRet = oslTranslateFileError(OSL_FET_ERROR, errno );
+ }
+
+ return eRet;
+}
+
+
+/****************************************************************************/
+/* osl_moveFile */
+/****************************************************************************/
+
+oslFileError osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
+{
+ char srcPath[PATH_MAX];
+ char destPath[PATH_MAX];
+ oslFileError eRet;
+ APIRET rc;
+
+ OSL_ASSERT( ustrFileURL );
+ OSL_ASSERT( ustrDestURL );
+
+ /* convert source url to system path */
+ eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ /* convert destination url to system path */
+ eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ //YD 01/05/06 rename() can overwrite existing files.
+ rc = DosDelete( (PCSZ)destPath);
+ rc = DosMove( (PCSZ)srcPath, (PCSZ)destPath);
+ if (!rc)
+ eRet = osl_File_E_None;
+ else
+ eRet = MapError( rc);
+
+ return eRet;
+}
+
+/****************************************************************************/
+/* osl_copyFile */
+/****************************************************************************/
+
+#define TMP_DEST_FILE_EXTENSION ".osl-tmp"
+
+static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
+{
+ int nRet=0;
+ sal_Char pszTmpDestFile[PATH_MAX];
+ size_t size_tmp_dest_buff = sizeof(pszTmpDestFile);
+
+ /* Quick fix for #106048, the whole copy file function seems
+ to be erroneous anyway and needs to be rewritten.
+ Besides osl_copyFile is currently not used from OO/SO code.
+ */
+ memset(pszTmpDestFile, 0, size_tmp_dest_buff);
+
+ if ( DestFileExists )
+ {
+ strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1);
+
+ if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff)
+ return osl_File_E_NAMETOOLONG;
+
+ strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION));
+
+ /* FIXME: what if pszTmpDestFile already exists? */
+ /* with getcanonical??? */
+ nRet=rename(pszDestFileName,pszTmpDestFile);
+ }
+
+ /* mfe: should be S_ISREG */
+ if ( !S_ISLNK(nMode) )
+ {
+ /* copy SourceFile to DestFile */
+ nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
+ }
+ /* mfe: OK redundant at the moment */
+ else if ( S_ISLNK(nMode) )
+ {
+ nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
+ }
+ else
+ {
+ /* mfe: what to do here? */
+ nRet=ENOSYS;
+ }
+
+ if ( nRet > 0 && DestFileExists == 1 )
+ {
+ unlink(pszDestFileName);
+ rename(pszTmpDestFile,pszDestFileName);
+ }
+
+ if ( nRet > 0 )
+ {
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ if ( DestFileExists == 1 )
+ {
+ unlink(pszTmpDestFile);
+ }
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * oslChangeFileModes
+ ****************************************/
+
+static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
+{
+ int nRet=0;
+ struct utimbuf aTimeBuffer;
+
+ nRet = chmod(pszFileName,nMode);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ aTimeBuffer.actime=nAcTime;
+ aTimeBuffer.modtime=nModTime;
+ nRet=utime(pszFileName,&aTimeBuffer);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ if ( nUID != getuid() )
+ {
+ nUID=getuid();
+ }
+
+ nRet=chown(pszFileName,nUID,nGID);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+
+ /* mfe: do not return an error here! */
+ /* return oslTranslateFileError(nRet);*/
+ }
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * oslDoCopyLink
+ ****************************************/
+
+static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
+{
+ int nRet=0;
+
+ /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
+ /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
+ sal_Char pszLinkContent[PATH_MAX];
+
+ pszLinkContent[0] = '\0';
+
+ nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return nRet;
+ }
+ else
+ pszLinkContent[ nRet ] = 0;
+
+ nRet = symlink(pszLinkContent,pszDestFileName);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return nRet;
+ }
+
+ return 0;
+}
+
+/*****************************************
+ * oslDoCopyFile
+ ****************************************/
+
+static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
+{
+ int SourceFileFD=0;
+ int DestFileFD=0;
+ int nRet=0;
+ void* pSourceFile=0;
+ char buffer[ 4096];
+
+ SourceFileFD=open(pszSourceFileName,O_RDONLY | O_BINARY);
+ if ( SourceFileFD < 0 )
+ {
+ nRet=errno;
+ return nRet;
+ }
+
+ DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT | O_BINARY, mode);
+ if ( DestFileFD < 0 )
+ {
+ nRet=errno;
+ close(SourceFileFD);
+ return nRet;
+ }
+
+ /* HACK: because memory mapping fails on various
+ platforms if the size of the source file is 0 byte */
+ if (0 == nSourceSize)
+ {
+ close(SourceFileFD);
+ close(DestFileFD);
+ return 0;
+ }
+
+ while( (nRet = read(SourceFileFD, buffer, sizeof(buffer))) !=0 )
+ {
+ nRet = write( DestFileFD, buffer, nRet);
+ }
+
+ close(SourceFileFD);
+ close(DestFileFD);
+
+ return nRet;
+}
+
+static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
+{
+ time_t nAcTime=0;
+ time_t nModTime=0;
+ uid_t nUID=0;
+ gid_t nGID=0;
+ int nRet=0;
+ mode_t nMode=0;
+ struct stat aFileStat;
+ oslFileError tErr=osl_File_E_invalidError;
+ size_t nSourceSize=0;
+ int DestFileExists=1;
+
+ /* mfe: does the source file really exists? */
+ nRet = lstat(pszPath,&aFileStat);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ /* mfe: we do only copy files here! */
+ if ( S_ISDIR(aFileStat.st_mode) )
+ {
+ return osl_File_E_ISDIR;
+ }
+
+ nSourceSize=(size_t)aFileStat.st_size;
+ nMode=aFileStat.st_mode;
+ nAcTime=aFileStat.st_atime;
+ nModTime=aFileStat.st_mtime;
+ nUID=aFileStat.st_uid;
+ nGID=aFileStat.st_gid;
+
+ nRet = stat(pszDestPath,&aFileStat);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+
+ if ( nRet == ENOENT )
+ {
+ DestFileExists=0;
+ }
+/* return oslTranslateFileError(nRet);*/
+ }
+
+ /* mfe: the destination file must not be a directory! */
+ if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
+ {
+ return osl_File_E_ISDIR;
+ }
+ else
+ {
+ /* mfe: file does not exists or is no dir */
+ }
+
+ tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
+
+ if ( tErr != osl_File_E_None )
+ {
+ return tErr;
+ }
+
+ /*
+ * mfe: ignore return code
+ * since only the success of the copy is
+ * important
+ */
+ oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
+
+ return tErr;
+}
+
+oslFileError osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
+{
+ char srcPath[PATH_MAX];
+ char destPath[PATH_MAX];
+ oslFileError eRet;
+ APIRET rc;
+
+ OSL_ASSERT( ustrFileURL );
+ OSL_ASSERT( ustrDestURL );
+
+ /* convert source url to system path */
+ eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ /* convert destination url to system path */
+ eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ return osl_psz_copyFile( srcPath, destPath );
+}
+
+/****************************************************************************/
+/* osl_removeFile */
+/****************************************************************************/
+
+oslFileError osl_removeFile( rtl_uString* ustrFileURL )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+ APIRET rc;
+
+ OSL_ASSERT( ustrFileURL );
+
+ /* convert file url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ rc = DosDelete( (PCSZ)path);
+ if (!rc)
+ eRet = osl_File_E_None;
+ else
+ eRet = MapError( rc);
+
+ return eRet;
+}
+
+/****************************************************************************/
+/* osl_getVolumeInformation */
+/****************************************************************************/
+
+#define TXFSDC_BLOCKR 0x00 // block device removable
+#define TXFSDC_GETBPB 0x00 // get device bpb info
+#define TXFSBPB_REMOVABLE 0x08 // BPB attribute for removable
+
+typedef struct drivecmd
+{
+ BYTE cmd; // 0=unlock 1=lock 2=eject
+ BYTE drv; // 0=A, 1=B 2=C ...
+} DRIVECMD; // end of struct "drivecmd"
+
+#pragma pack(push, 1) // byte packing
+typedef struct txfs_ebpb // ext. boot parameter block
+{ // at offset 0x0b in bootsector
+ USHORT SectSize; // 0B bytes per sector
+ BYTE ClustSize; // 0D sectors per cluster
+ USHORT FatOffset; // 0E sectors to 1st FAT
+ BYTE NrOfFats; // 10 nr of FATS (FAT only)
+ USHORT RootEntries; // 11 Max entries \ (FAT only)
+ USHORT Sectors; // 13 nr of sectors if < 64K
+ BYTE MediaType; // 15 mediatype (F8 for HD)
+ USHORT FatSectors; // 16 sectors/FAT (FAT only)
+ USHORT LogGeoSect; // 18 sectors/Track
+ USHORT LogGeoHead; // 1a nr of heads
+ ULONG HiddenSectors; // 1c sector-offset from MBR/EBR
+ ULONG BigSectors; // 20 nr of sectors if >= 64K
+} TXFS_EBPB; // last byte is at offset 0x23
+
+typedef struct drivebpb
+{
+ TXFS_EBPB ebpb; // extended BPB
+ BYTE reserved[6];
+ USHORT cyls;
+ BYTE type;
+ USHORT attributes; // device attributes
+ BYTE fill[6]; // documented for IOCtl
+} DRIVEBPB; // end of struct "drivebpb"
+
+struct CDInfo {
+ USHORT usCount;
+ USHORT usFirst;
+};
+
+#pragma pack(pop)
+
+/*****************************************************************************/
+// Get number of cdrom readers
+/*****************************************************************************/
+BOOL GetCDInfo( CDInfo * pCDInfo )
+{
+ HFILE hFileCD;
+ ULONG ulAction;
+
+ if( NO_ERROR == DosOpen( (PCSZ)"\\DEV\\CD-ROM2$",
+ &hFileCD, &ulAction, 0, FILE_NORMAL,
+ OPEN_ACTION_OPEN_IF_EXISTS,
+ OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL )) {
+ ULONG ulDataSize = sizeof(CDInfo);
+ APIRET rc = DosDevIOCtl( hFileCD, 0x82, 0x60, NULL, 0,
+ NULL, (PVOID)pCDInfo, ulDataSize, &ulDataSize);
+ DosClose( hFileCD);
+ if(rc == NO_ERROR)
+ return TRUE;
+ }
+ // failed
+ pCDInfo->usFirst = 0;
+ pCDInfo->usCount = 0;
+ return FALSE;
+}
+
+/*****************************************************************************/
+// Determine if unit is a cdrom or not
+/*****************************************************************************/
+BOOL DriveIsCDROM(UINT uiDrive, CDInfo *pCDInfo)
+{
+ return (uiDrive >= pCDInfo->usFirst)
+ && (uiDrive < (pCDInfo->usFirst + pCDInfo->usCount));
+}
+
+/*****************************************************************************/
+// Determine attached fstype, e.g. HPFS for specified drive
+/*****************************************************************************/
+BOOL TxFsType // RET FS type resolved
+(
+ char *drive, // IN Drive specification
+ char *fstype, // OUT Attached FS type
+ char *details // OUT details (UNC) or NULL
+)
+{
+ BOOL rc = FALSE;
+ FSQBUFFER2 *fsinfo; // Attached FS info
+ ULONG fsdlen = 2048; // Fs info data length
+
+ strcpy(fstype, "none");
+ if (details)
+ {
+ strcpy(details, "");
+ }
+ if ((fsinfo = (FSQBUFFER2*)calloc(1, fsdlen)) != NULL)
+ {
+ if (DosQFSAttach((PCSZ)drive, 0, 1, fsinfo, &fsdlen) == NO_ERROR)
+ {
+ strcpy(fstype, (char*) fsinfo->szName + fsinfo->cbName +1);
+ if (details && (fsinfo->cbFSAData != 0))
+ {
+ strcpy( details, (char*) fsinfo->szName + fsinfo->cbName +
+ fsinfo->cbFSDName +2);
+ }
+ rc = TRUE;
+ }
+ free(fsinfo);
+ }
+ return (rc);
+} // end 'TxFsType'
+/*---------------------------------------------------------------------------*/
+
+
+/*****************************************************************************/
+// Determine if a driveletter represents a removable medium/device
+/*****************************************************************************/
+BOOL TxFsIsRemovable // RET drive is removable
+(
+ char *drive // IN Driveletter to test
+)
+{
+ BOOL rc = FALSE;
+ DRIVECMD IOCtl;
+ DRIVEBPB RemAt;
+ ULONG DataLen;
+ ULONG ParmLen;
+ BYTE NoRem;
+
+ DosError( FERR_DISABLEHARDERR); // avoid 'not ready' popups
+
+ ParmLen = sizeof(IOCtl);
+ IOCtl.cmd = TXFSDC_BLOCKR;
+ IOCtl.drv = toupper(drive[0]) - 'A';
+ DataLen = sizeof(NoRem);
+
+ if (DosDevIOCtl((HFILE) -1, IOCTL_DISK,
+ DSK_BLOCKREMOVABLE,
+ &IOCtl, ParmLen, &ParmLen,
+ &NoRem, DataLen, &DataLen) == NO_ERROR)
+ {
+ if (NoRem) // non-removable sofar, check
+ { // BPB as well (USB devices)
+ ParmLen = sizeof(IOCtl);
+ IOCtl.cmd = TXFSDC_GETBPB;
+ IOCtl.drv = toupper(drive[0]) - 'A';
+ DataLen = sizeof(RemAt);
+
+ if (DosDevIOCtl((HFILE) -1, IOCTL_DISK,
+ DSK_GETDEVICEPARAMS,
+ &IOCtl, ParmLen, &ParmLen,
+ &RemAt, DataLen, &DataLen) == NO_ERROR)
+
+ {
+ if (RemAt.attributes & TXFSBPB_REMOVABLE)
+ {
+ rc = TRUE; // removable, probably USB
+ }
+ }
+ }
+ else
+ {
+ rc = TRUE; // removable block device
+ }
+ }
+ DosError( FERR_ENABLEHARDERR); // enable criterror handler
+ return (rc);
+} // end 'TxFsIsRemovable'
+/*---------------------------------------------------------------------------*/
+
+static oslFileError get_drive_type(const char* path, oslVolumeInfo* pInfo)
+{
+ char Drive_Letter = toupper( *path);
+ char fstype[ 64];
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+
+ // check for floppy A/B
+ BYTE nFloppies;
+ APIRET rc;
+ rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY );
+ if ((Drive_Letter - 'A') < nFloppies) {
+ pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
+ pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk;
+ return osl_File_E_None;
+ }
+
+ // query system for CD drives
+ CDInfo cdInfo;
+ GetCDInfo(&cdInfo);
+
+ // query if drive is a CDROM
+ if (DriveIsCDROM( Drive_Letter - 'A', &cdInfo))
+ pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
+
+ if (TxFsIsRemovable( (char*)path))
+ pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
+
+ if (TxFsType( (char*)path, fstype, NULL) == FALSE) {
+ // query failed, assume fixed disk
+ pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
+ return osl_File_E_None;
+ }
+
+ //- Note, connected Win-NT drives use the REAL FS-name like NTFS!
+ if ((strncasecmp( fstype, "LAN", 3) == 0) //- OS/2 LAN drives
+ || (strncasecmp( fstype, "NDFS", 4) == 0) //- NetDrive
+ || (strncasecmp( fstype, "REMOTE", 5) == 0) ) //- NT disconnected
+ pInfo->uAttributes |= osl_Volume_Attribute_Remote;
+ else if (strncasecmp( fstype, "RAMFS", 5) == 0)
+ pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk;
+ else if ((strncasecmp( fstype, "CD", 2) == 0) // OS2:CDFS, DOS/WIN:CDROM
+ || (strncasecmp( fstype, "UDF", 3) == 0) ) // OS2:UDF DVD's
+ pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
+ else
+ pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
+
+ return osl_File_E_None;
+}
+
+//#############################################
+inline bool is_volume_space_info_request(sal_uInt32 field_mask)
+{
+ return (field_mask &
+ (osl_VolumeInfo_Mask_TotalSpace |
+ osl_VolumeInfo_Mask_UsedSpace |
+ osl_VolumeInfo_Mask_FreeSpace));
+}
+
+//#############################################
+static void get_volume_space_information(const char* path, oslVolumeInfo *pInfo)
+{
+ FSALLOCATE aFSInfoBuf;
+ ULONG nDriveNumber = toupper( *path) - 'A' + 1;
+
+ // disable error popups
+ DosError(FERR_DISABLEHARDERR);
+ APIRET rc = DosQueryFSInfo( nDriveNumber, FSIL_ALLOC,
+ &aFSInfoBuf, sizeof(aFSInfoBuf) );
+ // enable error popups
+ DosError(FERR_ENABLEHARDERR);
+ if (!rc)
+ {
+ uint64_t aBytesPerCluster( uint64_t(aFSInfoBuf.cbSector) *
+ uint64_t(aFSInfoBuf.cSectorUnit) );
+ pInfo->uFreeSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnitAvail);
+ pInfo->uTotalSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnit);
+ pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace |
+ osl_VolumeInfo_Mask_UsedSpace |
+ osl_VolumeInfo_Mask_FreeSpace;
+ }
+}
+
+//#############################################
+inline bool is_filesystem_attributes_request(sal_uInt32 field_mask)
+{
+ return (field_mask &
+ (osl_VolumeInfo_Mask_MaxNameLength |
+ osl_VolumeInfo_Mask_MaxPathLength |
+ osl_VolumeInfo_Mask_FileSystemName |
+ osl_VolumeInfo_Mask_FileSystemCaseHandling));
+}
+
+//#############################################
+inline bool is_drivetype_request(sal_uInt32 field_mask)
+{
+ return (field_mask & osl_VolumeInfo_Mask_Attributes);
+}
+
+typedef struct _FSQBUFFER_
+{
+ FSQBUFFER2 aBuf;
+ UCHAR sBuf[64];
+} FSQBUFFER_;
+
+//#############################################
+static oslFileError get_filesystem_attributes(const char* path, sal_uInt32 field_mask, oslVolumeInfo* pInfo)
+{
+ pInfo->uAttributes = 0;
+
+ oslFileError osl_error = osl_File_E_None;
+
+ // osl_get_drive_type must be called first because
+ // this function resets osl_VolumeInfo_Mask_Attributes
+ // on failure
+ if (is_drivetype_request(field_mask))
+ osl_error = get_drive_type(path, pInfo);
+
+ if ((osl_File_E_None == osl_error) && is_filesystem_attributes_request(field_mask))
+ {
+ FSQBUFFER_ aBuf;
+ ULONG nBufLen;
+ APIRET nRet;
+
+ nBufLen = sizeof( aBuf );
+ // disable error popups
+ DosError(FERR_DISABLEHARDERR);
+ nRet = DosQueryFSAttach( (PCSZ)path, 0, FSAIL_QUERYNAME, (_FSQBUFFER2*) &aBuf, &nBufLen );
+ if ( !nRet )
+ {
+ char *pType = (char*)(aBuf.aBuf.szName + aBuf.aBuf.cbName + 1);
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
+ pInfo->uMaxNameLength = _MAX_FNAME;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
+ pInfo->uMaxPathLength = _MAX_PATH;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
+ rtl_uString_newFromAscii(&pInfo->ustrFileSystemName, pType);
+
+ // case is preserved always except for FAT
+ if (strcmp( pType, "FAT" ))
+ pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+ // enable error popups
+ DosError(FERR_ENABLEHARDERR);
+ }
+ return osl_error;
+}
+
+oslFileError SAL_CALL osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask )
+{
+ char volume_root[PATH_MAX];
+ oslFileError error;
+
+ OSL_ASSERT( ustrDirectoryURL );
+ OSL_ASSERT( pInfo );
+
+ /* convert directory url to system path */
+ error = FileURLToPath( volume_root, PATH_MAX, ustrDirectoryURL );
+ if( error != osl_File_E_None )
+ return error;
+
+ if (!pInfo)
+ return osl_File_E_INVAL;
+
+ pInfo->uValidFields = 0;
+
+ if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None)
+ return error;
+
+ if (is_volume_space_info_request(uFieldMask))
+ get_volume_space_information(volume_root, pInfo);
+
+ if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
+ {
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
+ rtl_uString* uVolumeRoot;
+ rtl_uString_newFromAscii( &uVolumeRoot, volume_root);
+ osl_getFileURLFromSystemPath( uVolumeRoot, (rtl_uString**)&pInfo->pDeviceHandle);
+ rtl_uString_release( uVolumeRoot);
+ }
+
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_getFileStatus */
+/****************************************************************************/
+static oslFileError _osl_getDriveInfo(
+ oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask)
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+ sal_Unicode cDrive[3];
+ sal_Unicode cRoot[4];
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ pStatus->uValidFields = 0;
+
+ cDrive[0] = pItemImpl->ustrDrive->buffer[0];
+ cDrive[1] = (sal_Unicode)':';
+ cDrive[2] = 0;
+ cRoot[0] = pItemImpl->ustrDrive->buffer[0];
+ cRoot[1] = (sal_Unicode)':';
+ cRoot[2] = 0;
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileName )
+ {
+ if ( pItemImpl->ustrDrive->buffer[0] == '\\' &&
+ pItemImpl->ustrDrive->buffer[1] == '\\' )
+ {
+ LPCWSTR lpFirstBkSlash = wcschr( (const wchar_t*)&pItemImpl->ustrDrive->buffer[2], '\\' );
+
+ if ( lpFirstBkSlash && lpFirstBkSlash[1] )
+ {
+ LPCWSTR lpLastBkSlash = wcschr( (const wchar_t*)&lpFirstBkSlash[1], '\\' );
+
+ if ( lpLastBkSlash )
+ rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1], lpLastBkSlash - lpFirstBkSlash - 1 );
+ else
+ rtl_uString_newFromStr( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1] );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ }
+ }
+ else
+ {
+ FSINFO aFSInfoBuf;
+ ULONG ulFSInfoLevel = FSIL_VOLSER;
+ ULONG nDriveNumber;
+ char szFileName[ _MAX_PATH];
+
+ nDriveNumber = toupper(*cDrive) - 'A' + 1;
+ memset( &aFSInfoBuf, 0, sizeof(FSINFO) );
+ // disable error popups
+ DosError(FERR_DISABLEHARDERR);
+ APIRET rc = DosQueryFSInfo( nDriveNumber, ulFSInfoLevel, &aFSInfoBuf, sizeof(FSINFO) );
+ // enable error popups
+ DosError(FERR_ENABLEHARDERR);
+ memset( szFileName, 0, sizeof( szFileName));
+ *szFileName = toupper(*cDrive);
+ strcat( szFileName, ": [");
+ if ( !rc || aFSInfoBuf.vol.cch)
+ strncat( szFileName, aFSInfoBuf.vol.szVolLabel, aFSInfoBuf.vol.cch);
+ strcat( szFileName, "]");
+ rtl_uString_newFromAscii( &pStatus->ustrFileName, szFileName );
+
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ }
+ }
+
+ pStatus->eType = osl_File_Type_Volume;
+ pStatus->uValidFields |= osl_FileStatus_Mask_Type;
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileURL )
+ {
+ rtl_uString *ustrSystemPath = NULL;
+
+ rtl_uString_newFromStr( &ustrSystemPath, pItemImpl->ustrDrive->buffer );
+ osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
+ rtl_uString_release( ustrSystemPath );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+
+ return osl_File_E_None;
+}
+
+oslFileError SAL_CALL osl_getFileStatus(
+ oslDirectoryItem Item,
+ oslFileStatus *pStatus,
+ sal_uInt32 uFieldMask )
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+ struct stat file_stat;
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ if ( pItemImpl->uType == DIRECTORYITEM_DRIVE)
+ return _osl_getDriveInfo( Item, pStatus, uFieldMask );
+
+ osl::lstat(pItemImpl->ustrFilePath, file_stat);
+ if ( uFieldMask & osl_FileStatus_Mask_Validate )
+ {
+ uFieldMask &= ~ osl_FileStatus_Mask_Validate;
+ }
+
+ /* If no fields to retrieve left ignore pStatus */
+ if ( !uFieldMask )
+ return osl_File_E_None;
+
+ /* Otherwise, this must be a valid pointer */
+ if ( !pStatus )
+ return osl_File_E_INVAL;
+
+ if ( pStatus->uStructSize != sizeof(oslFileStatus) )
+ return osl_File_E_INVAL;
+
+ pStatus->uValidFields = 0;
+
+ /* File time stamps */
+
+ if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime))
+ {
+ pStatus->aModifyTime.Seconds = file_stat.st_mtime;
+ pStatus->aModifyTime.Nanosec = 0;
+ pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime;
+ }
+
+ if ( (uFieldMask & osl_FileStatus_Mask_AccessTime))
+ {
+ pStatus->aAccessTime.Seconds = file_stat.st_atime;
+ pStatus->aAccessTime.Nanosec = 0;
+ pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime;
+ }
+
+ if ( (uFieldMask & osl_FileStatus_Mask_CreationTime))
+ {
+ pStatus->aAccessTime.Seconds = file_stat.st_birthtime;
+ pStatus->aAccessTime.Nanosec = 0;
+ pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime;
+ }
+
+ /* Most of the fields are already set, regardless of requiered fields */
+
+ osl_systemPathGetFileNameOrLastDirectoryPart(pItemImpl->ustrFilePath, &pStatus->ustrFileName);
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+
+ if (S_ISLNK(file_stat.st_mode))
+ pStatus->eType = osl_File_Type_Link;
+ else if (S_ISDIR(file_stat.st_mode))
+ pStatus->eType = osl_File_Type_Directory;
+ else if (S_ISREG(file_stat.st_mode))
+ pStatus->eType = osl_File_Type_Regular;
+ else if (S_ISFIFO(file_stat.st_mode))
+ pStatus->eType = osl_File_Type_Fifo;
+ else if (S_ISSOCK(file_stat.st_mode))
+ pStatus->eType = osl_File_Type_Socket;
+ else if (S_ISCHR(file_stat.st_mode) || S_ISBLK(file_stat.st_mode))
+ pStatus->eType = osl_File_Type_Special;
+ else
+ pStatus->eType = osl_File_Type_Unknown;
+
+ pStatus->uValidFields |= osl_FileStatus_Mask_Type;
+
+ pStatus->uAttributes = pItemImpl->d_attr;
+ pStatus->uValidFields |= osl_FileStatus_Mask_Attributes;
+
+ pStatus->uFileSize = file_stat.st_size;
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileSize;
+
+ if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL )
+ {
+ rtl_uString *ustrFullPath = NULL;
+
+ rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) );
+ osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrLinkTargetURL );
+ rtl_uString_release( ustrFullPath );
+
+ pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
+ }
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileURL )
+ {
+ rtl_uString *ustrFullPath = NULL;
+
+ rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) );
+ osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrFileURL );
+ rtl_uString_release( ustrFullPath );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_createDirectory */
+/****************************************************************************/
+
+oslFileError osl_createDirectory( rtl_uString* ustrDirectoryURL )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+ APIRET rc;
+
+ OSL_ASSERT( ustrDirectoryURL );
+
+ /* convert directory url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ rc = DosCreateDir( (PCSZ)path, NULL);
+ if (rc == ERROR_ACCESS_DENIED)
+ rc=ERROR_FILE_EXISTS;
+
+ if (!rc)
+ eRet = osl_File_E_None;
+ else
+ eRet = MapError( rc);
+
+ return eRet;
+}
+
+/****************************************************************************/
+/* osl_removeDirectory */
+/****************************************************************************/
+
+oslFileError osl_removeDirectory( rtl_uString* ustrDirectoryURL )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+ APIRET rc;
+
+ OSL_ASSERT( ustrDirectoryURL );
+
+ /* convert directory url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ rc = DosDeleteDir( (PCSZ)path);
+ if (!rc)
+ eRet = osl_File_E_None;
+ else
+ eRet = MapError( rc);
+
+ return eRet;
+}
+
+//#############################################
+int path_make_parent(sal_Unicode* path)
+{
+ int i = rtl_ustr_lastIndexOfChar(path, '/');
+
+ if (i > 0)
+ {
+ *(path + i) = 0;
+ return i;
+ }
+ else
+ return 0;
+}
+
+//#############################################
+int create_dir_with_callback(
+ sal_Unicode* directory_path,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ int mode = S_IRWXU | S_IRWXG | S_IRWXO;
+
+ if (osl::mkdir(directory_path, mode) == 0)
+ {
+ if (aDirectoryCreationCallbackFunc)
+ {
+ rtl::OUString url;
+ osl::FileBase::getFileURLFromSystemPath(directory_path, url);
+ aDirectoryCreationCallbackFunc(pData, url.pData);
+ }
+ return 0;
+ }
+ return errno;
+}
+
+//#############################################
+oslFileError create_dir_recursively_(
+ sal_Unicode* dir_path,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
+ "Path must not end with a slash");
+
+ int native_err = create_dir_with_callback(
+ dir_path, aDirectoryCreationCallbackFunc, pData);
+
+ if (native_err == 0)
+ return osl_File_E_None;
+
+ if (native_err != ENOENT)
+ return oslTranslateFileError(OSL_FET_ERROR, native_err);
+
+ // we step back until '/a_dir' at maximum because
+ // we should get an error unequal ENOENT when
+ // we try to create 'a_dir' at '/' and would so
+ // return before
+ int pos = path_make_parent(dir_path);
+
+ oslFileError osl_error = create_dir_recursively_(
+ dir_path, aDirectoryCreationCallbackFunc, pData);
+
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+
+ dir_path[pos] = '/';
+
+ return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
+}
+
+//#######################################
+oslFileError SAL_CALL osl_createDirectoryPath(
+ rtl_uString* aDirectoryUrl,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ if (aDirectoryUrl == NULL)
+ return osl_File_E_INVAL;
+
+ rtl::OUString sys_path;
+ oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
+ aDirectoryUrl, &sys_path.pData, sal_False);
+
+ if (osl_error != osl_File_E_None)
+ return osl_error;
+
+ osl::systemPathRemoveSeparator(sys_path);
+
+ // const_cast because sys_path is a local copy which we want to modify inplace instead of
+ // coyp it into another buffer on the heap again
+ return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
+}
+
+/****************************************************************************/
+/* osl_getCanonicalName */
+/****************************************************************************/
+
+oslFileError osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL )
+{
+ OSL_ENSURE(sal_False, "osl_getCanonicalName not implemented");
+
+ rtl_uString_newFromString(pustrValidURL, ustrFileURL);
+ return osl_File_E_None;
+}
+
+
+/****************************************************************************/
+/* osl_setFileAttributes */
+/****************************************************************************/
+
+oslFileError osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+ FILESTATUS3 fsts3ConfigInfo;
+ ULONG ulBufSize = sizeof(FILESTATUS3);
+ APIRET rc = NO_ERROR;
+
+ OSL_ASSERT( ustrFileURL );
+
+ /* convert file url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ /* query current attributes */
+ rc = DosQueryPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
+ if (rc != NO_ERROR)
+ return MapError( rc);
+
+ /* set/reset readonly/hidden (see w32\file.cxx) */
+ fsts3ConfigInfo.attrFile &= ~(FILE_READONLY | FILE_HIDDEN);
+ if ( uAttributes & osl_File_Attribute_ReadOnly )
+ fsts3ConfigInfo.attrFile |= FILE_READONLY;
+ if ( uAttributes & osl_File_Attribute_Hidden )
+ fsts3ConfigInfo.attrFile |= FILE_HIDDEN;
+
+ /* write new attributes */
+ rc = DosSetPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize, 0);
+ if (rc != NO_ERROR)
+ return MapError( rc);
+
+ /* everything ok */
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_setFileTime */
+/****************************************************************************/
+
+oslFileError osl_setFileTime( rtl_uString* ustrFileURL, const TimeValue* pCreationTime,
+ const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+
+ OSL_ASSERT( ustrFileURL );
+
+ /* convert file url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ return osl_psz_setFileTime( path, pCreationTime, pLastAccessTime, pLastWriteTime );
+}
+
+/******************************************************************************
+ *
+ * Exported Module Functions
+ * (independent of C or Unicode Strings)
+ *
+ *****************************************************************************/
+
+
+/*******************************************
+ osl_readFile
+********************************************/
+
+oslFileError osl_readFile(oslFileHandle Handle, void* pBuffer, sal_uInt64 uBytesRequested, sal_uInt64* pBytesRead)
+{
+ ssize_t nBytes = 0;
+ oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl*)Handle;
+
+ if ((0 == pHandleImpl) || (pHandleImpl->fd < 0) || (0 == pBuffer) || (0 == pBytesRead))
+ return osl_File_E_INVAL;
+
+ nBytes = read(pHandleImpl->fd, pBuffer, uBytesRequested);
+
+ if (-1 == nBytes)
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ *pBytesRead = nBytes;
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_writeFile
+********************************************/
+
+oslFileError osl_writeFile(oslFileHandle Handle, const void* pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64* pBytesWritten)
+{
+ ssize_t nBytes = 0;
+ oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl*)Handle;
+
+ OSL_ASSERT(pHandleImpl);
+ OSL_ASSERT(pBuffer);
+ OSL_ASSERT(pBytesWritten);
+
+ if ((0 == pHandleImpl) || (0 == pBuffer) || (0 == pBytesWritten))
+ return osl_File_E_INVAL;
+
+ OSL_ASSERT(pHandleImpl->fd >= 0);
+
+ if (pHandleImpl->fd < 0)
+ return osl_File_E_INVAL;
+
+ nBytes = write(pHandleImpl->fd, pBuffer, uBytesToWrite);
+
+ if (-1 == nBytes)
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ *pBytesWritten = nBytes;
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_writeFile
+********************************************/
+
+oslFileError osl_setFilePos( oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uPos )
+{
+ oslFileHandleImpl* pHandleImpl=0;
+ int nRet=0;
+ off_t nOffset=0;
+
+ pHandleImpl = (oslFileHandleImpl*) Handle;
+ if ( pHandleImpl == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pHandleImpl->fd < 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ /* FIXME mfe: setFilePos: Do we have any runtime function to determine LONG_MAX? */
+ if ( uPos > LONG_MAX )
+ {
+ return osl_File_E_OVERFLOW;
+ }
+
+ nOffset=(off_t)uPos;
+
+ switch(uHow)
+ {
+ case osl_Pos_Absolut:
+ nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_SET);
+ break;
+
+ case osl_Pos_Current:
+ nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_CUR);
+ break;
+
+ case osl_Pos_End:
+ nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_END);
+ break;
+
+ default:
+ return osl_File_E_INVAL;
+ }
+
+ if ( nOffset < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+
+/************************************************
+ * osl_getFilePos
+ ***********************************************/
+
+oslFileError osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos )
+{
+ oslFileHandleImpl* pHandleImpl=0;
+ off_t nOffset=0;
+ int nRet=0;
+
+ pHandleImpl = (oslFileHandleImpl*) Handle;
+ if ( pHandleImpl == 0 || pPos == 0)
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pHandleImpl->fd < 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ nOffset = lseek(pHandleImpl->fd,0,SEEK_CUR);
+
+ if (nOffset < 0)
+ {
+ nRet =errno;
+
+ /* *pPos =0; */
+
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ *pPos=nOffset;
+
+ return osl_File_E_None;
+}
+
+/****************************************************************************
+ * osl_getFileSize
+ ****************************************************************************/
+
+oslFileError osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize )
+{
+ oslFileHandleImpl* pHandleImpl=(oslFileHandleImpl*) Handle;
+ if (pHandleImpl == 0)
+ return osl_File_E_INVAL;
+
+ struct stat file_stat;
+ if (fstat(pHandleImpl->fd, &file_stat) == -1)
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ *pSize = file_stat.st_size;
+ return osl_File_E_None;
+}
+
+/************************************************
+ * osl_setFileSize
+ ***********************************************/
+
+oslFileError osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize )
+{
+ oslFileHandleImpl* pHandleImpl=0;
+ off_t nOffset=0;
+
+ pHandleImpl = (oslFileHandleImpl*) Handle;
+ if ( pHandleImpl == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pHandleImpl->fd < 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ /* FIXME: mfe: setFileSize: Do we have any runtime function to determine LONG_MAX? */
+ if ( uSize > LONG_MAX )
+ {
+ return osl_File_E_OVERFLOW;
+ }
+
+ nOffset = (off_t)uSize;
+ if (ftruncate (pHandleImpl->fd, nOffset) < 0)
+ {
+ /* Failure. Try fallback algorithm */
+ oslFileError result;
+ struct stat aStat;
+ off_t nCurPos;
+
+ /* Save original result */
+ result = oslTranslateFileError (OSL_FET_ERROR, errno);
+ PERROR("ftruncate", "Try osl_setFileSize [fallback]\n");
+
+ /* Check against current size. Fail upon 'shrink' */
+ if (fstat (pHandleImpl->fd, &aStat) < 0)
+ {
+ PERROR("ftruncate: fstat", "Out osl_setFileSize [error]\n");
+ return (result);
+ }
+ if ((0 <= nOffset) && (nOffset <= aStat.st_size))
+ {
+ /* Failure upon 'shrink'. Return original result */
+ return (result);
+ }
+
+ /* Save current position */
+ nCurPos = (off_t)lseek (pHandleImpl->fd, (off_t)0, SEEK_CUR);
+ if (nCurPos == (off_t)(-1))
+ {
+ PERROR("ftruncate: lseek", "Out osl_setFileSize [error]\n");
+ return (result);
+ }
+
+ /* Try 'expand' via 'lseek()' and 'write()' */
+ if (lseek (pHandleImpl->fd, (off_t)(nOffset - 1), SEEK_SET) < 0)
+ {
+ PERROR("ftruncate: lseek", "Out osl_setFileSize [error]\n");
+ return (result);
+ }
+ if (write (pHandleImpl->fd, (char*)"", (size_t)1) < 0)
+ {
+ /* Failure. Restore saved position */
+ PERROR("ftruncate: write", "Out osl_setFileSize [error]\n");
+ if (lseek (pHandleImpl->fd, (off_t)nCurPos, SEEK_SET) < 0)
+ {
+#ifdef DEBUG_OSL_FILE
+ perror("ftruncate: lseek");
+#endif /* DEBUG_OSL_FILE */
+ }
+ return (result);
+ }
+
+ /* Success. Restore saved position */
+ if (lseek (pHandleImpl->fd, (off_t)nCurPos, SEEK_SET) < 0)
+ {
+ PERROR("ftruncate: lseek", "Out osl_setFileSize [error]");
+ return (result);
+ }
+ }
+
+ return (osl_File_E_None);
+}
+
+/*###############################################*/
+oslFileError SAL_CALL osl_syncFile(oslFileHandle Handle)
+{
+ oslFileHandleImpl* handle_impl = (oslFileHandleImpl*)Handle;
+
+ if (handle_impl == 0)
+ return osl_File_E_INVAL;
+
+ if (fsync(handle_impl->fd) == -1)
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ return osl_File_E_None;
+}
+
+/******************************************************************************
+ *
+ * C-String Versions of Exported Module Functions
+ *
+ *****************************************************************************/
+
+#ifdef HAVE_STATFS_H
+
+#if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX)
+# define __OSL_STATFS_STRUCT struct statfs
+# define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
+# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
+# define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename)
+# define __OSL_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 0)
+
+/* always return true if queried for the properties of
+ the file system. If you think this is wrong under any
+ of the target platforms fix it!!!! */
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
+#endif /* FREEBSD || NETBSD */
+
+#if defined(LINUX)
+# define __OSL_NFS_SUPER_MAGIC 0x6969
+# define __OSL_SMB_SUPER_MAGIC 0x517B
+# define __OSL_MSDOS_SUPER_MAGIC 0x4d44
+# define __OSL_NTFS_SUPER_MAGIC 0x5346544e
+# define __OSL_STATFS_STRUCT struct statfs
+# define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
+# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
+# define __OSL_STATFS_IS_NFS(a) (__OSL_NFS_SUPER_MAGIC == (a).f_type)
+# define __OSL_STATFS_IS_SMB(a) (__OSL_SMB_SUPER_MAGIC == (a).f_type)
+# define __OSL_STATFS_ISREMOTE(a) (__OSL_STATFS_IS_NFS((a)) || __OSL_STATFS_IS_SMB((a)))
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type) && (__OSL_NTFS_SUPER_MAGIC != (a).f_type))
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type))
+#endif /* LINUX */
+
+#if defined(SOLARIS)
+# define __OSL_STATFS_STRUCT struct statvfs
+# define __OSL_STATFS(dir, sfs) statvfs((dir), (sfs))
+# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_frsize))
+# define __OSL_STATFS_TYPENAME(a) ((a).f_basetype)
+# define __OSL_STATFS_ISREMOTE(a) (rtl_str_compare((a).f_basetype, "nfs") == 0)
+
+/* always return true if queried for the properties of
+ the file system. If you think this is wrong under any
+ of the target platforms fix it!!!! */
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
+#endif /* SOLARIS */
+
+# define __OSL_STATFS_INIT(a) (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT)))
+
+#else /* no statfs available */
+
+# define __OSL_STATFS_STRUCT struct dummy {int i;}
+# define __OSL_STATFS_INIT(a) ((void)0)
+# define __OSL_STATFS(dir, sfs) (1)
+# define __OSL_STATFS_ISREMOTE(sfs) (0)
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
+#endif /* HAVE_STATFS_H */
+
+
+static oslFileError osl_psz_getVolumeInformation (
+ const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask)
+{
+ __OSL_STATFS_STRUCT sfs;
+
+ if (!pInfo)
+ return osl_File_E_INVAL;
+
+ __OSL_STATFS_INIT(sfs);
+
+ pInfo->uValidFields = 0;
+ pInfo->uAttributes = 0;
+
+ if ((__OSL_STATFS(pszDirectory, &sfs)) < 0)
+ {
+ oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno);
+ return (result);
+ }
+
+ /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */
+ if (uFieldMask & osl_VolumeInfo_Mask_Attributes)
+ {
+ if (__OSL_STATFS_ISREMOTE(sfs))
+ pInfo->uAttributes |= osl_Volume_Attribute_Remote;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+
+ if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling)
+ {
+ if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs))
+ pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive;
+
+ if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs))
+ pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+
+ pInfo->uTotalSpace = 0;
+ pInfo->uFreeSpace = 0;
+ pInfo->uUsedSpace = 0;
+
+#if defined(__OSL_STATFS_BLKSIZ)
+
+ if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) ||
+ (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
+ {
+ pInfo->uTotalSpace = __OSL_STATFS_BLKSIZ(sfs);
+ pInfo->uTotalSpace *= (sal_uInt64)(sfs.f_blocks);
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace;
+ }
+
+ if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) ||
+ (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
+ {
+ pInfo->uFreeSpace = __OSL_STATFS_BLKSIZ(sfs);
+
+ if (getuid() == 0)
+ pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree);
+ else
+ pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail);
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace;
+ }
+
+#endif /* __OSL_STATFS_BLKSIZ */
+
+ if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) &&
+ (pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace ))
+ {
+ pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace;
+ }
+
+ pInfo->uMaxNameLength = 0;
+ if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength)
+ {
+ long nLen = pathconf(pszDirectory, _PC_NAME_MAX);
+ if (nLen > 0)
+ {
+ pInfo->uMaxNameLength = (sal_uInt32)nLen;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
+ }
+ }
+
+ pInfo->uMaxPathLength = 0;
+ if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength)
+ {
+ long nLen = pathconf (pszDirectory, _PC_PATH_MAX);
+ if (nLen > 0)
+ {
+ pInfo->uMaxPathLength = (sal_uInt32)nLen;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
+ }
+ }
+
+#if defined(__OSL_STATFS_TYPENAME)
+
+ if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName)
+ {
+ rtl_string2UString(
+ &(pInfo->ustrFileSystemName),
+ __OSL_STATFS_TYPENAME(sfs),
+ rtl_str_getLength(__OSL_STATFS_TYPENAME(sfs)),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(pInfo->ustrFileSystemName != 0);
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
+ }
+
+#endif /* __OSL_STATFS_TYPENAME */
+
+ if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
+ {
+ /* FIXME: check also entries in mntent for the device
+ and fill it with correct values */
+
+ *pInfo->pDeviceHandle = osl_isFloppyDrive(pszDirectory);
+
+ if (*pInfo->pDeviceHandle)
+ {
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
+ pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+ }
+ return osl_File_E_None;
+}
+
+/******************************************
+ * osl_psz_setFileTime
+ *****************************************/
+
+static oslFileError osl_psz_setFileTime( const sal_Char* pszFilePath,
+ const TimeValue* /*pCreationTime*/,
+ const TimeValue* pLastAccessTime,
+ const TimeValue* pLastWriteTime )
+{
+ int nRet=0;
+ struct utimbuf aTimeBuffer;
+ struct stat aFileStat;
+#ifdef DEBUG_OSL_FILE
+ struct tm* pTM=0;
+#endif
+
+ nRet = lstat(pszFilePath,&aFileStat);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"File Times are (in localtime):\n");
+ pTM=localtime(&aFileStat.st_ctime);
+ fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM));
+ pTM=localtime(&aFileStat.st_atime);
+ fprintf(stderr,"AccessTime is '%s'\n",asctime(pTM));
+ pTM=localtime(&aFileStat.st_mtime);
+ fprintf(stderr,"Modification is '%s'\n",asctime(pTM));
+
+ fprintf(stderr,"File Times are (in UTC):\n");
+ fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime));
+ fprintf(stderr,"AccessTime is '%s'\n",ctime(&aTimeBuffer.actime));
+ fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime));
+#endif
+
+ if ( pLastAccessTime != 0 )
+ {
+ aTimeBuffer.actime=pLastAccessTime->Seconds;
+ }
+ else
+ {
+ aTimeBuffer.actime=aFileStat.st_atime;
+ }
+
+ if ( pLastWriteTime != 0 )
+ {
+ aTimeBuffer.modtime=pLastWriteTime->Seconds;
+ }
+ else
+ {
+ aTimeBuffer.modtime=aFileStat.st_mtime;
+ }
+
+ /* mfe: Creation time not used here! */
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"File Times are (in localtime):\n");
+ pTM=localtime(&aFileStat.st_ctime);
+ fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM));
+ pTM=localtime(&aTimeBuffer.actime);
+ fprintf(stderr,"AccessTime now '%s'\n",asctime(pTM));
+ pTM=localtime(&aTimeBuffer.modtime);
+ fprintf(stderr,"Modification now '%s'\n",asctime(pTM));
+
+ fprintf(stderr,"File Times are (in UTC):\n");
+ fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime));
+ fprintf(stderr,"AccessTime now '%s'\n",ctime(&aTimeBuffer.actime));
+ fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime));
+#endif
+
+ nRet=utime(pszFilePath,&aTimeBuffer);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+
+
+/*****************************************
+ * osl_psz_removeFile
+ ****************************************/
+#if 0
+static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
+{
+ int nRet=0;
+ struct stat aStat;
+
+ nRet = stat(pszPath,&aStat);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ if ( S_ISDIR(aStat.st_mode) )
+ {
+ return osl_File_E_ISDIR;
+ }
+
+ nRet = unlink(pszPath);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+#endif
+
+/*****************************************
+ * osl_psz_createDirectory
+ ****************************************/
+#if 0
+static oslFileError osl_psz_createDirectory( const sal_Char* pszPath )
+{
+ int nRet=0;
+ int mode = S_IRWXU | S_IRWXG | S_IRWXO;
+
+ nRet = mkdir(pszPath,mode);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+#endif
+/*****************************************
+ * osl_psz_removeDirectory
+ ****************************************/
+#if 0
+static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
+{
+ int nRet=0;
+
+ nRet = rmdir(pszPath);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+#endif
+/*****************************************
+ * oslDoMoveFile
+ ****************************************/
+#if 0
+static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
+{
+ oslFileError tErr=osl_File_E_invalidError;
+
+ tErr = osl_psz_moveFile(pszPath,pszDestPath);
+ if ( tErr == osl_File_E_None )
+ {
+ return tErr;
+ }
+
+ if ( tErr != osl_File_E_XDEV )
+ {
+ return tErr;
+ }
+
+ tErr=osl_psz_copyFile(pszPath,pszDestPath);
+
+ if ( tErr != osl_File_E_None )
+ {
+ oslFileError tErrRemove;
+ tErrRemove=osl_psz_removeFile(pszDestPath);
+ return tErr;
+ }
+
+ tErr=osl_psz_removeFile(pszPath);
+
+ return tErr;
+}
+#endif
+/*****************************************
+ * osl_psz_moveFile
+ ****************************************/
+#if 0
+static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
+{
+
+ int nRet = 0;
+
+ nRet = rename(pszPath,pszDestPath);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+#endif
+/*****************************************
+ * osl_psz_copyFile
+ ****************************************/
+#if 0
+static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
+{
+ time_t nAcTime=0;
+ time_t nModTime=0;
+ uid_t nUID=0;
+ gid_t nGID=0;
+ int nRet=0;
+ mode_t nMode=0;
+ struct stat aFileStat;
+ oslFileError tErr=osl_File_E_invalidError;
+ size_t nSourceSize=0;
+ int DestFileExists=1;
+
+ /* mfe: does the source file really exists? */
+ nRet = lstat(pszPath,&aFileStat);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ /* mfe: we do only copy files here! */
+ if ( S_ISDIR(aFileStat.st_mode) )
+ {
+ return osl_File_E_ISDIR;
+ }
+
+ nSourceSize=(size_t)aFileStat.st_size;
+ nMode=aFileStat.st_mode;
+ nAcTime=aFileStat.st_atime;
+ nModTime=aFileStat.st_mtime;
+ nUID=aFileStat.st_uid;
+ nGID=aFileStat.st_gid;
+
+ nRet = stat(pszDestPath,&aFileStat);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+
+ if ( nRet == ENOENT )
+ {
+ DestFileExists=0;
+ }
+/* return oslTranslateFileError(nRet);*/
+ }
+
+ /* mfe: the destination file must not be a directory! */
+ if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
+ {
+ return osl_File_E_ISDIR;
+ }
+ else
+ {
+ /* mfe: file does not exists or is no dir */
+ }
+
+ tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
+
+ if ( tErr != osl_File_E_None )
+ {
+ return tErr;
+ }
+
+ /*
+ * mfe: ignore return code
+ * since only the success of the copy is
+ * important
+ */
+ oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
+
+ return tErr;
+}
+#endif
+
+/******************************************************************************
+ *
+ * Utility Functions
+ *
+ *****************************************************************************/
+
+
+/*****************************************
+ * oslMakeUStrFromPsz
+ ****************************************/
+
+rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
+{
+ rtl_string2UString(
+ ustrValid,
+ pszStr,
+ rtl_str_getLength( pszStr ),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*ustrValid != 0);
+
+ return *ustrValid;
+}
+
+/*****************************************************************************
+ * UnicodeToText
+ * converting unicode to text manually saves us the penalty of a temporary
+ * rtl_String object.
+ ****************************************************************************/
+
+int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen )
+{
+ rtl_UnicodeToTextConverter hConverter;
+ sal_uInt32 nInfo;
+ sal_Size nSrcChars, nDestBytes;
+
+ /* stolen from rtl/string.c */
+ hConverter = rtl_createUnicodeToTextConverter( osl_getThreadTextEncoding() );
+
+ nDestBytes = rtl_convertUnicodeToText( hConverter, 0, uniText, uniTextLen,
+ buffer, bufLen,
+ OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH,
+ &nInfo, &nSrcChars );
+
+ rtl_destroyUnicodeToTextConverter( hConverter );
+
+ if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
+ {
+ errno = EOVERFLOW;
+ return 0;
+ }
+
+ /* ensure trailing '\0' */
+ buffer[nDestBytes] = '\0';
+
+ return nDestBytes;
+}
+
+/*****************************************************************************
+ TextToUnicode
+
+ @param text
+ The text to convert.
+
+ @param text_buffer_size
+ The number of characters.
+
+ @param unic_text
+ The unicode buffer.
+
+ @param unic_text_buffer_size
+ The size in characters of the unicode buffer.
+
+ ****************************************************************************/
+
+int TextToUnicode(
+ const char* text,
+ size_t text_buffer_size,
+ sal_Unicode* unic_text,
+ sal_Int32 unic_text_buffer_size)
+{
+ rtl_TextToUnicodeConverter hConverter;
+ sal_uInt32 nInfo;
+ sal_Size nSrcChars;
+ sal_Size nDestBytes;
+
+ /* stolen from rtl/string.c */
+ hConverter = rtl_createTextToUnicodeConverter(osl_getThreadTextEncoding());
+
+ nDestBytes = rtl_convertTextToUnicode(hConverter,
+ 0,
+ text, text_buffer_size,
+ unic_text, unic_text_buffer_size,
+ OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH,
+ &nInfo, &nSrcChars);
+
+ rtl_destroyTextToUnicodeConverter(hConverter);
+
+ if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
+ {
+ errno = EOVERFLOW;
+ return 0;
+ }
+
+ /* ensure trailing '\0' */
+ unic_text[nDestBytes] = '\0';
+
+ return nDestBytes;
+}
+
+/******************************************************************************
+ *
+ * GENERIC FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+
+/*****************************************
+ * osl_unmountVolumeDevice
+ ****************************************/
+
+oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ oslFileError tErr = osl_File_E_NOSYS;
+
+ tErr = osl_unmountFloppy(Handle);
+
+ /* Perhaps current working directory is set to mount point */
+
+ if ( tErr )
+ {
+ sal_Char *pszHomeDir = getenv("HOME");
+
+ if ( pszHomeDir && strlen( pszHomeDir ) && 0 == chdir( pszHomeDir ) )
+ {
+ /* try again */
+
+ tErr = osl_unmountFloppy(Handle);
+
+ OSL_ENSURE( tErr, "osl_unmountvolumeDevice: CWD was set to volume mount point" );
+ }
+ }
+
+ return tErr;
+}
+
+/*****************************************
+ * osl_automountVolumeDevice
+ ****************************************/
+
+oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ oslFileError tErr = osl_File_E_NOSYS;
+
+ tErr = osl_mountFloppy(Handle);
+
+ return tErr;
+}
+
+/*****************************************
+ * osl_getVolumeDeviceMountPath
+ ****************************************/
+
+oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
+{
+ oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle;
+ sal_Char Buffer[PATH_MAX];
+
+ Buffer[0] = '\0';
+
+ if ( pItem == 0 || pstrPath == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+ return osl_File_E_INVAL;
+ }
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"Handle is:\n");
+ osl_printFloppyHandle(pItem);
+#endif
+
+ snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint);
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"Mount Point is: '%s'\n",Buffer);
+#endif
+
+ oslMakeUStrFromPsz(Buffer, pstrPath);
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_acquireVolumeDeviceHandle
+ ****************************************/
+
+oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
+
+ if ( pItem == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ ++pItem->RefCount;
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_releaseVolumeDeviceHandle
+ ****************************************/
+
+oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
+
+ if ( pItem == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ --pItem->RefCount;
+
+ if ( pItem->RefCount == 0 )
+ {
+ rtl_freeMemory(pItem);
+ }
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_newVolumeDeviceHandleImpl
+ ****************************************/
+
+static oslVolumeDeviceHandleImpl* osl_newVolumeDeviceHandleImpl()
+{
+ oslVolumeDeviceHandleImpl* pHandle;
+ const size_t nSizeOfHandle = sizeof(oslVolumeDeviceHandleImpl);
+
+ pHandle = (oslVolumeDeviceHandleImpl*) rtl_allocateMemory (nSizeOfHandle);
+ if (pHandle != NULL)
+ {
+ pHandle->ident[0] = 'O';
+ pHandle->ident[1] = 'V';
+ pHandle->ident[2] = 'D';
+ pHandle->ident[3] = 'H';
+ pHandle->pszMountPoint[0] = '\0';
+ pHandle->pszFilePath[0] = '\0';
+ pHandle->pszDevice[0] = '\0';
+ pHandle->RefCount = 1;
+ }
+ return pHandle;
+}
+
+/*****************************************
+ * osl_freeVolumeDeviceHandleImpl
+ ****************************************/
+
+static void osl_freeVolumeDeviceHandleImpl (oslVolumeDeviceHandleImpl* pHandle)
+{
+ if (pHandle != NULL)
+ rtl_freeMemory (pHandle);
+}
+
+
+/******************************************************************************
+ *
+ * OS/2 FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+#if defined(OS2)
+static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath)
+{
+ return NULL;
+}
+
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ return osl_File_E_BUSY;
+}
+
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ return osl_File_E_BUSY;
+}
+
+static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem)
+{
+ return sal_False;
+}
+
+static sal_Bool osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice)
+{
+ return sal_False;
+}
+
+
+#ifdef DEBUG_OSL_FILE
+static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* pItem)
+{
+ if (pItem == 0 )
+ {
+ fprintf(stderr,"NULL Handle\n");
+ return;
+ }
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Invalid Handle]\n");
+#endif
+ return;
+ }
+
+
+ fprintf(stderr,"MountPoint : '%s'\n",pItem->pszMountPoint);
+ fprintf(stderr,"FilePath : '%s'\n",pItem->pszFilePath);
+ fprintf(stderr,"Device : '%s'\n",pItem->pszDevice);
+
+ return;
+}
+#endif
+
+#endif /* OS2 */
diff --git a/sal/osl/os2/file_error_transl.cxx b/sal/osl/os2/file_error_transl.cxx
new file mode 100644
index 000000000000..fd296d9dd3d2
--- /dev/null
+++ b/sal/osl/os2/file_error_transl.cxx
@@ -0,0 +1,252 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #ifndef _ERRNO_H
+ #include <errno.h>
+ #endif
+
+ #ifndef _FILE_ERROR_TRANSL_H_
+ #include "file_error_transl.h"
+ #endif
+
+ #ifndef _OSL_DIAGNOSE_H_
+ #include <osl/diagnose.h>
+ #endif
+
+
+/********************************************
+ * oslTranslateFileError
+ *******************************************/
+
+oslFileError oslTranslateFileError(sal_Bool bIsError, int Errno)
+{
+ oslFileError osl_error = osl_File_E_invalidError;
+
+ OSL_ENSURE((bIsError && (0 != Errno)) || (!bIsError && (0 == Errno)), "oslTranslateFileError strange input combination!");
+
+ /* Have a look at file_error_transl.h for
+ the reason that we do this here */
+ if (bIsError && (0 == Errno))
+ return osl_error;
+
+ switch(Errno)
+ {
+ case 0:
+ osl_error = osl_File_E_None;
+ break;
+
+ case EPERM:
+ osl_error = osl_File_E_PERM;
+ break;
+
+ case ENOENT:
+ osl_error = osl_File_E_NOENT;
+ break;
+
+ case ESRCH:
+ osl_error = osl_File_E_SRCH;
+ break;
+
+ case EINTR:
+ osl_error = osl_File_E_INTR;
+ break;
+
+ case EIO:
+ osl_error = osl_File_E_IO;
+ break;
+
+ case ENXIO:
+ osl_error = osl_File_E_IO;
+ break;
+
+ case E2BIG:
+ osl_error = osl_File_E_2BIG;
+ break;
+
+ case ENOEXEC:
+ osl_error = osl_File_E_NOEXEC;
+ break;
+
+ case EBADF:
+ osl_error = osl_File_E_BADF;
+ break;
+
+ case ECHILD:
+ osl_error = osl_File_E_CHILD;
+ break;
+
+ case EAGAIN:
+ osl_error = osl_File_E_AGAIN;
+ break;
+
+ case ENOMEM:
+ osl_error = osl_File_E_NOMEM;
+ break;
+
+ case EACCES:
+ osl_error = osl_File_E_ACCES;
+ break;
+
+ case EFAULT:
+ osl_error = osl_File_E_FAULT;
+ break;
+
+ case EBUSY:
+ osl_error = osl_File_E_BUSY;
+ break;
+
+ case EEXIST:
+ osl_error = osl_File_E_EXIST;
+ break;
+
+ case EXDEV:
+ osl_error = osl_File_E_XDEV;
+ break;
+
+ case ENODEV:
+ osl_error = osl_File_E_NODEV;
+ break;
+
+ case ENOTDIR:
+ osl_error = osl_File_E_NOTDIR;
+ break;
+
+ case EISDIR:
+ osl_error = osl_File_E_ISDIR;
+ break;
+
+ case EINVAL:
+ osl_error = osl_File_E_INVAL;
+ break;
+
+ case ENFILE:
+ osl_error = osl_File_E_NFILE;
+ break;
+
+ case EMFILE:
+ osl_error = osl_File_E_MFILE;
+ break;
+
+ case ENOTTY:
+ osl_error = osl_File_E_NOTTY;
+ break;
+
+ case EFBIG:
+ osl_error = osl_File_E_FBIG;
+ break;
+
+ case ENOSPC:
+ osl_error = osl_File_E_NOSPC;
+ break;
+
+ case ESPIPE:
+ osl_error = osl_File_E_SPIPE;
+ break;
+
+ case EROFS:
+ osl_error = osl_File_E_ROFS;
+ break;
+
+ case EMLINK:
+ osl_error = osl_File_E_MLINK;
+ break;
+
+ case EPIPE:
+ osl_error = osl_File_E_PIPE;
+ break;
+
+ case EDOM:
+ osl_error = osl_File_E_DOM;
+ break;
+
+ case ERANGE:
+ osl_error = osl_File_E_RANGE;
+ break;
+
+ case EDEADLK:
+ osl_error = osl_File_E_DEADLK;
+ break;
+
+ case ENAMETOOLONG:
+ osl_error = osl_File_E_NAMETOOLONG;
+ break;
+
+ case ENOLCK:
+ osl_error = osl_File_E_NOLCK;
+ break;
+
+ case ENOSYS:
+ osl_error = osl_File_E_NOSYS;
+ break;
+
+ case ENOTEMPTY:
+ osl_error = osl_File_E_NOTEMPTY;
+ break;
+
+ case ELOOP:
+ osl_error = osl_File_E_LOOP;
+ break;
+
+#if !(defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+ case EILSEQ:
+ osl_error = osl_File_E_ILSEQ;
+ break;
+#endif /* MACOSX */
+
+#if !(defined(MACOSX) || defined(NETBSD) || defined(FREEBSD) || defined(OS2))
+ case ENOLINK:
+ osl_error = osl_File_E_NOLINK;
+ break;
+#endif /* MACOSX */
+
+#if !(defined(MACOSX) || defined(NETBSD) || defined(FREEBSD) || defined(OS2))
+ case EMULTIHOP:
+ osl_error = osl_File_E_MULTIHOP;
+ break;
+#endif /* MACOSX */
+
+ case EUSERS:
+ osl_error = osl_File_E_USERS;
+ break;
+
+ case EOVERFLOW:
+ osl_error = osl_File_E_OVERFLOW;
+ break;
+
+ case ETIMEDOUT:
+ osl_error = osl_File_E_TIMEDOUT;
+ break;
+
+ default:
+ /* FIXME translateFileError: is this alright? Or add a new one: osl_File_E_Unknown? */
+ osl_error = osl_File_E_invalidError;
+ break;
+ }
+
+ return osl_error;
+}
+
diff --git a/sal/osl/os2/file_error_transl.h b/sal/osl/os2/file_error_transl.h
new file mode 100644
index 000000000000..59d7b1d9faec
--- /dev/null
+++ b/sal/osl/os2/file_error_transl.h
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _FILE_ERROR_TRANSL_H_
+#define _FILE_ERROR_TRANSL_H_
+
+#include <osl/file.h>
+#include <sal/types.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*********************************************
+ oslTranslateFileError
+ Translate errno's to osl file errors
+
+ @param bIsError [in] specifies if nErrno
+ should be interpreted as error,
+ some libc functions signaling an error
+ but errno is nevertheless 0 in this
+ case the function should at least
+ return osl_File_E_Unknown but in no
+ case osl_File_E_None!
+
+ @param nErrno [in] the errno if errno is 0
+ and bIsError is true the function
+ returns osl_File_E_Unknown
+
+ @returns the osl error code appropriate to
+ the errno
+
+ *********************************************/
+
+#define OSL_FET_SUCCESS sal_False
+#define OSL_FET_ERROR sal_True
+
+oslFileError oslTranslateFileError(sal_Bool bIsError, int Errno);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sal/osl/os2/file_path_helper.cxx b/sal/osl/os2/file_path_helper.cxx
new file mode 100644
index 000000000000..1aa5840deca4
--- /dev/null
+++ b/sal/osl/os2/file_path_helper.cxx
@@ -0,0 +1,377 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ /*******************************************
+ Includes
+ ******************************************/
+
+ #ifndef _OSL_THREAD_H_
+ #include "osl/thread.h"
+ #endif
+
+ #ifndef _OSL_FILE_PATH_HELPER_H_
+ #include "file_path_helper.h"
+ #endif
+
+ #ifndef _OSL_FILE_PATH_HELPER_HXX_
+ #include "file_path_helper.hxx"
+ #endif
+
+ #ifndef _OSL_UUNXAPI_HXX_
+ #include "uunxapi.hxx"
+ #endif
+
+ #ifndef _OSL_DIAGNOSE_H_
+ #include <osl/diagnose.h>
+ #endif
+
+ #ifndef _RTL_USTRING_HXX_
+ #include <rtl/ustring.hxx>
+ #endif
+
+ /*******************************************
+ Constants
+ ******************************************/
+
+ const sal_Unicode FPH_CHAR_PATH_SEPARATOR = (sal_Unicode)'\\';
+ const sal_Unicode FPH_CHAR_DOT = (sal_Unicode)'.';
+ const sal_Unicode FPH_CHAR_COLON = (sal_Unicode)':';
+
+ inline const rtl::OUString FPH_PATH_SEPARATOR()
+ { return rtl::OUString::createFromAscii("\\"); }
+ inline const rtl::OUString FPH_LOCAL_DIR_ENTRY()
+ { return rtl::OUString::createFromAscii("."); }
+ inline const rtl::OUString FPH_PARENT_DIR_ENTRY()
+ { return rtl::OUString::createFromAscii(".."); }
+
+ /*******************************************
+ * osl_systemPathRemoveSeparator
+ ******************************************/
+
+ void SAL_CALL osl_systemPathRemoveSeparator(rtl_uString* pustrPath)
+ {
+ OSL_PRECOND(pustrPath, "osl_systemPathRemoveSeparator: Invalid parameter");
+
+ // maybe there are more than one separator at end
+ // so we run in a loop
+ while ((pustrPath->length > 1) && (FPH_CHAR_PATH_SEPARATOR == pustrPath->buffer[pustrPath->length - 1]))
+ {
+ pustrPath->length--;
+ pustrPath->buffer[pustrPath->length] = (sal_Unicode)'\0';
+ }
+
+ OSL_POSTCOND((0 == pustrPath->length) || (1 == pustrPath->length) || \
+ (pustrPath->length > 1 && pustrPath->buffer[pustrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR), \
+ "osl_systemPathRemoveSeparator: Post condition failed");
+ }
+
+ /*******************************************
+ osl_systemPathEnsureSeparator
+ ******************************************/
+
+ void SAL_CALL osl_systemPathEnsureSeparator(rtl_uString** ppustrPath)
+ {
+ OSL_PRECOND(ppustrPath && (NULL != *ppustrPath), \
+ "osl_systemPathEnsureSeparator: Invalid parameter");
+
+ rtl::OUString path(*ppustrPath);
+ sal_Int32 lp = path.getLength();
+ sal_Int32 i = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
+
+ if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0))
+ {
+ path += FPH_PATH_SEPARATOR();
+ rtl_uString_assign(ppustrPath, path.pData);
+ }
+
+ OSL_POSTCOND(path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR) == (path.getLength() - 1), \
+ "osl_systemPathEnsureSeparator: Post condition failed");
+ }
+
+ /*******************************************
+ * osl_systemPathIsRelativePath
+ ******************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsRelativePath(const rtl_uString* pustrPath)
+ {
+ OSL_PRECOND(pustrPath, "osl_systemPathIsRelativePath: Invalid parameter");
+ return (!osl_systemPathIsAbsolutePath(pustrPath));
+ }
+
+ /******************************************
+ * osl_systemPathIsAbsolutePath
+ *****************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsAbsolutePath(const rtl_uString* pustrPath)
+ {
+ OSL_PRECOND(pustrPath, "osl_systemPathIsAbsolutePath: Invalid parameter");
+ if (pustrPath->length == 0)
+ return sal_False;
+ if (pustrPath->buffer[0] == FPH_CHAR_PATH_SEPARATOR)
+ return sal_True;
+ if (pustrPath->buffer[1] == FPH_CHAR_COLON
+ && pustrPath->buffer[2] == FPH_CHAR_PATH_SEPARATOR)
+ return sal_True;
+ return sal_False;
+ }
+
+ /******************************************
+ osl_systemPathMakeAbsolutePath
+ *****************************************/
+
+ void SAL_CALL osl_systemPathMakeAbsolutePath(
+ const rtl_uString* pustrBasePath,
+ const rtl_uString* pustrRelPath,
+ rtl_uString** ppustrAbsolutePath)
+{
+ rtl::OUString base(rtl_uString_getStr(const_cast<rtl_uString*>(pustrBasePath)));
+ rtl::OUString rel(const_cast<rtl_uString*>(pustrRelPath));
+
+ if (base.getLength() > 0)
+ osl_systemPathEnsureSeparator(&base.pData);
+
+ base += rel;
+
+ rtl_uString_acquire(base.pData);
+ *ppustrAbsolutePath = base.pData;
+}
+
+
+ /*****************************************
+ osl_systemPathGetParent
+ ****************************************/
+
+ sal_Int32 SAL_CALL osl_systemPathGetParent(rtl_uString* pustrPath)
+ {
+ return 0;
+ }
+
+ /*******************************************
+ osl_systemPathGetFileOrLastDirectoryPart
+ ******************************************/
+
+ void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart(
+ const rtl_uString* pustrPath,
+ rtl_uString** ppustrFileNameOrLastDirPart)
+{
+ OSL_PRECOND(pustrPath && ppustrFileNameOrLastDirPart, \
+ "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter");
+
+ rtl::OUString path(const_cast<rtl_uString*>(pustrPath));
+
+ osl_systemPathRemoveSeparator(path.pData);
+
+ rtl::OUString last_part;
+
+ if (path.getLength() > 1 || (1 == path.getLength() && *path.getStr() != FPH_CHAR_PATH_SEPARATOR))
+ {
+ sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
+ idx_ps++; // always right to increment by one even if idx_ps == -1!
+ last_part = rtl::OUString(path.getStr() + idx_ps);
+ }
+ rtl_uString_assign(ppustrFileNameOrLastDirPart, last_part.pData);
+}
+
+
+ /********************************************
+ osl_systemPathIsHiddenFileOrDirectoryEntry
+ *********************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry(
+ const rtl_uString* pustrPath)
+{
+ OSL_PRECOND(pustrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter");
+
+ sal_Bool is_hidden = sal_False;
+
+ if (pustrPath->length > 0)
+ {
+ rtl::OUString fdp;
+
+ osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &fdp.pData);
+
+ is_hidden = ((fdp.pData->length > 0) && (fdp.pData->buffer[0] == FPH_CHAR_DOT) &&
+ !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData));
+ }
+
+ return is_hidden;
+}
+
+
+ /************************************************
+ osl_systemPathIsLocalOrParentDirectoryEntry
+ ************************************************/
+
+sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry(
+ const rtl_uString* pustrPath)
+{
+ OSL_PRECOND(pustrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter");
+
+ rtl::OUString dirent;
+
+ osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &dirent.pData);
+
+ return (
+ (dirent == FPH_LOCAL_DIR_ENTRY()) ||
+ (dirent == FPH_PARENT_DIR_ENTRY())
+ );
+}
+
+/***********************************************
+ Simple iterator for a path list separated by
+ the specified character
+ **********************************************/
+
+class path_list_iterator
+{
+public:
+
+ /******************************************
+ constructor
+
+ after construction get_current_item
+ returns the first path in list, no need
+ to call reset first
+ *****************************************/
+ path_list_iterator(const rtl::OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) :
+ m_path_list(path_list),
+ m_end(m_path_list.getStr() + m_path_list.getLength() + 1),
+ m_separator(list_separator)
+ {
+ reset();
+ }
+
+ /******************************************
+ reset the iterator
+ *****************************************/
+ void reset()
+ {
+ m_path_segment_begin = m_path_segment_end = m_path_list.getStr();
+ advance();
+ }
+
+ /******************************************
+ move the iterator to the next position
+ *****************************************/
+ void next()
+ {
+ OSL_PRECOND(!done(), "path_list_iterator: Already done!");
+
+ m_path_segment_begin = ++m_path_segment_end;
+ advance();
+ }
+
+ /******************************************
+ check if done
+ *****************************************/
+ bool done() const
+ {
+ return (m_path_segment_end >= m_end);
+ }
+
+ /******************************************
+ return the current item
+ *****************************************/
+ rtl::OUString get_current_item() const
+ {
+ return rtl::OUString(
+ m_path_segment_begin,
+ (m_path_segment_end - m_path_segment_begin));
+ }
+
+private:
+
+ /******************************************
+ move m_path_end to the next separator or
+ to the edn of the string
+ *****************************************/
+ void advance()
+ {
+ while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator))
+ ++m_path_segment_end;
+
+ OSL_ASSERT(m_path_segment_end <= m_end);
+ }
+
+private:
+ rtl::OUString m_path_list;
+ const sal_Unicode* m_end;
+ const sal_Unicode m_separator;
+ const sal_Unicode* m_path_segment_begin;
+ const sal_Unicode* m_path_segment_end;
+
+// prevent copy and assignment
+private:
+ /******************************************
+ copy constructor
+ remember: do not simply copy m_path_begin
+ and m_path_end because they point to
+ the memory of other.m_path_list!
+ *****************************************/
+ path_list_iterator(const path_list_iterator& other);
+
+ /******************************************
+ assignment operator
+ remember: do not simply copy m_path_begin
+ and m_path_end because they point to
+ the memory of other.m_path_list!
+ *****************************************/
+ path_list_iterator& operator=(const path_list_iterator& other);
+};
+
+ /************************************************
+ osl_searchPath
+ ***********************************************/
+
+sal_Bool SAL_CALL osl_searchPath(
+ const rtl_uString* pustrFilePath,
+ const rtl_uString* pustrSearchPathList,
+ rtl_uString** ppustrPathFound)
+{
+ OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter");
+
+ bool bfound = false;
+ rtl::OUString fp(const_cast<rtl_uString*>(pustrFilePath));
+ rtl::OUString pl = rtl::OUString(const_cast<rtl_uString*>(pustrSearchPathList));
+ path_list_iterator pli(pl);
+
+ while (!pli.done())
+ {
+ rtl::OUString p = pli.get_current_item();
+ osl::systemPathEnsureSeparator(p);
+ p += fp;
+
+ if (osl::access(p, F_OK) > -1)
+ {
+ bfound = true;
+ rtl_uString_assign(ppustrPathFound, p.pData);
+ break;
+ }
+ pli.next();
+ }
+ return bfound;
+}
diff --git a/sal/osl/os2/file_path_helper.h b/sal/osl/os2/file_path_helper.h
new file mode 100644
index 000000000000..88b8ccbe9b6a
--- /dev/null
+++ b/sal/osl/os2/file_path_helper.h
@@ -0,0 +1,292 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #ifndef _OSL_FILE_PATH_HELPER_H_
+ #define _OSL_FILE_PATH_HELPER_H_
+
+
+ #ifndef _SAL_TYPES_H_
+ #include <sal/types.h>
+ #endif
+
+ #ifndef _RTL_USTRING_H_
+ #include <rtl/ustring.h>
+ #endif
+
+
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+
+
+ /*******************************************
+ osl_systemPathRemoveSeparator
+ Removes the last separator from the
+ given system path if any and if the path
+ is not the root path '/'
+
+ @param ppustrPath [inout] a system path
+ if the path is not the root path
+ and the last character is a
+ path separator it will be cut off
+ ppustrPath must not be NULL and
+ must point to a valid rtl_uString
+
+ @returns nothing
+
+ ******************************************/
+
+ void SAL_CALL osl_systemPathRemoveSeparator(
+ /*inout*/ rtl_uString* pustrPath);
+
+ /*******************************************
+ osl_systemPathEnsureSeparator
+ Adds a trailing path separator to the
+ given system path if not already there
+ and if the path is not the root path '/'
+
+ @param pustrPath [inout] a system path
+ if the path is not the root path
+ '/' and has no trailing separator
+ a separator will be added
+ ppustrPath must not be NULL and
+ must point to a valid rtl_uString
+
+ @returns nothing
+
+ ******************************************/
+
+ void SAL_CALL osl_systemPathEnsureSeparator(
+ /*inout*/ rtl_uString** ppustrPath);
+
+ /*******************************************
+ osl_systemPathIsRelativePath
+ Returns true if the given path is a
+ relative path and so starts not with '/'
+
+ @param pustrPath [in] a system path
+ pustrPath must not be NULL
+
+ @returns sal_True if the given path
+ doesn't start with a separator
+ else sal_False will be returned
+
+ ******************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsRelativePath(
+ const rtl_uString* pustrPath);
+
+ /******************************************
+ osl_systemPathIsAbsolutePath
+ Returns true if the given path is an
+ absolute path and so starts with a '/'
+
+ @param pustrPath [in] a system path
+ pustrPath must not be NULL
+
+ @returns sal_True if the given path
+ start's with a separator else
+ sal_False will be returned
+
+ *****************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsAbsolutePath(
+ const rtl_uString* pustrPath);
+
+ /******************************************
+ osl_systemPathMakeAbsolutePath
+ Append a relative path to a base path
+
+ @param pustrBasePath [in] a system
+ path that will be considered as
+ base path
+ pustrBasePath must not be NULL
+
+ @param pustrRelPath [in] a system path
+ that will be considered as
+ relative path
+ pustrBasePath must not be NULL
+
+ @param ppustrAbsolutePath [out] the
+ resulting path which is a
+ concatination of the base and
+ the relative path
+ if base path is empty the
+ resulting absolute path is the
+ relative path
+ if relative path is empty the
+ resulting absolute path is the
+ base path
+ if base and relative path are
+ empty the resulting absolute
+ path is also empty
+ ppustrAbsolutePath must not be
+ NULL and *ppustrAbsolutePath
+ must be 0 or point to a valid
+ rtl_uString
+
+ *****************************************/
+
+ void SAL_CALL osl_systemPathMakeAbsolutePath(
+ const rtl_uString* pustrBasePath,
+ const rtl_uString* pustrRelPath,
+ rtl_uString** ppustrAbsolutePath);
+
+ /*****************************************
+ osl_systemPathGetParent
+ Replaces the last occurrance of a path
+ separator with '\0' and returns the
+ position where the '/' was replaced
+
+ @param pustrPath [inout] a system
+ path, the last separator of
+ this path will be replaced by
+ a '\0'
+ if the path is the root path
+ '/' or the path is considered
+ as to have no parent, e.g.
+ '/NoParent' or 'NoParent' or
+ the path is empty no
+ replacement will be made
+ pustrPath must not be NULL
+
+ @returns the position of the last path
+ separator that was replaced
+ or 0 if no replacement took
+ place
+
+ ****************************************/
+
+ sal_Int32 SAL_CALL osl_systemPathGetParent(
+ /*inout*/ rtl_uString* pustrPath);
+
+ /*****************************************
+ osl_systemPathGetFileOrLastDirectoryPart
+ Returns the file or the directory part
+ of the given path
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @param ppustrFileOrDirPart [out] on
+ return receives the last part
+ of the given directory or the
+ file name
+ if pustrPath is the root path
+ '/' an empty string will be
+ returned
+ if pustrPath has a trailing
+ '/' the last part before the
+ '/' will be returned else
+ the part after the last '/'
+ will be returned
+
+ @returns nothing
+
+ ****************************************/
+ void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart(
+ const rtl_uString* pustrPath,
+ rtl_uString** ppustrFileNameOrLastDirPart);
+
+
+ /********************************************
+ osl_systemPathIsHiddenFileOrDirectoryEntry
+ Returns sal_True if the last part of
+ given system path is not '.' or '..'
+ alone and starts with a '.'
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @returns sal_True if the last part of
+ the given system path starts
+ with '.' or sal_False the last
+ part is '.' or '..' alone or
+ doesn't start with a dot
+
+ *********************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry(
+ const rtl_uString* pustrPath);
+
+
+ /************************************************
+ osl_systemPathIsLocalOrParentDirectoryEntry
+ Returns sal_True if the last part of the given
+ system path is the local directory entry '.'
+ or the parent directory entry '..'
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @returns sal_True if the last part of the
+ given system path is '.' or '..'
+ else sal_False
+
+ ************************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry(
+ const rtl_uString* pustrPath);
+
+
+ /************************************************
+ osl_searchPath
+ Searches for a file name or path name in all
+ directories specified by a given path list.
+ Symbolic links in the resulting path will not be
+ resolved, it's up to the caller to do this.
+
+ @param pustrFilePath [in] a file name or
+ directory name to search for, the name must
+ be provided as system path not as a file URL
+
+ @param pustrSearchPathList [in] a ':'
+ separated list of paths in which to search for
+ the file or directory name
+
+ @ppustrPathFound [out] on success receives the
+ complete path of the file or directory found
+ as a system path
+
+ @returns sal_True if the specified file or
+ directory was found else sal_False
+ ***********************************************/
+
+ sal_Bool SAL_CALL osl_searchPath(
+ const rtl_uString* pustrFilePath,
+ const rtl_uString* pustrSearchPathList,
+ rtl_uString** ppustrPathFound);
+
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+
+ #endif /* #ifndef _OSL_PATH_HELPER_H_ */
+
diff --git a/sal/osl/os2/file_path_helper.hxx b/sal/osl/os2/file_path_helper.hxx
new file mode 100644
index 000000000000..5310f462efc0
--- /dev/null
+++ b/sal/osl/os2/file_path_helper.hxx
@@ -0,0 +1,296 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_FILE_PATH_HELPER_HXX_
+#define _OSL_FILE_PATH_HELPER_HXX_
+
+
+#ifndef _OSL_FILE_PATH_HELPER_H_
+#include "file_path_helper.h"
+#endif
+
+#include <rtl/ustring.hxx>
+
+
+namespace osl
+{
+
+ /*******************************************
+ systemPathRemoveSeparator
+ Removes the last separator from the
+ given system path if any and if the path
+ is not the root path '/'
+
+ @param ppustrPath [inout] a system path
+ if the path is not the root path
+ and the last character is a
+ path separator it will be cut off
+ ppustrPath must not be NULL and
+ must point to a valid rtl_uString
+
+ @returns nothing
+
+ ******************************************/
+
+ inline void systemPathRemoveSeparator(/*inout*/ rtl::OUString& Path)
+ {
+ osl_systemPathRemoveSeparator(Path.pData);
+ }
+
+ /*******************************************
+ systemPathEnsureSeparator
+ Adds a trailing path separator to the
+ given system path if not already there
+ and if the path is not the root path '/'
+
+ @param pustrPath [inout] a system path
+ if the path is not the root path
+ '/' and has no trailing separator
+ a separator will be added
+ ppustrPath must not be NULL and
+ must point to a valid rtl_uString
+
+ @returns nothing
+
+ ******************************************/
+
+ inline void systemPathEnsureSeparator(/*inout*/ rtl::OUString& Path)
+ {
+ osl_systemPathEnsureSeparator(&Path.pData);
+ }
+
+ /*******************************************
+ systemPathIsRelativePath
+ Returns true if the given path is a
+ relative path and so starts not with '/'
+
+ @param pustrPath [in] a system path
+ pustrPath must not be NULL
+
+ @returns sal_True if the given path
+ doesn't start with a separator
+ else sal_False will be returned
+
+ ******************************************/
+
+ inline bool systemPathIsRelativePath(const rtl::OUString& Path)
+ {
+ return osl_systemPathIsRelativePath(Path.pData);
+ }
+
+ /******************************************
+ systemPathIsAbsolutePath
+ Returns true if the given path is an
+ absolute path and so starts with a '/'
+
+ @param pustrPath [in] a system path
+ pustrPath must not be NULL
+
+ @returns sal_True if the given path
+ start's with a separator else
+ sal_False will be returned
+
+ *****************************************/
+
+ inline bool systemPathIsAbsolutePath(const rtl::OUString& Path)
+ {
+ return osl_systemPathIsAbsolutePath(Path.pData);
+ }
+
+ /******************************************
+ systemPathMakeAbsolutePath
+ Append a relative path to a base path
+
+ @param pustrBasePath [in] a system
+ path that will be considered as
+ base path
+ pustrBasePath must not be NULL
+
+ @param pustrRelPath [in] a system path
+ that will be considered as
+ relative path
+ pustrBasePath must not be NULL
+
+ @param ppustrAbsolutePath [out] the
+ resulting path which is a
+ concatination of the base and
+ the relative path
+ if base path is empty the
+ resulting absolute path is the
+ relative path
+ if relative path is empty the
+ resulting absolute path is the
+ base path
+ if base and relative path are
+ empty the resulting absolute
+ path is also empty
+ ppustrAbsolutePath must not be
+ NULL and *ppustrAbsolutePath
+ must be 0 or point to a valid
+ rtl_uString
+
+ *****************************************/
+
+ inline void systemPathMakeAbsolutePath(
+ const rtl::OUString& BasePath,
+ const rtl::OUString& RelPath,
+ rtl::OUString& AbsolutePath)
+ {
+ osl_systemPathMakeAbsolutePath(
+ BasePath.pData, RelPath.pData, &AbsolutePath.pData);
+ }
+
+ /*****************************************
+ systemPathGetParent
+ Replaces the last occurrance of a path
+ separator with '\0' and returns the
+ position where the '/' was replaced
+
+ @param pustrPath [inout] a system
+ path, the last separator of
+ this path will be replaced by
+ a '\0'
+ if the path is the root path
+ '/' or the path is considered
+ as to have no parent, e.g.
+ '/NoParent' or 'NoParent' or
+ the path is empty no
+ replacement will be made
+ pustrPath must not be NULL
+
+ @returns the position of the last path
+ separator that was replaced
+ or 0 if no replacement took
+ place
+
+ ****************************************/
+
+ inline sal_Int32 systemPathGetParent(/*inout*/ rtl::OUString& Path)
+ {
+ return osl_systemPathGetParent(Path.pData);
+ }
+
+ /*****************************************
+ systemPathGetFileOrLastDirectoryPart
+ Returns the file or the directory part
+ of the given path
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @param ppustrFileOrDirPart [out] on
+ return receives the last part
+ of the given directory or the
+ file name
+ if pustrPath is the root path
+ '/' an empty string will be
+ returned
+ if pustrPath has a trailing
+ '/' the last part before the
+ '/' will be returned else
+ the part after the last '/'
+ will be returned
+
+ @returns nothing
+
+ ****************************************/
+
+ inline void systemPathGetFileNameOrLastDirectoryPart(
+ const rtl::OUString& Path,
+ rtl::OUString& FileNameOrLastDirPart)
+ {
+ osl_systemPathGetFileNameOrLastDirectoryPart(
+ Path.pData, &FileNameOrLastDirPart.pData);
+ }
+
+
+ /********************************************
+ systemPathIsHiddenFileOrDirectoryEntry
+ Returns sal_True if the last part of
+ given system path is not '.' or '..'
+ alone and starts with a '.'
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @returns sal_True if the last part of
+ the given system path starts
+ with '.' or sal_False the last
+ part is '.' or '..' alone or
+ doesn't start with a dot
+
+ *********************************************/
+
+ inline bool systemPathIsHiddenFileOrDirectoryEntry(
+ const rtl::OUString& Path)
+ {
+ return osl_systemPathIsHiddenFileOrDirectoryEntry(Path.pData);
+ }
+
+
+ /************************************************
+ systemPathIsLocalOrParentDirectoryEntry
+ Returns sal_True if the last part of the given
+ system path is the local directory entry '.'
+ or the parent directory entry '..'
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @returns sal_True if the last part of the
+ given system path is '.' or '..'
+ else sal_False
+
+ ************************************************/
+
+ inline bool systemPathIsLocalOrParentDirectoryEntry(
+ const rtl::OUString& Path)
+ {
+ return osl_systemPathIsLocalOrParentDirectoryEntry(Path.pData);
+ }
+
+ /************************************************
+ searchPath
+ ***********************************************/
+
+ inline bool searchPath(
+ const rtl::OUString& ustrFilePath,
+ const rtl::OUString& ustrSearchPathList,
+ rtl::OUString& ustrPathFound)
+ {
+ return osl_searchPath(
+ ustrFilePath.pData,
+ ustrSearchPathList.pData,
+ &ustrPathFound.pData);
+ }
+
+
+ } // namespace osl
+
+
+ #endif /* #ifndef _OSL_PATH_HELPER_HXX_ */
+
diff --git a/sal/osl/os2/file_url.cxx b/sal/osl/os2/file_url.cxx
new file mode 100644
index 000000000000..e3b5fbf00c48
--- /dev/null
+++ b/sal/osl/os2/file_url.cxx
@@ -0,0 +1,1626 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <ctype.h>
+#include "system.h"
+
+#ifndef _LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef _ERRNO_H
+#include <errno.h>
+#endif
+
+#ifndef _STDLIB_H_
+#include <stdlib.h>
+#endif
+
+#ifndef _STRINGS_H
+#include <strings.h>
+#endif
+
+#ifndef _UNISTD_H
+#include <unistd.h>
+#endif
+#include <osl/file.h>
+#include <osl/security.h>
+#include <rtl/uri.h>
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.h>
+
+#ifndef _OSL_TREAD_H_
+#include <osl/thread.h>
+#endif
+#include <osl/file.hxx>
+#include <osl/mutex.h>
+#include <osl/process.h>
+#include "file_error_transl.h"
+
+#ifndef _FILE_URL_H_
+#include "file_url.h"
+#endif
+#include "file_path_helper.hxx"
+
+#ifndef _OSL_UUNXAPI_HXX_
+#include "uunxapi.hxx"
+#endif
+
+#include <wchar.h>
+#include <wctype.h>
+
+/***************************************************
+
+ General note
+
+ This file contains the part that handles File URLs.
+
+ File URLs as scheme specific notion of URIs
+ (RFC2396) may be handled platform independend, but
+ will not in osl which is considered wrong.
+ Future version of osl should handle File URLs this
+ way. In rtl/uri there is already an URI parser etc.
+ so this code should be consolidated.
+
+ **************************************************/
+
+oslMutex g_CurrentDirectoryMutex;
+
+
+/***************************************************
+ * forward
+ **************************************************/
+
+void _osl_warnFile(const char*, rtl_uString*);
+rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr);
+
+extern "C" int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32);
+extern "C" int TextToUnicode(const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size);
+
+/***************************************************
+ * namespace directives
+ **************************************************/
+
+using namespace osl;
+
+/******************************************************************************
+ *
+ * Exported Module Functions
+ *
+ *****************************************************************************/
+
+/* a slightly modified version of Pchar in rtl/source/uri.c */
+const sal_Bool uriCharClass[128] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */
+};
+
+
+/* check for top wrong usage strings */
+/*
+static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len )
+{
+ rtl_uString *pTmp = NULL;
+ sal_Bool bRet;
+
+ rtl_uString_newFromStr_WithLength( &pTmp, path, len );
+
+ rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length );
+
+ bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) );
+
+ rtl_uString_release( pTmp );
+ return bRet;
+}
+*/
+
+
+/****************************************************************************/
+/* osl_getFileURLFromSystemPath */
+/****************************************************************************/
+
+BOOL WINAPI IsValidFilePathComponent(
+ LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags)
+{
+ LPCTSTR lpComponentEnd = NULL;
+ LPCTSTR lpCurrent = lpComponent;
+ BOOL fValid = TRUE; /* Assume success */
+ TCHAR cLast = 0;
+
+ /* Path component length must not exceed MAX_PATH */
+
+ while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < _MAX_PATH )
+ {
+ switch ( *lpCurrent )
+ {
+ /* Both backslash and slash determine the end of a path component */
+ case '\0':
+ case '/':
+ case '\\':
+ switch ( cLast )
+ {
+ /* Component must not end with '.' or blank and can't be empty */
+
+ case '.':
+ if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE )
+ {
+ if ( 1 == lpCurrent - lpComponent )
+ {
+ /* Current directory is O.K. */
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent )
+ {
+ /* Parent directory is O.K. */
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ }
+ case 0:
+ case ' ':
+ lpComponentEnd = lpCurrent - 1;
+ fValid = FALSE;
+ break;
+ default:
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ break;
+ /* '?' and '*' are valid wildcards but not valid file name characters */
+ case '?':
+ case '*':
+ if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS )
+ break;
+ /* The following characters are reserved */
+ case '<':
+ case '>':
+ case '\"':
+ case '|':
+ case ':':
+ lpComponentEnd = lpCurrent;
+ fValid = FALSE;
+ break;
+ default:
+ /* Characters below ASCII 32 are not allowed */
+ if ( *lpCurrent < ' ' )
+ {
+ lpComponentEnd = lpCurrent;
+ fValid = FALSE;
+ }
+ break;
+ }
+ cLast = *lpCurrent++;
+ }
+
+ /* If we don't reached the end of the component the length of the component was to long
+ ( See condition of while loop ) */
+ if ( !lpComponentEnd )
+ {
+ fValid = FALSE;
+ lpComponentEnd = lpCurrent;
+ }
+
+ /* Test wether the component specifies a device name what is not allowed */
+
+ // MT: PERFORMANCE:
+ // This is very expensive. A lot of calls to _tcsicmp.
+ // in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp!
+ // Possible optimizations
+ // - Array should be const static
+ // - Sorted array, use binary search
+ // - More intelligent check for com1-9, lpt1-9
+ // Maybe make szComponent upper case, don't search case intensitive
+ // Talked to HRO: Could be removed. Shouldn't be used in OOo, and if used for something like a filename, it will lead to an error anyway.
+ /*
+ if ( fValid )
+ {
+ LPCTSTR alpDeviceNames[] =
+ {
+ TEXT("CON"),
+ TEXT("PRN"),
+ TEXT("AUX"),
+ TEXT("CLOCK$"),
+ TEXT("NUL"),
+ TEXT("LPT1"),
+ TEXT("LPT2"),
+ TEXT("LPT3"),
+ TEXT("LPT4"),
+ TEXT("LPT5"),
+ TEXT("LPT6"),
+ TEXT("LPT7"),
+ TEXT("LPT8"),
+ TEXT("LPT9"),
+ TEXT("COM1"),
+ TEXT("COM2"),
+ TEXT("COM3"),
+ TEXT("COM4"),
+ TEXT("COM5"),
+ TEXT("COM6"),
+ TEXT("COM7"),
+ TEXT("COM8"),
+ TEXT("COM9")
+ };
+
+ TCHAR szComponent[MAX_PATH];
+ int nComponentLength;
+ LPCTSTR lpDot;
+ int i;
+
+ // A device name with an extension is also invalid
+ lpDot = _tcschr( lpComponent, '.' );
+
+ if ( !lpDot || lpDot > lpComponentEnd )
+ nComponentLength = lpComponentEnd - lpComponent;
+ else
+ nComponentLength = lpDot - lpComponent;
+
+ _tcsncpy( szComponent, lpComponent, nComponentLength );
+ szComponent[nComponentLength] = 0;
+
+ for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ )
+ {
+ if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) )
+ {
+ lpComponentEnd = lpComponent;
+ fValid = FALSE;
+ break;
+ }
+ }
+ }
+ */
+
+ if ( fValid )
+ {
+ // Empty components are not allowed
+ if ( lpComponentEnd - lpComponent < 1 )
+ fValid = FALSE;
+
+ // If we reached the end of the string NULL is returned
+ else if ( !*lpComponentEnd )
+ lpComponentEnd = NULL;
+
+ }
+
+ if ( lppComponentEnd )
+ *lppComponentEnd = lpComponentEnd;
+
+ return fValid;
+}
+
+//#####################################################
+DWORD WINAPI IsValidFilePath(LPCTSTR lpszPath, LPCTSTR *lppError, DWORD dwFlags)
+{
+ LPCTSTR lpComponent;
+ BOOL fValid = TRUE;
+ DWORD dwPathType = PATHTYPE_ERROR;
+
+ if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
+ dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE;
+
+ if ( !lpszPath )
+ {
+ fValid = FALSE;
+ lpComponent = lpszPath;
+ }
+
+ /* Test for UNC path notation */
+ if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) )
+ {
+ /* Place the pointer behind the leading to backslashes */
+
+ lpComponent = lpszPath + 2;
+
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE );
+
+ /* So far we have a valid servername. Now let's see if we also have a network resource */
+
+ dwPathType = PATHTYPE_ABSOLUTE_UNC;
+
+ if ( fValid )
+ {
+ if ( lpComponent && !*++lpComponent )
+ lpComponent = NULL;
+
+ if ( !lpComponent )
+ {
+#if 0
+ /* We only have a Server specification what is invalid */
+
+ lpComponent = lpszPath;
+ fValid = FALSE;
+#else
+ dwPathType |= PATHTYPE_IS_SERVER;
+#endif
+ }
+ else
+ {
+ /* Now test the network resource */
+
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 );
+
+ /* If we now reached the end of the path, everything is O.K. */
+
+
+ if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) )
+ {
+ lpComponent = NULL;
+ dwPathType |= PATHTYPE_IS_VOLUME;
+ }
+ }
+ }
+ }
+
+ /* Local path verification. Must start with <drive>: */
+ else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] )
+ {
+ /* Place pointer behind correct drive specification */
+
+ lpComponent = lpszPath + 2;
+
+ if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
+ lpComponent++;
+ else if ( *lpComponent )
+ fValid = FALSE;
+
+ dwPathType = PATHTYPE_ABSOLUTE_LOCAL;
+
+ /* Now we are behind the backslash or it was a simple drive without backslash */
+
+ if ( fValid && !*lpComponent )
+ {
+ lpComponent = NULL;
+ dwPathType |= PATHTYPE_IS_VOLUME;
+ }
+ }
+
+ /* Can be a relative path */
+ else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
+ {
+ lpComponent = lpszPath;
+
+ /* Relative path can start with a backslash */
+
+ if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
+ {
+ lpComponent++;
+ if ( !*lpComponent )
+ lpComponent = NULL;
+ }
+
+ dwPathType = PATHTYPE_RELATIVE;
+ }
+
+ /* Anything else is an error */
+ else
+ {
+ fValid = FALSE;
+ lpComponent = lpszPath;
+ }
+
+ /* Now validate each component of the path */
+ while ( fValid && lpComponent )
+ {
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags );
+
+ if ( fValid && lpComponent )
+ {
+ lpComponent++;
+
+ /* If the string behind the backslash is empty, we've done */
+
+ if ( !*lpComponent )
+ lpComponent = NULL;
+ }
+ }
+
+ if ( fValid && _tcslen( lpszPath ) >= _MAX_PATH )
+ {
+ fValid = FALSE;
+ lpComponent = lpszPath + _MAX_PATH;
+ }
+
+ if ( lppError )
+ *lppError = lpComponent;
+
+ return fValid ? dwPathType : PATHTYPE_ERROR;
+}
+
+sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL )
+{
+ sal_Char *pBuffer;
+ const sal_Char *pSrcEnd;
+ const sal_Char *pSrc;
+ sal_Char *pDest;
+ sal_Int32 nSrcLen;
+ sal_Bool bValidEncoded = sal_True; /* Assume success */
+
+ /* The resulting decoded string length is shorter or equal to the source length */
+
+ nSrcLen = rtl_string_getLength(strUTF8);
+ pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1));
+
+ pDest = pBuffer;
+ pSrc = rtl_string_getStr(strUTF8);
+ pSrcEnd = pSrc + nSrcLen;
+
+ /* Now decode the URL what should result in an UTF8 string */
+ while ( bValidEncoded && pSrc < pSrcEnd )
+ {
+ switch ( *pSrc )
+ {
+ case '%':
+ {
+ sal_Char aToken[3];
+ sal_Char aChar;
+
+ pSrc++;
+ aToken[0] = *pSrc++;
+ aToken[1] = *pSrc++;
+ aToken[2] = 0;
+
+ aChar = (sal_Char)strtoul( aToken, NULL, 16 );
+
+ /* The chars are path delimiters and must not be encoded */
+
+ if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar )
+ bValidEncoded = sal_False;
+ else
+ *pDest++ = aChar;
+ }
+ break;
+ default:
+ *pDest++ = *pSrc++;
+ break;
+ }
+ }
+
+ *pDest++ = 0;
+
+ if ( bValidEncoded ) {
+ rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pstrDecodedURL != 0);
+ }
+
+ rtl_freeMemory( pBuffer );
+
+ return bValidEncoded;
+}
+
+//#############################################
+void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL )
+{
+ /* Encode non ascii characters within the URL */
+
+ rtl_String *strUTF8 = NULL;
+ sal_Char *pszEncodedURL;
+ const sal_Char *pURLScan;
+ sal_Char *pURLDest;
+ sal_Int32 nURLScanLen;
+ sal_Int32 nURLScanCount;
+
+ rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1) * sizeof(sal_Char) );
+
+ pURLDest = pszEncodedURL;
+ pURLScan = rtl_string_getStr( strUTF8 );
+ nURLScanLen = rtl_string_getLength( strUTF8 );
+ nURLScanCount = 0;
+
+ while ( nURLScanCount < nURLScanLen )
+ {
+ sal_Char cCurrent = *pURLScan;
+
+ switch ( cCurrent )
+ {
+ default:
+ if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) )
+ {
+ sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent );
+ pURLDest += 3;
+ break;
+ }
+ case '!':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '-':
+ case '.':
+ case '_':
+ case '~':
+ case '$':
+ case '&':
+ case '+':
+ case ',':
+ case '=':
+ case '@':
+ case ':':
+ case '/':
+ case '\\':
+ case '|':
+ *pURLDest++ = cCurrent;
+ break;
+ case 0:
+ break;
+ }
+
+ pURLScan++;
+ nURLScanCount++;
+ }
+
+
+ *pURLDest = 0;
+
+ rtl_string_release( strUTF8 );
+ rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL );
+ rtl_freeMemory( pszEncodedURL );
+}
+
+//#############################################
+oslFileError SAL_CALL _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL )
+{
+ oslFileError nError = osl_File_E_INVAL; /* Assume failure */
+ rtl_uString *strTempURL = NULL;
+ DWORD dwPathType = PATHTYPE_ERROR;
+
+ if (strPath)
+ dwPathType = IsValidFilePath(strPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE);
+
+ if (dwPathType)
+ {
+ rtl_uString *strTempPath = NULL;
+
+ /* Replace backslashes */
+
+ rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
+
+ switch ( dwPathType & PATHTYPE_MASK_TYPE )
+ {
+ case PATHTYPE_RELATIVE:
+ rtl_uString_assign( &strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ case PATHTYPE_ABSOLUTE_UNC:
+ rtl_uString_newFromAscii( &strTempURL, "file:" );
+ rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ case PATHTYPE_ABSOLUTE_LOCAL:
+ rtl_uString_newFromAscii( &strTempURL, "file:///" );
+ rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ default:
+ break;
+ }
+
+ /* Release temp path */
+
+ rtl_uString_release( strTempPath );
+ }
+
+ if ( osl_File_E_None == nError )
+ {
+ rtl_String *strEncodedURL = NULL;
+
+ /* Encode the URL */
+
+ _osl_encodeURL( strTempURL, &strEncodedURL );
+
+ /* Provide URL via unicode string */
+
+ rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pstrURL != 0);
+ rtl_string_release( strEncodedURL );
+ }
+
+ /* Release temp URL */
+
+ if ( strTempURL )
+ rtl_uString_release( strTempURL );
+
+ /*
+ OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath );
+ */
+
+ return nError;
+}
+
+oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL )
+{
+ return _osl_getFileURLFromSystemPath( ustrSystemPath, pustrFileURL );
+#if 0
+ static const sal_Unicode pDoubleSlash[2] = { '/', '/' };
+
+ rtl_uString *pTmp = NULL;
+ sal_Int32 nIndex;
+
+ if( 0 == ustrSystemPath->length )
+ return osl_File_E_INVAL;
+
+ /* YD convert '\' to '/' */
+ rtl_ustr_replaceChar( ustrSystemPath->buffer, '\\', '/' );
+
+ /* temporary hack: if already file url, return ustrSystemPath */
+ if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file:", 5 ) )
+ {
+ /*
+ if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file://", 7 ) )
+ {
+ OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is already file URL" );
+ rtl_uString_assign( pustrFileURL, ustrSystemPath );
+ }
+ else
+ {
+ rtl_uString *pTmp2 = NULL;
+
+ OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is wrong file URL" );
+ rtl_uString_newFromStr_WithLength( pustrFileURL, ustrSystemPath->buffer + 5, ustrSystemPath->length - 5 );
+ rtl_uString_newFromAscii( &pTmp2, "file://" );
+ rtl_uString_newConcat( pustrFileURL, *pustrFileURL, pTmp2 );
+ rtl_uString_release( pTmp2 );
+ }
+ return osl_File_E_None;
+ */
+ return osl_File_E_INVAL;
+ }
+
+
+ /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
+ if( (sal_Unicode) '~' == ustrSystemPath->buffer[0] )
+ {
+ /* check if another user is specified */
+ if( ( 1 == ustrSystemPath->length ) || ( (sal_Unicode)'/' == ustrSystemPath->buffer[1] ) )
+ {
+ /* osl_getHomeDir returns file URL */
+ osl_getHomeDir( osl_getCurrentSecurity(), &pTmp );
+
+ /* remove "file://" prefix */
+ rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + 7, pTmp->length - 7 );
+
+ /* replace '~' in original string */
+ rtl_uString_newReplaceStrAt( &pTmp, ustrSystemPath, 0, 1, pTmp );
+ }
+
+ else
+ {
+ /* FIXME: replace ~user with users home directory */
+ return osl_File_E_INVAL;
+ }
+ }
+
+ /* check if initial string contains double instances of '/' */
+ nIndex = rtl_ustr_indexOfStr_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, pDoubleSlash, 2 );
+ if( -1 != nIndex )
+ {
+ sal_Int32 nSrcIndex;
+ sal_Int32 nDeleted = 0;
+
+ /* if pTmp is not already allocated, copy ustrSystemPath for modification */
+ if( NULL == pTmp )
+ rtl_uString_newFromString( &pTmp, ustrSystemPath );
+
+ /* adapt index to pTmp */
+ nIndex += pTmp->length - ustrSystemPath->length;
+
+ /* remove all occurances of '//' */
+ for( nSrcIndex = nIndex + 1; nSrcIndex < pTmp->length; nSrcIndex++ )
+ {
+ if( ((sal_Unicode) '/' == pTmp->buffer[nSrcIndex]) && ((sal_Unicode) '/' == pTmp->buffer[nIndex]) )
+ nDeleted++;
+ else
+ pTmp->buffer[++nIndex] = pTmp->buffer[nSrcIndex];
+ }
+
+ /* adjust length member */
+ pTmp->length -= nDeleted;
+ }
+
+ if( NULL == pTmp )
+ rtl_uString_assign( &pTmp, ustrSystemPath );
+
+ /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
+ /*
+ OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
+ */
+
+ /* file URLs must be URI encoded */
+ rtl_uriEncode( pTmp, uriCharClass, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8, pustrFileURL );
+
+ rtl_uString_release( pTmp );
+
+ /* absolute urls should start with 'file://' */
+ if( (sal_Unicode)'/' == (*pustrFileURL)->buffer[0] )
+ {
+ rtl_uString *pProtocol = NULL;
+
+ rtl_uString_newFromAscii( &pProtocol, "file://" );
+ rtl_uString_newConcat( pustrFileURL, pProtocol, *pustrFileURL );
+ rtl_uString_release( pProtocol );
+ }
+
+ return osl_File_E_None;
+#endif
+}
+
+//#############################################
+oslFileError SAL_CALL _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative )
+{
+ rtl_String *strUTF8 = NULL;
+ rtl_uString *strDecodedURL = NULL;
+ rtl_uString *strTempPath = NULL;
+ const sal_Unicode *pDecodedURL;
+ sal_uInt32 nDecodedLen;
+ sal_Bool bValidEncoded;
+ oslFileError nError = osl_File_E_INVAL; /* Assume failure */
+
+ /* If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from
+ having a mixed encoded URL later */
+
+ rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */
+
+ OSL_ENSURE_FILE(
+ strUTF8->length == strURL->length ||
+ 0 != rtl_ustr_ascii_shortenedCompare_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 )
+ ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL );
+
+ bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL );
+
+ /* Release the encoded UTF8 string */
+
+ rtl_string_release( strUTF8 );
+
+
+ if ( bValidEncoded )
+ {
+ /* Replace backslashes and pipes */
+
+ rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' );
+ rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' );
+
+ pDecodedURL = rtl_uString_getStr( strDecodedURL );
+ nDecodedLen = rtl_uString_getLength( strDecodedURL );
+
+ /* Must start with "file://" */
+
+ if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) )
+ {
+ sal_uInt32 nSkip;
+
+ if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) )
+ nSkip = 8;
+ else if (
+ 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) ||
+ 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 )
+ )
+ nSkip = 17;
+ else
+ nSkip = 5;
+
+ /* Indicates local root */
+ if ( nDecodedLen == nSkip )
+ rtl_uString_newFromStr_WithLength( &strTempPath, (const sal_Unicode*)WSTR_SYSTEM_ROOT_PATH, ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 );
+ else
+ rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip );
+
+ if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_ELLIPSE ) )
+ nError = osl_File_E_None;
+ }
+ else if ( bAllowRelative ) /* This maybe a relative file URL */
+ {
+ rtl_uString_assign( &strTempPath, strDecodedURL );
+
+ if ( IsValidFilePath( strTempPath->buffer, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE ) )
+ nError = osl_File_E_None;
+ }
+ /*
+ else
+ OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL );
+ */
+
+ }
+
+ if ( strDecodedURL )
+ rtl_uString_release( strDecodedURL );
+
+ if ( osl_File_E_None == nError )
+ rtl_uString_assign( pustrPath, strTempPath );
+
+ if ( strTempPath )
+ rtl_uString_release( strTempPath );
+
+ /*
+ OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL );
+ */
+
+ return nError;
+}
+
+/****************************************************************************/
+/* osl_getSystemPathFromFileURL */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath )
+{
+ return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, sal_True );
+#if 0
+ sal_Int32 nIndex = 0;
+ rtl_uString * pTmp = NULL;
+
+ sal_Unicode encodedSlash[3] = { '%', '2', 'F' };
+
+ /* temporary hack: if already system path, return ustrFileURL */
+ /*
+ if( (sal_Unicode) '/' == ustrFileURL->buffer[0] )
+ {
+ OSL_ENSURE( 0, "osl_getSystemPathFromFileURL: input is already system path" );
+ rtl_uString_assign( pustrSystemPath, ustrFileURL );
+ return osl_File_E_None;
+ }
+ */
+
+ /* a valid file url may not start with '/' */
+ if( ( 0 == ustrFileURL->length ) || ( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ /* search for encoded slashes (%2F) and decode every single token if we find one */
+ if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, encodedSlash, 3 ) )
+ {
+ rtl_uString * ustrPathToken = NULL;
+ sal_Int32 nOffset = 7;
+
+ do
+ {
+ nOffset += nIndex;
+
+ /* break url down in '/' devided tokens tokens */
+ nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, (sal_Unicode) '/' );
+
+ /* copy token to new string */
+ rtl_uString_newFromStr_WithLength( &ustrPathToken, ustrFileURL->buffer + nOffset,
+ -1 == nIndex ? ustrFileURL->length - nOffset : nIndex++ );
+
+ /* decode token */
+ rtl_uriDecode( ustrPathToken, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
+
+ /* the result should not contain any '/' */
+ if( -1 != rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, (sal_Unicode) '/' ) )
+ {
+ rtl_uString_release( pTmp );
+ rtl_uString_release( ustrPathToken );
+
+ return osl_File_E_INVAL;
+ }
+
+ } while( -1 != nIndex );
+
+ /* release temporary string and restore index variable */
+ rtl_uString_release( ustrPathToken );
+ nIndex = 0;
+ }
+
+ /* protocol and server should not be encoded, so decode the whole string */
+ rtl_uriDecode( ustrFileURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
+
+ /* check if file protocol specified */
+ /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
+ if( 7 <= pTmp->length )
+ {
+ rtl_uString * pProtocol = NULL;
+ rtl_uString_newFromStr_WithLength( &pProtocol, pTmp->buffer, 7 );
+
+ /* protocol is case insensitive */
+ rtl_ustr_toAsciiLowerCase_WithLength( pProtocol->buffer, pProtocol->length );
+
+ if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pProtocol->buffer, pProtocol->length,"file://", 7 ) )
+ nIndex = 7;
+
+ rtl_uString_release( pProtocol );
+ }
+
+ /* skip "localhost" or "127.0.0.1" if "file://" is specified */
+ /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
+ if( nIndex && ( 10 <= pTmp->length - nIndex ) )
+ {
+ rtl_uString * pServer = NULL;
+ rtl_uString_newFromStr_WithLength( &pServer, pTmp->buffer + nIndex, 10 );
+
+ /* server is case insensitive */
+ rtl_ustr_toAsciiLowerCase_WithLength( pServer->buffer, pServer->length );
+
+ if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"localhost/", 10 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"127.0.0.1/", 10 ) ) )
+ {
+ /* don't exclude the '/' */
+ nIndex += 9;
+ }
+
+ rtl_uString_release( pServer );
+ }
+
+ if( nIndex )
+ rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex );
+
+ /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
+ if( (sal_Unicode) '~' == pTmp->buffer[0] )
+ {
+ /* check if another user is specified */
+ if( ( 1 == pTmp->length ) || ( (sal_Unicode)'/' == pTmp->buffer[1] ) )
+ {
+ rtl_uString *pTmp2 = NULL;
+
+ /* osl_getHomeDir returns file URL */
+ osl_getHomeDir( osl_getCurrentSecurity(), &pTmp2 );
+
+ /* remove "file://" prefix */
+ rtl_uString_newFromStr_WithLength( &pTmp2, pTmp2->buffer + 7, pTmp2->length - 7 );
+
+ /* replace '~' in original string */
+ rtl_uString_newReplaceStrAt( &pTmp, pTmp, 0, 1, pTmp2 );
+ rtl_uString_release( pTmp2 );
+ }
+
+ else
+ {
+ /* FIXME: replace ~user with users home directory */
+ return osl_File_E_INVAL;
+ }
+ }
+
+ /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
+ /*
+ OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
+ */
+
+ *pustrSystemPath = pTmp;
+ return osl_File_E_None;
+#endif // 0
+}
+
+
+/****************************************************************************
+ * osl_getSystemPathFromFileURL_Ex - helper function
+ * clients may specify if they want to accept relative
+ * URLs or not
+ ****************************************************************************/
+
+oslFileError osl_getSystemPathFromFileURL_Ex(
+ rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative)
+{
+ return _osl_getSystemPathFromFileURL( ustrFileURL, pustrSystemPath, bAllowRelative);
+#if 0
+ rtl_uString* temp = 0;
+ oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &temp);
+
+ if (osl_File_E_None == osl_error)
+ {
+ if (bAllowRelative
+ || (UNICHAR_SLASH == temp->buffer[0])
+ || (UNICHAR_COLON == temp->buffer[1] && UNICHAR_SLASH == temp->buffer[2]))
+ {
+ *pustrSystemPath = temp;
+ }
+ else
+ {
+ rtl_uString_release(temp);
+ osl_error = osl_File_E_INVAL;
+ }
+ }
+
+ return osl_error;
+#endif
+}
+
+namespace /* private */
+{
+
+#if 0 // YD
+
+ /******************************************************
+ * Helper function, return a pinter to the final '\0'
+ * of a string
+ ******************************************************/
+
+ sal_Unicode* ustrtoend(sal_Unicode* pStr)
+ {
+ return (pStr + rtl_ustr_getLength(pStr));
+ }
+
+ /*********************************************
+
+ ********************************************/
+ sal_Unicode* ustrcpy(const sal_Unicode* s, sal_Unicode* d)
+ {
+ const sal_Unicode* sc = s;
+ sal_Unicode* dc = d;
+
+ while ((*dc++ = *sc++))
+ /**/;
+
+ return d;
+ }
+
+ /*********************************************
+
+ ********************************************/
+
+ sal_Unicode* ustrncpy(const sal_Unicode* s, sal_Unicode* d, unsigned int n)
+ {
+ const sal_Unicode* sc = s;
+ sal_Unicode* dc = d;
+ unsigned int i = n;
+
+ while (i--)
+ *dc++ = *sc++;
+
+ if (n)
+ *dc = 0;
+
+ return d;
+ }
+
+ /*********************************************
+
+ ********************************************/
+
+ sal_Unicode* ustrchrcat(const sal_Unicode chr, sal_Unicode* d)
+ {
+ sal_Unicode* p = ustrtoend(d);
+ *p++ = chr;
+ *p = 0;
+ return d;
+ }
+
+ /*********************************************
+
+ ********************************************/
+
+ sal_Unicode* ustrcat(const sal_Unicode* s, sal_Unicode* d)
+ {
+ sal_Unicode* dc = ustrtoend(d);
+ ustrcpy(s, dc);
+ return d;
+ }
+
+ /******************************************************
+ *
+ ******************************************************/
+
+ bool _islastchr(sal_Unicode* pStr, sal_Unicode Chr)
+ {
+ sal_Unicode* p = ustrtoend(pStr);
+ if (p > pStr)
+ p--;
+ return (*p == Chr);
+ }
+
+ /******************************************************
+ * Ensure that the given string has the specified last
+ * character if necessary append it
+ ******************************************************/
+
+ sal_Unicode* _strensurelast(sal_Unicode* pStr, sal_Unicode Chr)
+ {
+ if (!_islastchr(pStr, Chr))
+ ustrchrcat(Chr, pStr);
+ return pStr;
+ }
+
+ /******************************************************
+ * Remove the last part of a path, a path that has
+ * only a '/' or no '/' at all will be returned
+ * unmodified
+ ******************************************************/
+
+ sal_Unicode* _rmlastpathtoken(sal_Unicode* aPath)
+ {
+ /* we always may skip -2 because we
+ may at least stand on a '/' but
+ either there is no other character
+ before this '/' or it's another
+ character than the '/'
+ */
+ sal_Unicode* p = ustrtoend(aPath) - 2;
+
+ // move back to the next path separator
+ // or to the start of the string
+ while ((p > aPath) && (*p != UNICHAR_SLASH))
+ p--;
+
+ if (p >= aPath)
+ {
+ if (UNICHAR_SLASH == *p)
+ {
+ p++;
+ *p = '\0';
+ }
+ else
+ {
+ *p = '\0';
+ }
+ }
+
+ return aPath;
+ }
+
+ /******************************************************
+ *
+ ******************************************************/
+
+ oslFileError _osl_resolvepath(
+ /*inout*/ sal_Unicode* path,
+ /*inout*/ sal_Unicode* current_pos,
+ /*in */ sal_Unicode* sentinel,
+ /*inout*/ bool* failed)
+ {
+ oslFileError ferr = osl_File_E_None;
+
+ if (!*failed)
+ {
+ char unresolved_path[PATH_MAX];
+ if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), path, rtl_ustr_getLength(path)))
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ char resolved_path[PATH_MAX];
+ if (realpath(unresolved_path, resolved_path))
+ {
+ if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX))
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ current_pos = ustrtoend(path) - 1;
+ }
+ else
+ {
+ if (EACCES == errno || ENOTDIR == errno || ENOENT == errno)
+ *failed = true;
+ else
+ ferr = oslTranslateFileError(OSL_FET_ERROR, errno);
+ }
+ }
+
+ return ferr;
+ }
+
+ /******************************************************
+ * Works even with non existing paths. The resulting
+ * path must not exceed PATH_MAX else
+ * osl_File_E_NAMETOOLONG is the result
+ ******************************************************/
+
+ oslFileError osl_getAbsoluteFileURL_impl_(const rtl::OUString& unresolved_path, rtl::OUString& resolved_path)
+ {
+ // the given unresolved path must not exceed PATH_MAX
+ if (unresolved_path.getLength() >= (PATH_MAX - 2))
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ sal_Unicode path_resolved_so_far[PATH_MAX];
+ const sal_Unicode* punresolved = unresolved_path.getStr();
+ sal_Unicode* presolvedsf = path_resolved_so_far;
+
+ // reserve space for leading '/' and trailing '\0'
+ // do not exceed this limit
+ sal_Unicode* sentinel = path_resolved_so_far + PATH_MAX - 2;
+
+ // if realpath fails with error ENOTDIR, EACCES or ENOENT
+ // we will not call it again, because _osl_realpath should also
+ // work with non existing directories etc.
+ bool realpath_failed = false;
+ oslFileError ferr;
+
+ path_resolved_so_far[0] = '\0';
+
+ while (*punresolved != '\0')
+ {
+ // ignore '/.' , skip one part back when '/..'
+
+ if ((UNICHAR_DOT == *punresolved) && (UNICHAR_SLASH == *presolvedsf))
+ {
+ if ('\0' == *(punresolved + 1))
+ {
+ punresolved++;
+ continue;
+ }
+ else if (UNICHAR_SLASH == *(punresolved + 1))
+ {
+ punresolved += 2;
+ continue;
+ }
+ else if ((UNICHAR_DOT == *(punresolved + 1)) && ('\0' == *(punresolved + 2) || (UNICHAR_SLASH == *(punresolved + 2))))
+ {
+ _rmlastpathtoken(path_resolved_so_far);
+
+ presolvedsf = ustrtoend(path_resolved_so_far) - 1;
+
+ if (UNICHAR_SLASH == *(punresolved + 2))
+ punresolved += 3;
+ else
+ punresolved += 2;
+
+ continue;
+ }
+ else // a file or directory name may start with '.'
+ {
+ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ ustrchrcat(*punresolved++, path_resolved_so_far);
+
+ if ('\0' == *punresolved && !realpath_failed)
+ {
+ ferr = _osl_resolvepath(
+ path_resolved_so_far,
+ presolvedsf,
+ sentinel,
+ &realpath_failed);
+
+ if (osl_File_E_None != ferr)
+ return ferr;
+ }
+ }
+ }
+ else if (UNICHAR_SLASH == *punresolved)
+ {
+ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ ustrchrcat(*punresolved++, path_resolved_so_far);
+
+ if (!realpath_failed)
+ {
+ ferr = _osl_resolvepath(
+ path_resolved_so_far,
+ presolvedsf,
+ sentinel,
+ &realpath_failed);
+
+ if (osl_File_E_None != ferr)
+ return ferr;
+
+ if (!_islastchr(path_resolved_so_far, UNICHAR_SLASH))
+ {
+ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ ustrchrcat(UNICHAR_SLASH, path_resolved_so_far);
+ }
+ }
+ }
+ else // any other character
+ {
+ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ ustrchrcat(*punresolved++, path_resolved_so_far);
+
+ if ('\0' == *punresolved && !realpath_failed)
+ {
+ ferr = _osl_resolvepath(
+ path_resolved_so_far,
+ presolvedsf,
+ sentinel,
+ &realpath_failed);
+
+ if (osl_File_E_None != ferr)
+ return ferr;
+ }
+ }
+ }
+
+ sal_Int32 len = rtl_ustr_getLength(path_resolved_so_far);
+
+ OSL_ASSERT(len < PATH_MAX);
+
+ resolved_path = rtl::OUString(path_resolved_so_far, len);
+
+ return osl_File_E_None;
+ }
+
+#endif // 0 // YD
+
+} // end namespace private
+
+#if OSL_DEBUG_LEVEL > 0
+
+ //#####################################################
+ void _osl_warnFile( const char *message, rtl_uString *ustrFile )
+ {
+ char szBuffer[2048];
+
+ if (ustrFile)
+ {
+ rtl_String *strFile = NULL;
+
+ rtl_uString2String( &strFile, rtl_uString_getStr( ustrFile ), rtl_uString_getLength( ustrFile ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ snprintf( szBuffer, sizeof(szBuffer), message, strFile->buffer );
+ rtl_string_release( strFile );
+
+ message = szBuffer;
+ }
+ OSL_ENSURE( 0, message );
+ }
+
+#endif // OSL_DEBUG_LEVEL > 0
+
+/******************************************************
+ * osl_getAbsoluteFileURL
+ ******************************************************/
+
+//oslFileError osl_getAbsoluteFileURL(rtl_uString* ustrBaseDirURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL)
+oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL )
+{
+ oslFileError eError;
+ rtl_uString *ustrRelSysPath = NULL;
+ rtl_uString *ustrBaseSysPath = NULL;
+
+ if ( ustrBaseURL && ustrBaseURL->length )
+ {
+ eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False );
+ OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" );
+
+ eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True );
+ }
+ else
+ {
+ eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False );
+ OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" );
+ }
+
+ if ( !eError )
+ {
+ CHAR szBuffer[_MAX_PATH];
+ CHAR szRelSysPath[_MAX_PATH];
+ CHAR szCurrentDir[_MAX_PATH];
+ int result;
+ char* cwd;
+ int rc;
+
+/*@@@ToDo
+ Bad, bad hack, this only works if the base path
+ really exists which is not necessary according
+ to RFC2396
+ The whole FileURL implementation should be merged
+ with the rtl/uri class.
+*/
+ if ( ustrBaseSysPath )
+ {
+ CHAR szBaseSysPath[_MAX_PATH];
+
+ if (!g_CurrentDirectoryMutex)
+ g_CurrentDirectoryMutex = osl_createMutex();
+
+ osl_acquireMutex( g_CurrentDirectoryMutex );
+
+ cwd = getcwd( szCurrentDir, sizeof(szCurrentDir) );
+ UnicodeToText( szBaseSysPath, sizeof(szBaseSysPath), ustrBaseSysPath->buffer, ustrBaseSysPath->length);
+ rc = chdir( szBaseSysPath);
+ }
+
+ UnicodeToText( szRelSysPath, sizeof(szRelSysPath), ustrRelSysPath->buffer, ustrRelSysPath->length);
+ result = !_abspath( szBuffer, szRelSysPath, sizeof(szBuffer));
+
+ if ( ustrBaseSysPath )
+ {
+ rc = chdir( szCurrentDir );
+
+ osl_releaseMutex( g_CurrentDirectoryMutex );
+ }
+
+ if ( result )
+ {
+ rtl_uString *ustrAbsSysPath = NULL;
+
+ oslMakeUStrFromPsz( szBuffer, &ustrAbsSysPath);
+
+ eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL );
+
+ if ( ustrAbsSysPath )
+ rtl_uString_release( ustrAbsSysPath );
+ }
+ else
+ eError = osl_File_E_INVAL;
+ }
+
+ if ( ustrBaseSysPath )
+ rtl_uString_release( ustrBaseSysPath );
+
+ if ( ustrRelSysPath )
+ rtl_uString_release( ustrRelSysPath );
+
+ return eError;
+#if 0
+ FileBase::RC rc;
+ rtl::OUString unresolved_path;
+
+ rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrRelativeURL), unresolved_path);
+
+ if(FileBase::E_None != rc)
+ return oslFileError(rc);
+
+ if (systemPathIsRelativePath(unresolved_path))
+ {
+ rtl::OUString base_path;
+ rc = (FileBase::RC) osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL, &base_path.pData, sal_False);
+
+ if (FileBase::E_None != rc)
+ return oslFileError(rc);
+
+ rtl::OUString abs_path;
+ systemPathMakeAbsolutePath(base_path, unresolved_path, abs_path);
+
+ unresolved_path = abs_path;
+ }
+
+ rtl::OUString resolved_path;
+ rc = (FileBase::RC) osl_getAbsoluteFileURL_impl_(unresolved_path, resolved_path);
+
+ if (FileBase::E_None == rc)
+ {
+ rc = (FileBase::RC) osl_getFileURLFromSystemPath(resolved_path.pData, pustrAbsoluteURL);
+ OSL_ASSERT(FileBase::E_None == rc);
+ }
+
+ return oslFileError(rc);
+#endif // 0
+}
+
+
+namespace /* private */
+{
+
+ /*********************************************
+ No separate error code if unicode to text
+ conversion or getenv fails because for the
+ caller there is no difference why a file
+ could not be found in $PATH
+ ********************************************/
+
+ bool find_in_PATH(const rtl::OUString& file_path, rtl::OUString& result)
+ {
+ bool bfound = false;
+ rtl::OUString path = rtl::OUString::createFromAscii("PATH");
+ rtl::OUString env_path;
+
+ if (osl_Process_E_None == osl_getEnvironment(path.pData, &env_path.pData))
+ bfound = osl::searchPath(file_path, env_path, result);
+
+ return bfound;
+ }
+
+ /*********************************************
+ No separate error code if unicode to text
+ conversion or getcwd fails because for the
+ caller there is no difference why a file
+ could not be found in CDW
+ ********************************************/
+
+ bool find_in_CWD(const rtl::OUString& file_path, rtl::OUString& result)
+ {
+ bool bfound = false;
+ rtl::OUString cwd_url;
+
+ if (osl_Process_E_None == osl_getProcessWorkingDir(&cwd_url.pData))
+ {
+ rtl::OUString cwd;
+ FileBase::getSystemPathFromFileURL(cwd_url, cwd);
+ bfound = osl::searchPath(file_path, cwd, result);
+ }
+ return bfound;
+ }
+
+ /*********************************************
+
+ ********************************************/
+
+ bool find_in_searchPath(const rtl::OUString& file_path, rtl_uString* search_path, rtl::OUString& result)
+ {
+ return (search_path && osl::searchPath(file_path, rtl::OUString(search_path), result));
+ }
+
+} // end namespace private
+
+
+/****************************************************************************
+ * osl_searchFileURL
+ ***************************************************************************/
+
+oslFileError osl_searchFileURL(rtl_uString* ustrFilePath, rtl_uString* ustrSearchPath, rtl_uString** pustrURL)
+{
+ OSL_PRECOND(ustrFilePath && pustrURL, "osl_searchFileURL: invalid parameter");
+
+ FileBase::RC rc;
+ rtl::OUString file_path;
+
+ // try to interpret search path as file url else assume it's a system path list
+ rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath), file_path);
+ if ((FileBase::E_None != rc) && (FileBase::E_INVAL == rc))
+ file_path = ustrFilePath;
+ else if (FileBase::E_None != rc)
+ return oslFileError(rc);
+
+ bool bfound = false;
+ rtl::OUString result;
+
+ if (find_in_searchPath(file_path, ustrSearchPath, result) ||
+ find_in_PATH(file_path, result) ||
+ find_in_CWD(file_path, result))
+ {
+ rtl::OUString resolved;
+
+ if (osl::realpath(result, resolved))
+ {
+#if OSL_DEBUG_LEVEL > 0
+ oslFileError osl_error =
+#endif
+ osl_getFileURLFromSystemPath(resolved.pData, pustrURL);
+ OSL_ASSERT(osl_File_E_None == osl_error);
+ bfound = true;
+ }
+ }
+ return bfound ? osl_File_E_None : osl_File_E_NOENT;
+}
+
+
+/****************************************************************************
+ * FileURLToPath
+ ***************************************************************************/
+
+oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL)
+{
+ rtl_uString* ustrSystemPath = NULL;
+ oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &ustrSystemPath);
+
+ if(osl_File_E_None != osl_error)
+ return osl_error;
+
+ osl_systemPathRemoveSeparator(ustrSystemPath);
+
+ /* convert unicode path to text */
+ if(!UnicodeToText( buffer, bufLen, ustrSystemPath->buffer, ustrSystemPath->length))
+ osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ rtl_uString_release(ustrSystemPath);
+
+ return osl_error;
+}
diff --git a/sal/osl/os2/file_url.h b/sal/osl/os2/file_url.h
new file mode 100644
index 000000000000..052858503b24
--- /dev/null
+++ b/sal/osl/os2/file_url.h
@@ -0,0 +1,183 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ /***************************************************
+ * Internal header file, declares all functions
+ * that are not part of the offical API and are
+ * not defined in the osl header files
+ **************************************************/
+
+ #ifndef _FILE_URL_H_
+ #define _FILE_URL_H_
+
+ #ifndef _FILE_H_
+ #include <osl/file.h>
+ #endif
+
+
+/***************************************************
+ * constants
+ **************************************************/
+
+#define _tcslen(a) wcslen((const wchar_t *) a)
+#define _tcsspn(a,b) wcsspn((const wchar_t *) a, (const wchar_t *) b)
+#define _istalpha(a) iswalpha((wint_t) a)
+
+const sal_Unicode UNICHAR_SLASH = ((sal_Unicode)'/');
+const sal_Unicode UNICHAR_COLON = ((sal_Unicode)':');
+const sal_Unicode UNICHAR_DOT = ((sal_Unicode)'.');
+
+#define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
+
+#if OSL_DEBUG_LEVEL > 0
+#define OSL_ENSURE_FILE( cond, msg, file ) ( (cond) ? (void)0 : _osl_warnFile( msg, file ) )
+#else
+#define OSL_ENSURE_FILE( cond, msg, file ) ((void)0)
+#endif
+
+typedef sal_Unicode TCHAR;
+typedef sal_Unicode *LPTSTR;
+typedef const sal_Unicode *LPCTSTR;
+typedef wchar_t *LPWSTR;
+typedef const wchar_t *LPCWSTR;
+typedef sal_Unicode DWORD;
+#define WINAPI
+
+#define CHARSET_SEPARATOR L"\\/"
+#define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\"
+
+
+/******************************************************************************
+ *
+ * Data Type Definition
+ *
+ ******************************************************************************/
+
+#define PATHTYPE_ERROR 0
+#define PATHTYPE_RELATIVE 1
+#define PATHTYPE_ABSOLUTE_UNC 2
+#define PATHTYPE_ABSOLUTE_LOCAL 3
+#define PATHTYPE_MASK_TYPE 0xFF
+#define PATHTYPE_IS_VOLUME 0x0100
+#define PATHTYPE_IS_SERVER 0x0200
+
+#define VALIDATEPATH_NORMAL 0x0000
+#define VALIDATEPATH_ALLOW_WILDCARDS 0x0001
+#define VALIDATEPATH_ALLOW_ELLIPSE 0x0002
+#define VALIDATEPATH_ALLOW_RELATIVE 0x0004
+#define VALIDATEPATH_ALLOW_UNC 0x0008
+
+typedef struct {
+ UINT uType;
+ rtl_uString* ustrDrive;
+ rtl_uString* ustrFilePath; /* holds native directory path */
+ int d_attr; /* OS/2 file attributes */
+ int nRefCount;
+}DirectoryItem_Impl;
+
+#define DIRECTORYTYPE_LOCALROOT 0
+#define DIRECTORYTYPE_NETROOT 1
+#define DIRECTORYTYPE_NETRESORCE 2
+#define DIRECTORYTYPE_FILESYSTEM 3
+
+#define DIRECTORYITEM_DRIVE 0
+#define DIRECTORYITEM_FILE 1
+#define DIRECTORYITEM_SERVER 2
+
+typedef struct
+{
+ UINT uType;
+ rtl_uString* ustrPath; /* holds native directory path */
+ DIR* pDirStruct;
+ ULONG ulDriveMap;
+ ULONG ulNextDrive;
+ ULONG ulNextDriveMask;
+} DirectoryImpl;
+
+/* Different types of paths */
+typedef enum _PATHTYPE
+{
+ PATHTYPE_SYNTAXERROR = 0,
+ PATHTYPE_NETROOT,
+ PATHTYPE_NETSERVER,
+ PATHTYPE_VOLUME,
+ PATHTYPE_FILE
+} PATHTYPE;
+
+DWORD WINAPI IsValidFilePath(LPCTSTR, LPCTSTR*, DWORD);
+
+typedef struct
+{
+ rtl_uString* ustrFilePath; /* holds native file path */
+ int fd;
+ sal_Bool bLocked;
+} oslFileHandleImpl;
+
+
+typedef struct _oslVolumeDeviceHandleImpl
+{
+ sal_Char pszMountPoint[PATH_MAX];
+ sal_Char pszFilePath[PATH_MAX];
+ sal_Char pszDevice[PATH_MAX];
+ sal_Char ident[4];
+ sal_uInt32 RefCount;
+} oslVolumeDeviceHandleImpl;
+
+/* OS error to errno values mapping table */
+struct errentry {
+ unsigned long oscode; /* OS return value */
+ int errnocode; /* System V error code */
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************************************
+* _osl_getSystemPathFromFileURL
+*************************************************/
+
+#define FURL_ALLOW_RELATIVE sal_True
+#define FURL_DENY_RELATIVE sal_False
+
+oslFileError osl_getSystemPathFromFileURL_Ex(rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative);
+
+/**************************************************
+* FileURLToPath
+*************************************************/
+
+oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* #define _FILE_URL_H_ */
+
diff --git a/sal/osl/os2/helpers/debug.h b/sal/osl/os2/helpers/debug.h
new file mode 100644
index 000000000000..83edca5db676
--- /dev/null
+++ b/sal/osl/os2/helpers/debug.h
@@ -0,0 +1,1779 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*
+ *@@sourcefile debug.h:
+ * header file for debug.c (exception handling and debugging).
+ * See remarks there.
+ *
+ * Note: Version numbering in this file relates to XWorkplace version
+ * numbering.
+ *
+ *@@changed V0.9.0: included contents of newexe.h
+ *
+ *@@include #define INCL_BASE
+ *@@include #include <os2.h>
+ *@@include #include <stdio.h>
+ *@@include #include "helpers\debug.h"
+ */
+
+/*
+ * This file incorporates code from the following:
+ * -- Marc Fiammante, John Currier, Kim Rasmussen,
+ * Anthony Cruise (EXCEPT3.ZIP package for a generic
+ * exception handling DLL, available at Hobbes).
+ *
+ * This file Copyright (C) 1992-99 Ulrich M�ller,
+ * Kim Rasmussen,
+ * Marc Fiammante,
+ * John Currier,
+ * Anthony Cruise.
+ *
+ * 2009-06-15 published under LGPL3 with Ulrich M�ller permission.
+ *
+ */
+
+#ifndef DEBUG_HEADER_INCLUDED
+ #define DEBUG_HEADER_INCLUDED
+
+ /********************************************************************
+ *
+ * SYM file declarations
+ *
+ ********************************************************************/
+
+ // Pointer means offset from beginning of file or beginning of struct
+ #pragma pack(1)
+
+ typedef struct
+ {
+ unsigned short int ppNextMap; // paragraph pointer to next map
+ unsigned char bFlags; // symbol types
+ unsigned char bReserved1; // reserved
+ unsigned short int pSegEntry; // segment entry point value
+ unsigned short int cConsts; // count of constants in map
+ unsigned short int pConstDef; // pointer to constant chain
+ unsigned short int cSegs; // count of segments in map
+ unsigned short int ppSegDef; // paragraph pointer to first segment
+ unsigned char cbMaxSym; // maximum symbol-name length
+ unsigned char cbModName; // length of module name
+ char achModName[1]; // cbModName Bytes of module-name member
+ } MAPDEF;
+
+ typedef struct
+ {
+ unsigned short int ppNextMap; // always zero
+ unsigned char release; // release number (minor version number)
+ unsigned char version; // major version number
+ } LAST_MAPDEF;
+
+ typedef struct
+ {
+ unsigned short int ppNextSeg; // paragraph pointer to next segment
+ unsigned short int cSymbols; // count of symbols in list
+ unsigned short int pSymDef; // offset of symbol chain
+ unsigned short int wReserved1; // reserved
+ unsigned short int wReserved2; // reserved
+ unsigned short int wReserved3; // reserved
+ unsigned short int wReserved4; // reserved
+ unsigned char bFlags; // symbol types; bit 0 signals 32-bit (*UM)
+ unsigned char bReserved1; // reserved
+ unsigned short int ppLineDef; // offset of line number record
+ unsigned char bReserved2; // reserved
+ unsigned char bReserved3; // reserved
+ unsigned char cbSegName; // length of segment name
+ char achSegName[1]; /* cbSegName Bytes of segment-name member*/
+ } SEGDEF;
+
+ typedef struct
+ {
+ unsigned short int wSymVal; // symbol address or constant
+ unsigned char cbSymName; // length of symbol name
+ char achSymName[1]; // cbSymName Bytes of symbol-name member
+ } SYMDEF16;
+
+ typedef struct
+ {
+ unsigned int wSymVal; // symbol address or constant
+ unsigned char cbSymName; // length of symbol name
+ char achSymName[1]; // cbSymName Bytes of symbol-name member
+ } SYMDEF32;
+
+ typedef struct
+ {
+ unsigned short int ppNextLine; // ptr to next linedef (0 if last)
+ unsigned short int wReserved1; // reserved
+ unsigned short int pLines; // pointer to line numbers
+ unsigned short int cLines; // reserved
+ unsigned char cbFileName; // length of filename
+ char achFileName[1];// cbFileName Bytes of filename
+ } LINEDEF;
+
+ typedef struct
+ {
+ unsigned short int wCodeOffset; // executable offset
+ unsigned short int dwFileOffset; // source offset
+ } LINEINF;
+
+ #define SEGDEFOFFSET(MapDef) (MapDef.ppSegDef*16)
+ #define NEXTSEGDEFOFFSET(SegDef) (SegDef.ppNextSeg*16)
+
+ #define ASYMPTROFFSET(SegDefOffset,Segdef) (SegDefOffset+SegDef.pSymDef)
+ #define SYMDEFOFFSET(SegDefOffset,SegDef,n) (ASYMPTROFFSET(SegDefOffset,SegDef)+(n)*(sizeof(unsigned short int)))
+
+ #define ACONSTPTROFFSET(MapDef) (MapDef.ppConstDef)
+ #define CONSTDEFOFFSET(MapDef,n) ((MapDef.ppConstDef)+(n)*(sizeof(unsigned short int)))
+
+ #define LINEDEFOFFSET(SegDef) (SegDef.ppLineDef*16)
+ #define NEXTLINEDEFOFFSET(LineDef) (LineDef.ppNextLine*16)
+ #define LINESOFFSET(LinedefOffset,LineDef) ((LinedefOffset)+LineDef.pLines)
+
+ /********************************************************************
+ *
+ * EXE declarations taken from exe.h
+ *
+ ********************************************************************/
+
+ #ifndef WORD
+ typedef unsigned short WORD;
+ #endif
+
+ typedef WORD bbmask;
+
+ struct exe {
+ WORD eid; // contains EXEID, below
+ WORD elast; // # of bytes in last page
+ WORD epagsiz; // # of pages in whole file
+ WORD erelcnt; // # of relocation entrys
+ WORD ehdrsiz; // size of header, in paragraphs
+ WORD eminfre; // min # of free paragraphs needed
+ WORD emaxfre; // max # of free paragraphs needed
+ WORD eiSS; // initial SS value
+ WORD eiSP; // initial SP value
+ WORD enegsum; // negative sum of entire file
+ WORD eiIP; // initial IP value
+ WORD eiCS; // initial CS value
+ WORD ereloff; // offset in file of relocation table
+ WORD eovlnum; // number of the overlay
+
+ /* the following fields may not be present.
+ * ereloff = 28 not present
+ * = 30 exe.ever present and valid
+ * = 32 exe.ever field contains garbage
+ * ereloff > 32 exe.ever present and valid
+ * = 0 if "don't know"
+ */
+
+ WORD ever; // version # of producing linker
+ WORD dumy; // unused
+
+ /* the following fields may not be present - if the exe.ereloff
+ * value encompasses the fields then they are present and valid.
+ */
+
+ bbmask ebb; // behavior bits
+ WORD dumy2[7]; // must be 0 until defined
+ };
+
+
+ #define EXEID 0x5a4d // magic ID value
+
+ /********************************************************************
+ *
+ * Object Module Format (OMF) declarations
+ *
+ ********************************************************************/
+
+ struct exehdr_rec
+ {
+ BYTE signature[2]; // Must be "MZ"
+ USHORT image_len; // Image Length
+ USHORT pages; // Pages
+ USHORT reloc_items; // Relocation table items
+ USHORT min_paragraphs; // Mininum 16-bytes paragraphs
+ USHORT max_paragraphs; // Maximum 16-bytes paragraphs
+ USHORT stack_pos; // Stack position
+ USHORT offset_in_sp; // Offset in SP
+ USHORT checksum; // Checksum
+ USHORT offset_in_ip; // Offset in IP
+ USHORT code_pos; // Code segment pos.
+ USHORT reloc_item_pos; // Position of first relocation item
+ USHORT overlay_number; // Overlay number
+ BYTE unused[8]; // Unused bytes
+ USHORT oem_id; // OEM Identifier
+ BYTE oem_info[24]; // OEM Info
+ ULONG lexe_offset; // Offset to linear header
+ };
+
+ struct lexehdr_rec
+ {
+ BYTE signature[2]; // Must be "LX"
+ BYTE b_ord; // Byte ordering
+ BYTE w_ord; // Word ordering
+ ULONG format_level; // Format level
+ USHORT cpu_type; // CPU Type
+ USHORT os_type; // Operating system
+ ULONG module_version; // Module version
+ ULONG mod_flags; // Module flags
+ ULONG mod_pages; // Module pages
+ ULONG EIP_object; // EIP Object no.
+ ULONG EIP; // EIP Value
+ ULONG ESP_object; // ESP Object no
+ ULONG ESP; // ESP Value
+ ULONG page_size; // Page size
+ ULONG page_ofs_shift; // Page offset shift
+ ULONG fixup_sect_size; // Fixup section size
+ ULONG fixup_sect_checksum; // Fixup section checksum
+ ULONG loader_sect_size; // Loader section size
+ ULONG loader_sect_checksum; // Loader section checksum
+ ULONG obj_table_ofs; // Object table offset
+ ULONG obj_count; // Object count
+ ULONG obj_page_tab_ofs; // Object page table offset
+ ULONG obj_iter_page_ofs; // Object iteration pages offset
+ ULONG res_tab_ofs; // Resource table offset
+ ULONG res_table_entries; // Resource table entries
+ ULONG res_name_tab_ofs; // Resident name table offset;
+ ULONG ent_tab_ofs; // Entry table offset
+ ULONG mod_dir_ofs; // Module directives offset
+ ULONG mod_dir_count; // Number of module directives
+ ULONG fixup_page_tab_ofs; // Fixup page table offset
+ ULONG fixup_rec_tab_ofs; // Fixup record table offset
+ ULONG imp_tab_ofs; // Import module table offset
+ ULONG imp_mod_entries; // Import module entries
+ ULONG imp_proc_tab_ofs; // Import proc table offset
+ ULONG per_page_check_ofs; // Per page checksum offset
+ ULONG data_page_offset; // Data pages offset
+ ULONG preload_page_count; // Preload pages count
+ ULONG nonres_tab_ofs; // Nonresident name table offset
+ ULONG nonres_tab_len; // Nonresident name table len
+ ULONG nonres_tab_check; // Nonresident tables checksum
+ ULONG auto_ds_objectno; // Auto DS object number
+ ULONG debug_info_ofs; // Debug info offset
+ ULONG debug_info_len; // Debug info length
+ ULONG inst_preload_count; // Instance preload count
+ ULONG inst_demand_count; // Instance demand count
+ ULONG heapsize; // Heap size
+ ULONG stacksize; // Stack size
+ };
+
+ struct debug_head_rec
+ {
+ BYTE signature[3]; // Debug signature
+ BYTE type; // Debug info type
+ };
+
+ struct dir_inf_rec
+ {
+ USHORT dirstruct_size; // Size of directory structure
+ USHORT number_of_entries; // Number of dnt_rec's in the array
+ USHORT unknown; // Unknown data
+ // Followed by an array of dnt_rec structures
+ };
+
+ struct dnt_rec
+ {
+ USHORT subsect_type; // sst Subsection type
+ USHORT mod_index; // Module index (1-based)
+ ULONG offset; // Offset of start of section
+ ULONG size; // Size of section
+ };
+
+ // Modules subsection
+ struct modules_rec
+ {
+ USHORT code_seg_base; // Code segment base
+ ULONG code_seg_offset; // Code segment offset
+ ULONG code_seg_len; // Code segment length
+ USHORT overlay_no; // Overlay number
+ USHORT lib_idx; // Index into library section or 0
+ BYTE segments; // Number of segments
+ BYTE reserved;
+ BYTE debug_style[2]; // "HL" for HLL, "CV" or 0 for CodeView
+ BYTE debug_version[2]; // 00 01 or 00 03 for HLL, 00 00 for CV
+ BYTE name_len; // Length of name (which follows)
+ };
+
+ // Publics subsection
+ struct publics_rec
+ {
+ ULONG offset; // Offset
+ USHORT segment; // Segment
+ USHORT type; // Type index
+ BYTE name_len; // Length of name (wich follows)
+ };
+
+ #if 0
+ // Linenumbers header
+ struct linhead_rec
+ {
+ BYTE id; // 0x95 for flat mem, 32 bit progs
+ USHORT length; // Record length
+ USHORT base_group; // Base group
+ USHORT base_segment; // Base segment
+ };
+ #endif
+
+ // First linenumber record
+ struct linfirst_rec
+ {
+ USHORT lineno; // Line number (0)
+ BYTE entry_type; // Entry type
+ BYTE reserved; // Reserved
+ USHORT entries_count; // Number of table entries
+ USHORT segment_no; // Segment number
+ ULONG filename_tabsize; // File names table size
+ };
+
+ // Source line numbers
+ struct linsource_rec
+ {
+ USHORT source_line; // Source file line number
+ USHORT source_idx; // Source file index
+ ULONG offset; // Offset into segment
+ };
+
+ // Listing statement numbers
+ struct linlist_rec
+ {
+ ULONG list_line; // Listing file linenumber
+ ULONG statement; // Listing file statement number
+ ULONG offset; // Offset into segment
+ };
+
+ // Source and Listing statement numbers
+ struct linsourcelist_rec
+ {
+ USHORT source_line; // Source file line number
+ USHORT source_idx; // Source file index
+ ULONG list_line; // Listing file linenumber
+ ULONG statement; // Listing file statement number
+ ULONG offset; // Offset into segment
+ };
+
+ // Path table
+ struct pathtab_rec
+ {
+ ULONG offset; // Offset into segment
+ USHORT path_code; // Path code
+ USHORT source_idx; // Source file index
+ };
+
+ // File names table
+ struct filenam_rec
+ {
+ ULONG first_char; // First displayable char in list file
+ ULONG disp_chars; // Number of displayable chars in list line
+ ULONG filecount; // Number of source/listing files
+ };
+
+ // Symbol types
+ #define SYM_BEGIN 0x00 // Begin block
+ #define SYM_PROC 0x01 // Function
+ #define SYM_END 0x02 // End block of function
+ #define SYM_AUTO 0x04 // Auto variable
+ #define SYM_STATIC 0x05 // Static variable
+ #define SYM_LABEL 0x0B // Label
+ #define SYM_WITH 0x0C // With start symbol (not used)
+ #define SYM_REG 0x0D // Register variable
+ #define SYM_CONST 0x0E // Constant
+ #define SYM_ENTRY 0x0F // Secondary entry (not in C)
+ #define SYM_SKIP 0x10 // For incremental linking (not used)
+ #define SYM_CHANGESEG 0x11 // Change segment (#pragma alloc_text)
+ #define SYM_TYPEDEF 0x12 // Typedef variable
+ #define SYM_PUBLIC 0x13 // Public reference
+ #define SYM_MEMBER 0x14 // Member of minor or major structure
+ #define SYM_BASED 0x15 // Based variable
+ #define SYM_TAG 0x16 // Tag in struct, union, enum ...
+ #define SYM_TABLE 0x17 // Table (used in RPG - not C)
+ #define SYM_MAP 0x18 // Map variable (extern in C)
+ #define SYM_CLASS 0x19 // Class symbol (C++)
+ #define SYM_MEMFUNC 0x1A // Member function
+ #define SYM_AUTOSCOPE 0x1B // Scoped auto for C++ (not used)
+ #define SYM_STATICSCOPE 0x1C // scoped static for C++ (not used)
+ #define SYM_CPPPROC 0x1D // C++ Proc
+ #define SYM_CPPSTAT 0x1E // C++ Static var
+ #define SYM_COMP 0x40 // Compiler information
+
+ // Symbolic begin record
+ struct symbegin_rec
+ {
+ ULONG offset; // Segment offset
+ ULONG length; // Length of block
+ BYTE name_len; // Length of block name
+ // Block name follows
+ };
+
+ // Symbolic auto var record
+ struct symauto_rec
+ {
+ ULONG stack_offset; // Stack offset
+ USHORT type_idx; // Type index
+ BYTE name_len; // Length of name
+ // Var name follows
+ };
+
+ // Symbolic procedure record
+ struct symproc_rec
+ {
+ ULONG offset; // Segment offset
+ USHORT type_idx; // Type index
+ ULONG length; // Length of procedure
+ USHORT pro_len; // Length of prologue
+ ULONG pro_bodylen; // Length of prologue + body
+ USHORT class_type; // Class type
+ BYTE near_far; // Near or far
+ BYTE name_len; // Length of name
+ // Function name follows
+ };
+
+ // Symbolic static var record
+ struct symstatic_rec
+ {
+ ULONG offset; // Segment offset
+ USHORT segaddr; // Segment address
+ USHORT type_idx; // Type index
+ BYTE name_len; // Length of name
+ // Var name follows
+ };
+
+ // Symbolic label var record
+ struct symlabel_rec
+ {
+ ULONG offset; // Segment offset
+ BYTE near_far; // Near or far
+ BYTE name_len; // Length of name
+ // Var name follows
+ };
+
+ // Symbolic register var record
+ struct symreg_rec
+ {
+ USHORT type_idx; // Type index
+ BYTE reg_no; // Register number
+ BYTE name_len; // Length of name
+ // Var name follows
+ };
+
+ // Symbolic change-segment record
+ struct symseg_rec
+ {
+ USHORT seg_no; // Segment number
+ };
+
+ // Symbolic typedef record
+ struct symtypedef_rec
+ {
+ USHORT type_idx; // Type index
+ BYTE name_len; // Length of name
+ // Name follows
+ };
+
+ // Symbolic public record
+ struct sympublic_rec
+ {
+ ULONG offset; // Segment offset
+ USHORT segaddr; // Segment address
+ USHORT type_idx; // Type index
+ BYTE name_len; // Length of name
+ // Name follows
+ };
+
+ // Symbolic member record
+ struct symmember_rec
+ {
+ ULONG offset; // Offset to subrecord
+ BYTE name_len; // Length of name
+ // Name follows
+ };
+
+ // Symbolic based record
+ struct symbased_rec
+ {
+ ULONG offset; // Offset to subrecord
+ USHORT type_idx; // Type index
+ BYTE name_len; // Length of name
+ // Name follows
+ };
+
+ // Symbolic tag record
+ struct symtag_rec
+ {
+ USHORT type_idx; // Type index
+ BYTE name_len; // Length of name
+ // Name follows
+ };
+
+ // Symbolic table record
+ struct symtable_rec
+ {
+ ULONG offset; // Segment offset
+ USHORT segaddr; // Segment address
+ USHORT type_idx; // Type index
+ ULONG idx_ofs; // Index offset to subrecord
+ BYTE name_len; // Length of name
+ // Name follows
+ };
+
+ // Type record
+ struct type_rec
+ {
+ USHORT length; // Length of sub-record
+ BYTE type; // Sub-record type
+ BYTE type_qual; // Type qualifier
+ };
+
+ // Types
+ #define TYPE_CLASS 0x40 // Class
+ #define TYPE_BASECLASS 0x41 // Base class
+ #define TYPE_FRIEND 0x42 // Friend
+ #define TYPE_CLASSDEF 0x43 // Class definition
+ #define TYPE_MEMBERFUNC 0x45 // Member function
+ #define TYPE_CLASSMEMBER 0x46 // Class member
+ #define TYPE_REF 0x48 // Reference
+ #define TYPE_MEMBERPTR 0x49 // Member pointer
+ #define TYPE_SCALARS 0x51 // Scalars
+ #define TYPE_SET 0x52 // Set
+ #define TYPE_ENTRY 0x53 // Entry
+ #define TYPE_FUNCTION 0x54 // Function
+ #define TYPE_AREA 0x55 // Area
+ #define TYPE_LOGICAL 0x56 // Logical
+ #define TYPE_STACK 0x57 // Stack
+ #define TYPE_MACRO 0x59 // Macro
+ #define TYPE_BITSTRING 0x5C // Bit string
+ #define TYPE_USERDEF 0x5D // User defined
+ #define TYPE_CHARSTR 0x60 // Character string
+ #define TYPE_PICTURE 0x61 // Picture
+ #define TYPE_GRAPHIC 0x62 // Graphic
+ #define TYPE_FORMATLAB 0x65 // Format label
+ #define TYPE_FILE 0x67 // File
+ #define TYPE_SUBRANGE 0x6F // Subrange
+ #define TYPE_CODELABEL 0x72 // Code label
+ #define TYPE_PROCEDURE 0x75 // Procedure
+ #define TYPE_ARRAY 0x78 // Array
+ #define TYPE_STRUCT 0x79 // Structure / Union / Record
+ #define TYPE_POINTER 0x7A // Pointer
+ #define TYPE_ENUM 0x7B // Enum
+ #define TYPE_LIST 0x7F // List
+
+ // Type userdef
+ struct type_userdefrec
+ {
+ BYTE FID_index; // Field ID
+ USHORT type_index; // Type index
+ BYTE FID_string; // String ID
+ BYTE name_len; // Length of name which follows
+ };
+
+ // Type function
+ struct type_funcrec
+ {
+ USHORT params;
+ USHORT max_params;
+ BYTE FID_index; // Field ID
+ USHORT type_index; // Type index of return value
+ BYTE FID_index1; // String ID
+ USHORT typelist_index; // Index of list of params
+ };
+
+ // Type struct
+ struct type_structrec
+ {
+ ULONG size; // Size of structure
+ USHORT field_count; // Number of fields in structure
+ BYTE FID_index; // Field ID
+ USHORT type_list_idx; // Index to type list
+ BYTE FID_index1; // Field ID
+ USHORT type_name_idx; // Index to names / offsets
+ BYTE dont_know; // Haven't a clue, but it seems to be needed
+ BYTE name_len; // Length of structure name which follows
+ };
+
+ // Type list, type qualifier 1: contains types for structures
+ // This record is repeated for the number of items in the structure definition
+ struct type_list1
+ {
+ BYTE FID_index; // Field identifier for index
+ USHORT type_index; // Type index.
+ };
+
+ // Type list, type qualifier 2: contains names and offsets for structure items
+ // This record is repeated for the number of items in the structure definition
+ struct type_list2
+ {
+ BYTE FID_string; // String identifier
+ BYTE name_len; // Length of name which follows
+ };
+
+ // Type list, subrecord to the above, contains offset of variable in the structure
+ struct type_list2_1
+ {
+ BYTE FID_span; // Defines what type of variable follows
+ union {
+ BYTE b_len;
+ USHORT s_len;
+ ULONG l_len;
+ } u;
+ };
+
+ // Type pointer
+ struct type_pointerrec
+ {
+ BYTE FID_index; // Index identifier
+ USHORT type_index; // Type index
+ BYTE FID_string; // String identifier
+ BYTE name_len; // Length of name which follows
+ };
+
+ /********************************************************************
+ *
+ * Prototypes
+ *
+ ********************************************************************/
+
+ BOOL dbgPrintStackFrame(FILE *LogFile,
+ PSZ pszModuleName, // in: module name (fully q'fied)
+ ULONG ulObject,
+ ULONG ulOffset);
+
+ VOID dbgPrintStack(FILE *file,
+ PUSHORT StackBottom,
+ PUSHORT StackTop,
+ PUSHORT Ebp,
+ PUSHORT ExceptionAddress);
+
+ APIRET APIENTRY DosQueryModFromEIP(HMODULE *phMod, // out: trapping module
+ ULONG *pulObjNum, // out: object/segment number
+ ULONG ulBuffLen, // in: sizeof(*pszBuff)
+ CHAR *pszBuff, // out: module name
+ ULONG *pulOffset, // out: offset in module
+ ULONG ulAddress); // in: address to be analyzed
+
+ APIRET APIENTRY DOSQUERYMODFROMEIP(HMODULE * phMod,
+ ULONG * pObjNum,
+ ULONG BuffLen,
+ PCHAR pBuff,
+ ULONG * pOffset,
+ PVOID Address);
+
+ typedef ULONG *_Seg16 PULONG16;
+ APIRET16 APIENTRY16 DOS16SIZESEG(USHORT Seg, PULONG16 Size);
+ typedef APIRET16(APIENTRY16 _PFN16) (VOID);
+ ULONG APIENTRY DosSelToFlat(ULONG);
+
+ APIRET16 APIENTRY16 DOSQPROCSTATUS(ULONG * _Seg16 pBuf, USHORT cbBuf);
+
+ #define CONVERT(fp,QSsel) MAKEP((QSsel),OFFSETOF(fp))
+
+ #pragma pack() // added V0.9.0
+
+
+ /********************************************************************
+ *
+ * Executable definitions
+ *
+ ********************************************************************/
+
+ #define EXE386 1
+
+ #ifndef __NEWEXE__
+ #define __NEWEXE__
+
+ #pragma pack(1)
+
+ /*_________________________________________________________________*
+ | |
+ | |
+ | DOS3 .EXE FILE HEADER DEFINITION |
+ | |
+ |_________________________________________________________________|
+ * */
+
+
+ #define EMAGIC 0x5A4D // Old magic number
+ #define ENEWEXE sizeof(struct exe_hdr)
+ // Value of E_LFARLC for new .EXEs
+ #define ENEWHDR 0x003C // Offset in old hdr. of ptr. to new
+ #define ERESWDS 0x0010 // No. of reserved words (OLD)
+ #define ERES1WDS 0x0004 // No. of reserved words in e_res
+ #define ERES2WDS 0x000A // No. of reserved words in e_res2
+ #define ECP 0x0004 // Offset in struct of E_CP
+ #define ECBLP 0x0002 // Offset in struct of E_CBLP
+ #define EMINALLOC 0x000A // Offset in struct of E_MINALLOC
+
+ /*
+ *@@ exe_hdr:
+ * DOS 1, 2, 3 .EXE header.
+ */
+
+ struct exe_hdr
+ {
+ unsigned short e_magic; // Magic number
+ unsigned short e_cblp; // Bytes on last page of file
+ unsigned short e_cp; // Pages in file
+ unsigned short e_crlc; // Relocations
+ unsigned short e_cparhdr; // Size of header in paragraphs
+ unsigned short e_minalloc; // Minimum extra paragraphs needed
+ unsigned short e_maxalloc; // Maximum extra paragraphs needed
+ unsigned short e_ss; // Initial (relative) SS value
+ unsigned short e_sp; // Initial SP value
+ unsigned short e_csum; // Checksum
+ unsigned short e_ip; // Initial IP value
+ unsigned short e_cs; // Initial (relative) CS value
+ unsigned short e_lfarlc; // File address of relocation table
+ unsigned short e_ovno; // Overlay number
+ unsigned short e_res[ERES1WDS];// Reserved words
+ unsigned short e_oemid; // OEM identifier (for e_oeminfo)
+ unsigned short e_oeminfo; // OEM information; e_oemid specific
+ unsigned short e_res2[ERES2WDS];// Reserved words
+ long e_lfanew; // File address of new exe header
+ };
+
+ #define E_MAGIC(x) (x).e_magic
+ #define E_CBLP(x) (x).e_cblp
+ #define E_CP(x) (x).e_cp
+ #define E_CRLC(x) (x).e_crlc
+ #define E_CPARHDR(x) (x).e_cparhdr
+ #define E_MINALLOC(x) (x).e_minalloc
+ #define E_MAXALLOC(x) (x).e_maxalloc
+ #define E_SS(x) (x).e_ss
+ #define E_SP(x) (x).e_sp
+ #define E_CSUM(x) (x).e_csum
+ #define E_IP(x) (x).e_ip
+ #define E_CS(x) (x).e_cs
+ #define E_LFARLC(x) (x).e_lfarlc
+ #define E_OVNO(x) (x).e_ovno
+ #define E_RES(x) (x).e_res
+ #define E_OEMID(x) (x).e_oemid
+ #define E_OEMINFO(x) (x).e_oeminfo
+ #define E_RES2(x) (x).e_res2
+ #define E_LFANEW(x) (x).e_lfanew
+
+
+ /*_________________________________________________________________*
+ | |
+ | |
+ | OS/2 & WINDOWS .EXE FILE HEADER DEFINITION - 286 version |
+ | |
+ |_________________________________________________________________|
+ * */
+
+ #define NEMAGIC 0x454E // New magic number
+ #define NERESBYTES 8 // Eight bytes reserved (now)
+ #define NECRC 8 // Offset into new header of NE_CRC
+
+ /*
+ *@@ new_exe:
+ * New Executable (NE) header.
+ * Follows DOS header in the executable file.
+ */
+
+ struct new_exe
+ {
+ unsigned short ne_magic; // Magic number NE_MAGIC
+ unsigned char ne_ver; // Version number
+ unsigned char ne_rev; // Revision number
+ unsigned short ne_enttab; // Offset of Entry Table
+ unsigned short ne_cbenttab; // Number of bytes in Entry Table
+ long ne_crc; // Checksum of whole file
+ unsigned short ne_flags; // Flag word
+ unsigned short ne_autodata; // Automatic data segment number
+ unsigned short ne_heap; // Initial heap allocation
+ unsigned short ne_stack; // Initial stack allocation
+ long ne_csip; // Initial CS:IP setting
+ long ne_sssp; // Initial SS:SP setting
+ unsigned short ne_cseg; // Count of file segments
+ unsigned short ne_cmod; // Entries in Module Reference Table
+ unsigned short ne_cbnrestab; // Size of non-resident name table
+ unsigned short ne_segtab; // Offset of Segment Table
+ unsigned short ne_rsrctab; // Offset of Resource Table
+ unsigned short ne_restab; // Offset of resident name table
+ unsigned short ne_modtab; // Offset of Module Reference Table
+ unsigned short ne_imptab; // Offset of Imported Names Table
+ long ne_nrestab; // Offset of Non-resident Names Table
+ unsigned short ne_cmovent; // Count of movable entries
+ unsigned short ne_align; // Segment alignment shift count
+ unsigned short ne_cres; // Count of resource entries
+ unsigned char ne_exetyp; // Target operating system
+ unsigned char ne_flagsothers; // Other .EXE flags
+ char ne_res[NERESBYTES]; // Pad structure to 64 bytes
+ };
+
+ #pragma pack()
+
+ #define NE_MAGIC(x) (x).ne_magic
+ #define NE_VER(x) (x).ne_ver
+ #define NE_REV(x) (x).ne_rev
+ #define NE_ENTTAB(x) (x).ne_enttab
+ #define NE_CBENTTAB(x) (x).ne_cbenttab
+ #define NE_CRC(x) (x).ne_crc
+ #define NE_FLAGS(x) (x).ne_flags
+ #define NE_AUTODATA(x) (x).ne_autodata
+ #define NE_HEAP(x) (x).ne_heap
+ #define NE_STACK(x) (x).ne_stack
+ #define NE_CSIP(x) (x).ne_csip
+ #define NE_SSSP(x) (x).ne_sssp
+ #define NE_CSEG(x) (x).ne_cseg
+ #define NE_CMOD(x) (x).ne_cmod
+ #define NE_CBNRESTAB(x) (x).ne_cbnrestab
+ #define NE_SEGTAB(x) (x).ne_segtab
+ #define NE_RSRCTAB(x) (x).ne_rsrctab
+ #define NE_RESTAB(x) (x).ne_restab
+ #define NE_MODTAB(x) (x).ne_modtab
+ #define NE_IMPTAB(x) (x).ne_imptab
+ #define NE_NRESTAB(x) (x).ne_nrestab
+ #define NE_CMOVENT(x) (x).ne_cmovent
+ #define NE_ALIGN(x) (x).ne_align
+ #define NE_CRES(x) (x).ne_cres
+ #define NE_RES(x) (x).ne_res
+ #define NE_EXETYP(x) (x).ne_exetyp
+ #define NE_FLAGSOTHERS(x) (x).ne_flagsothers
+
+ #define NE_USAGE(x) (WORD)*((WORD *)(x)+1)
+ #define NE_PNEXTEXE(x) (WORD)(x).ne_cbenttab
+ #define NE_ONEWEXE(x) (WORD)(x).ne_crc
+ #define NE_PFILEINFO(x) (WORD)((DWORD)(x).ne_crc >> 16)
+
+
+ /*
+ * Target operating systems
+ */
+
+ #define NE_UNKNOWN 0x0 /* Unknown (any "new-format" OS) */
+ #define NE_OS2 0x1 /* OS/2 (default) */
+ #define NE_WINDOWS 0x2 /* Windows */
+ #define NE_DOS4 0x3 /* DOS 4.x */
+ #define NE_DEV386 0x4 /* Windows 386 */
+
+
+ /*
+ * Format of NE_FLAGS(x):
+ *
+ * p Not-a-process
+ * x Unused
+ * e Errors in image
+ * x Unused
+ * b Bound Family/API
+ * ttt Application type
+ * f Floating-point instructions
+ * 3 386 instructions
+ * 2 286 instructions
+ * 0 8086 instructions
+ * P Protected mode only
+ * p Per-process library initialization
+ * i Instance data
+ * s Solo data
+ */
+ #define NENOTP 0x8000 /* Not a process */
+ #define NEIERR 0x2000 /* Errors in image */
+ #define NEBOUND 0x0800 /* Bound Family/API */
+ #define NEAPPTYP 0x0700 /* Application type mask */
+ #define NENOTWINCOMPAT 0x0100 /* Not compatible with P.M. Windowing */
+ #define NEWINCOMPAT 0x0200 /* Compatible with P.M. Windowing */
+ #define NEWINAPI 0x0300 /* Uses P.M. Windowing API */
+ #define NEFLTP 0x0080 /* Floating-point instructions */
+ #define NEI386 0x0040 /* 386 instructions */
+ #define NEI286 0x0020 /* 286 instructions */
+ #define NEI086 0x0010 /* 8086 instructions */
+ #define NEPROT 0x0008 /* Runs in protected mode only */
+ #define NEPPLI 0x0004 /* Per-Process Library Initialization */
+ #define NEINST 0x0002 /* Instance data */
+ #define NESOLO 0x0001 /* Solo data */
+
+ /*
+ * Format of NE_FLAGSOTHERS(x):
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * | | | |
+ * | | | +---------------- Support for long file names
+ * | | +------------------ Windows 2.x app runs in prot mode
+ * | +-------------------- Windows 2.x app gets prop. font
+ * +------------------------------ WLO appl on OS/2 (markwlo.exe)
+ *
+ */
+
+ #define NELONGNAMES 0x01
+ #define NEWINISPROT 0x02
+ #define NEWINGETPROPFON 0x04
+ #define NEWLOAPPL 0x80
+
+
+
+ struct new_seg /* New .EXE segment table entry */
+ {
+ unsigned short ns_sector; /* File sector of start of segment */
+ unsigned short ns_cbseg; /* Number of bytes in file */
+ unsigned short ns_flags; /* Attribute flags */
+ unsigned short ns_minalloc; /* Minimum allocation in bytes */
+ };
+
+ #define NS_SECTOR(x) (x).ns_sector
+ #define NS_CBSEG(x) (x).ns_cbseg
+ #define NS_FLAGS(x) (x).ns_flags
+ #define NS_MINALLOC(x) (x).ns_minalloc
+
+
+ /*
+ * Format of NS_FLAGS(x)
+ *
+ * Flag word has the following format:
+ *
+ * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no
+ * | | | | | | | | | | | | | | |
+ * | | | | | | | | | | | | +-+-+--- Segment type DATA/CODE
+ * | | | | | | | | | | | +--------- Iterated segment
+ * | | | | | | | | | | +----------- Movable segment
+ * | | | | | | | | | +------------- Segment can be shared
+ * | | | | | | | | +--------------- Preload segment
+ * | | | | | | | +----------------- Execute/read-only for code/data segment
+ * | | | | | | +------------------- Segment has relocations
+ * | | | | | +--------------------- Code conforming/Data is expand down
+ * | | | +--+----------------------- I/O privilege level
+ * | | +----------------------------- Discardable segment
+ * | +-------------------------------- 32-bit code segment
+ * +----------------------------------- Huge segment/GDT allocation requested
+ *
+ */
+
+ #define NSTYPE 0x0007 /* Segment type mask */
+
+ #ifdef EXE386
+ #define NSCODE 0x0000 /* Code segment */
+ #define NSDATA 0x0001 /* Data segment */
+ #define NSITER 0x0008 /* Iterated segment flag */
+ #define NSMOVE 0x0010 /* Movable segment flag */
+ #define NSSHARED 0x0020 /* Shared segment flag */
+ #define NSPRELOAD 0x0040 /* Preload segment flag */
+ #define NSEXRD 0x0080 /* Execute-only (code segment), or
+ * read-only (data segment)
+ */
+ #define NSRELOC 0x0100 /* Segment has relocations */
+ #define NSCONFORM 0x0200 /* Conforming segment */
+ #define NSEXPDOWN 0x0200 /* Data segment is expand down */
+ #define NSDPL 0x0C00 /* I/O privilege level (286 DPL bits) */
+ #define SHIFTDPL 10 /* Left shift count for SEGDPL field */
+ #define NSDISCARD 0x1000 /* Segment is discardable */
+ #define NS32BIT 0x2000 /* 32-bit code segment */
+ #define NSHUGE 0x4000 /* Huge memory segment, length of
+ * segment and minimum allocation
+ * size are in segment sector units
+ */
+ #define NSGDT 0x8000 /* GDT allocation requested */
+
+ #define NSPURE NSSHARED /* For compatibility */
+
+ #define NSALIGN 9 /* Segment data aligned on 512 byte boundaries */
+
+ #define NSLOADED 0x0004 /* ns_sector field contains memory addr */
+ #endif
+
+
+ struct new_segdata /* Segment data */
+ {
+ union
+ {
+ struct
+ {
+ unsigned short ns_niter; /* number of iterations */
+ unsigned short ns_nbytes; /* number of bytes */
+ char ns_iterdata; /* iterated data bytes */
+ } ns_iter;
+ struct
+ {
+ char ns_data; /* data bytes */
+ } ns_noniter;
+ } ns_union;
+ };
+
+ struct new_rlcinfo /* Relocation info */
+ {
+ unsigned short nr_nreloc; /* number of relocation items that */
+ }; /* follow */
+
+ #pragma pack(1)
+
+
+ struct new_rlc /* Relocation item */
+ {
+ char nr_stype; /* Source type */
+ char nr_flags; /* Flag byte */
+ unsigned short nr_soff; /* Source offset */
+ union
+ {
+ struct
+ {
+ char nr_segno; /* Target segment number */
+ char nr_res; /* Reserved */
+ unsigned short nr_entry; /* Target Entry Table offset */
+ } nr_intref; /* Internal reference */
+ struct
+ {
+ unsigned short nr_mod; /* Index into Module Reference Table */
+ unsigned short nr_proc; /* Procedure ordinal or name offset */
+ } nr_import; /* Import */
+ struct
+ {
+ unsigned short nr_ostype; /* OSFIXUP type */
+ unsigned short nr_osres; /* reserved */
+ } nr_osfix; /* Operating system fixup */
+ } nr_union; /* Union */
+ };
+
+ #pragma pack()
+
+
+ #define NR_STYPE(x) (x).nr_stype
+ #define NR_FLAGS(x) (x).nr_flags
+ #define NR_SOFF(x) (x).nr_soff
+ #define NR_SEGNO(x) (x).nr_union.nr_intref.nr_segno
+ #define NR_RES(x) (x).nr_union.nr_intref.nr_res
+ #define NR_ENTRY(x) (x).nr_union.nr_intref.nr_entry
+ #define NR_MOD(x) (x).nr_union.nr_import.nr_mod
+ #define NR_PROC(x) (x).nr_union.nr_import.nr_proc
+ #define NR_OSTYPE(x) (x).nr_union.nr_osfix.nr_ostype
+ #define NR_OSRES(x) (x).nr_union.nr_osfix.nr_osres
+
+
+
+ /*
+ * Format of NR_STYPE(x) and R32_STYPE(x):
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * | | | |
+ * +-+-+-+--- source type
+ *
+ */
+
+ #define NRSTYP 0x0f /* Source type mask */
+ #define NRSBYT 0x00 /* lo byte (8-bits)*/
+ #define NRSSEG 0x02 /* 16-bit segment (16-bits) */
+ #define NRSPTR 0x03 /* 16:16 pointer (32-bits) */
+ #define NRSOFF 0x05 /* 16-bit offset (16-bits) */
+ #define NRPTR48 0x06 /* 16:32 pointer (48-bits) */
+ #define NROFF32 0x07 /* 32-bit offset (32-bits) */
+ #define NRSOFF32 0x08 /* 32-bit self-relative offset (32-bits) */
+
+
+ /*
+ * Format of NR_FLAGS(x) and R32_FLAGS(x):
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * | | |
+ * | +-+--- Reference type
+ * +------- Additive fixup
+ */
+
+ #define NRADD 0x04 /* Additive fixup */
+ #define NRRTYP 0x03 /* Reference type mask */
+ #define NRRINT 0x00 /* Internal reference */
+ #define NRRORD 0x01 /* Import by ordinal */
+ #define NRRNAM 0x02 /* Import by name */
+ #define NRROSF 0x03 /* Operating system fixup */
+
+
+ #if (EXE386 == 0)
+
+ /* Resource type or name string */
+ struct rsrc_string
+ {
+ char rs_len; /* number of bytes in string */
+ char rs_string[ 1 ]; /* text of string */
+ };
+
+ #define RS_LEN( x ) (x).rs_len
+ #define RS_STRING( x ) (x).rs_string
+
+ /* Resource type information block */
+ struct rsrc_typeinfo
+ {
+ unsigned short rt_id;
+ unsigned short rt_nres;
+ long rt_proc;
+ };
+
+ #define RT_ID( x ) (x).rt_id
+ #define RT_NRES( x ) (x).rt_nres
+ #define RT_PROC( x ) (x).rt_proc
+
+ /* Resource name information block */
+ struct rsrc_nameinfo
+ {
+ /* The following two fields must be shifted left by the value of */
+ /* the rs_align field to compute their actual value. This allows */
+ /* resources to be larger than 64k, but they do not need to be */
+ /* aligned on 512 byte boundaries, the way segments are */
+ unsigned short rn_offset; /* file offset to resource data */
+ unsigned short rn_length; /* length of resource data */
+ unsigned short rn_flags; /* resource flags */
+ unsigned short rn_id; /* resource name id */
+ unsigned short rn_handle; /* If loaded, then global handle */
+ unsigned short rn_usage; /* Initially zero. Number of times */
+ /* the handle for this resource has */
+ /* been given out */
+ };
+
+ #define RN_OFFSET( x ) (x).rn_offset
+ #define RN_LENGTH( x ) (x).rn_length
+ #define RN_FLAGS( x ) (x).rn_flags
+ #define RN_ID( x ) (x).rn_id
+ #define RN_HANDLE( x ) (x).rn_handle
+ #define RN_USAGE( x ) (x).rn_usage
+
+ #define RSORDID 0x8000 /* if high bit of ID set then integer id */
+ /* otherwise ID is offset of string from
+ the beginning of the resource table */
+
+ /* Ideally these are the same as the */
+ /* corresponding segment flags */
+ #define RNMOVE 0x0010 /* Moveable resource */
+ #define RNPURE 0x0020 /* Pure (read-only) resource */
+ #define RNPRELOAD 0x0040 /* Preloaded resource */
+ #define RNDISCARD 0xF000 /* Discard priority level for resource */
+
+ /* Resource table */
+ struct new_rsrc
+ {
+ unsigned short rs_align; /* alignment shift count for resources */
+ struct rsrc_typeinfo rs_typeinfo;
+ };
+
+ #define RS_ALIGN( x ) (x).rs_align
+
+
+ #endif /* NOT EXE386 */
+
+ #endif /* __NEWEXE__ */
+
+ #ifndef DWORD
+ #define DWORD long int
+ #endif
+
+ #ifndef WORD
+ #define WORD short int
+ #endif
+
+ #ifndef __EXE386__
+ #define __EXE386__
+
+ #pragma pack(1) /* Force byte alignment */
+
+ /*_________________________________________________________________*
+ | |
+ | |
+ | OS/2 .EXE FILE HEADER DEFINITION - 386 version 0:32 |
+ | |
+ |_________________________________________________________________|
+ * */
+
+ #define BITPERWORD 16
+ #define BITPERBYTE 8
+ #define OBJPAGELEN 4096
+ #define E32MAGIC1 'L' /* New magic number "LX" */
+ #define E32MAGIC2 'X' /* New magic number "LX" */
+ #define E32MAGIC 0x584c /* New magic number "LX" */
+ #define E32RESBYTES1 0 /* First bytes reserved */
+ #define E32RESBYTES2 0 /* Second bytes reserved */
+ #define E32RESBYTES3 20 /* Third bytes reserved */
+ #define E32LEBO 0x00 /* Little Endian Byte Order */
+ #define E32BEBO 0x01 /* Big Endian Byte Order */
+ #define E32LEWO 0x00 /* Little Endian Word Order */
+ #define E32BEWO 0x01 /* Big Endian Word Order */
+ #define E32LEVEL 0L /* 32-bit EXE format level */
+ #define E32CPU286 0x001 /* Intel 80286 or upwardly compatibile */
+ #define E32CPU386 0x002 /* Intel 80386 or upwardly compatibile */
+ #define E32CPU486 0x003 /* Intel 80486 or upwardly compatibile */
+
+
+
+ struct e32_exe /* New 32-bit .EXE header */
+ {
+ unsigned char e32_magic[2]; /* Magic number E32_MAGIC */
+ unsigned char e32_border; /* The byte ordering for the .EXE */
+ unsigned char e32_worder; /* The word ordering for the .EXE */
+ unsigned long e32_level; /* The EXE format level for now = 0 */
+ unsigned short e32_cpu; /* The CPU type */
+ unsigned short e32_os; /* The OS type */
+ unsigned long e32_ver; /* Module version */
+ unsigned long e32_mflags; /* Module flags */
+ unsigned long e32_mpages; /* Module # pages */
+ unsigned long e32_startobj; /* Object # for instruction pointer */
+ unsigned long e32_eip; /* Extended instruction pointer */
+ unsigned long e32_stackobj; /* Object # for stack pointer */
+ unsigned long e32_esp; /* Extended stack pointer */
+ unsigned long e32_pagesize; /* .EXE page size */
+ unsigned long e32_pageshift; /* Page alignment shift in .EXE */
+ unsigned long e32_fixupsize; /* Fixup section size */
+ unsigned long e32_fixupsum; /* Fixup section checksum */
+ unsigned long e32_ldrsize; /* Loader section size */
+ unsigned long e32_ldrsum; /* Loader section checksum */
+ unsigned long e32_objtab; /* Object table offset */
+ unsigned long e32_objcnt; /* Number of objects in module */
+ unsigned long e32_objmap; /* Object page map offset */
+ unsigned long e32_itermap; /* Object iterated data map offset */
+ unsigned long e32_rsrctab; /* Offset of Resource Table */
+ unsigned long e32_rsrccnt; /* Number of resource entries */
+ unsigned long e32_restab; /* Offset of resident name table */
+ unsigned long e32_enttab; /* Offset of Entry Table */
+ unsigned long e32_dirtab; /* Offset of Module Directive Table */
+ unsigned long e32_dircnt; /* Number of module directives */
+ unsigned long e32_fpagetab; /* Offset of Fixup Page Table */
+ unsigned long e32_frectab; /* Offset of Fixup Record Table */
+ unsigned long e32_impmod; /* Offset of Import Module Name Table */
+ unsigned long e32_impmodcnt; /* Number of entries in Import Module Name Table */
+ unsigned long e32_impproc; /* Offset of Import Procedure Name Table */
+ unsigned long e32_pagesum; /* Offset of Per-Page Checksum Table */
+ unsigned long e32_datapage; /* Offset of Enumerated Data Pages */
+ unsigned long e32_preload; /* Number of preload pages */
+ unsigned long e32_nrestab; /* Offset of Non-resident Names Table */
+ unsigned long e32_cbnrestab; /* Size of Non-resident Name Table */
+ unsigned long e32_nressum; /* Non-resident Name Table Checksum */
+ unsigned long e32_autodata; /* Object # for automatic data object */
+ unsigned long e32_debuginfo; /* Offset of the debugging information */
+ unsigned long e32_debuglen; /* The length of the debugging info. in bytes */
+ unsigned long e32_instpreload;/* Number of instance pages in preload section of .EXE file */
+ unsigned long e32_instdemand; /* Number of instance pages in demand load section of .EXE file */
+ unsigned long e32_heapsize; /* Size of heap - for 16-bit apps */
+ unsigned long e32_stacksize; /* Size of stack */
+ unsigned char e32_res3[E32RESBYTES3];
+ /* Pad structure to 196 bytes */
+ };
+
+
+
+ #define E32_MAGIC1(x) (x).e32_magic[0]
+ #define E32_MAGIC2(x) (x).e32_magic[1]
+ #define E32_BORDER(x) (x).e32_border
+ #define E32_WORDER(x) (x).e32_worder
+ #define E32_LEVEL(x) (x).e32_level
+ #define E32_CPU(x) (x).e32_cpu
+ #define E32_OS(x) (x).e32_os
+ #define E32_VER(x) (x).e32_ver
+ #define E32_MFLAGS(x) (x).e32_mflags
+ #define E32_MPAGES(x) (x).e32_mpages
+ #define E32_STARTOBJ(x) (x).e32_startobj
+ #define E32_EIP(x) (x).e32_eip
+ #define E32_STACKOBJ(x) (x).e32_stackobj
+ #define E32_ESP(x) (x).e32_esp
+ #define E32_PAGESIZE(x) (x).e32_pagesize
+ #define E32_PAGESHIFT(x) (x).e32_pageshift
+ #define E32_FIXUPSIZE(x) (x).e32_fixupsize
+ #define E32_FIXUPSUM(x) (x).e32_fixupsum
+ #define E32_LDRSIZE(x) (x).e32_ldrsize
+ #define E32_LDRSUM(x) (x).e32_ldrsum
+ #define E32_OBJTAB(x) (x).e32_objtab
+ #define E32_OBJCNT(x) (x).e32_objcnt
+ #define E32_OBJMAP(x) (x).e32_objmap
+ #define E32_ITERMAP(x) (x).e32_itermap
+ #define E32_RSRCTAB(x) (x).e32_rsrctab
+ #define E32_RSRCCNT(x) (x).e32_rsrccnt
+ #define E32_RESTAB(x) (x).e32_restab
+ #define E32_ENTTAB(x) (x).e32_enttab
+ #define E32_DIRTAB(x) (x).e32_dirtab
+ #define E32_DIRCNT(x) (x).e32_dircnt
+ #define E32_FPAGETAB(x) (x).e32_fpagetab
+ #define E32_FRECTAB(x) (x).e32_frectab
+ #define E32_IMPMOD(x) (x).e32_impmod
+ #define E32_IMPMODCNT(x) (x).e32_impmodcnt
+ #define E32_IMPPROC(x) (x).e32_impproc
+ #define E32_PAGESUM(x) (x).e32_pagesum
+ #define E32_DATAPAGE(x) (x).e32_datapage
+ #define E32_PRELOAD(x) (x).e32_preload
+ #define E32_NRESTAB(x) (x).e32_nrestab
+ #define E32_CBNRESTAB(x) (x).e32_cbnrestab
+ #define E32_NRESSUM(x) (x).e32_nressum
+ #define E32_AUTODATA(x) (x).e32_autodata
+ #define E32_DEBUGINFO(x) (x).e32_debuginfo
+ #define E32_DEBUGLEN(x) (x).e32_debuglen
+ #define E32_INSTPRELOAD(x) (x).e32_instpreload
+ #define E32_INSTDEMAND(x) (x).e32_instdemand
+ #define E32_HEAPSIZE(x) (x).e32_heapsize
+ #define E32_STACKSIZE(x) (x).e32_stacksize
+
+
+
+ /*
+ * Format of E32_MFLAGS(x):
+ *
+ * Low word has the following format:
+ *
+ * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no
+ * | | | | | | | |
+ * | | | | | | | +------- Per-Process Library Initialization
+ * | | | | | | +--------- SystemDLL (internal fixups discarded)
+ * | | | | | +----------- No Internal Fixups for Module in .EXE
+ * | | | | +------------- No External Fixups for Module in .EXE
+ * | | | +------------------- Incompatible with PM Windowing
+ * | | +--------------------- Compatible with PM Windowing
+ * | | Uses PM Windowing API
+ * | +-------------------------------- Module not Loadable
+ * +-------------------------------------- Library Module
+ */
+
+
+ #define E32NOTP 0x8000L /* Library Module - used as NENOTP */
+ #define E32NOLOAD 0x2000L /* Module not Loadable */
+ #define E32PMAPI 0x0300L /* Uses PM Windowing API */
+ #define E32PMW 0x0200L /* Compatible with PM Windowing */
+ #define E32NOPMW 0x0100L /* Incompatible with PM Windowing */
+ #define E32NOEXTFIX 0x0020L /* NO External Fixups in .EXE */
+ #define E32NOINTFIX 0x0010L /* NO Internal Fixups in .EXE */
+ #define E32SYSDLL 0x0008L /* System DLL, Internal Fixups discarded*/
+ #define E32LIBINIT 0x0004L /* Per-Process Library Initialization */
+ #define E32LIBTERM 0x40000000L /* Per-Process Library Termination */
+ #define E32APPMASK 0x0300L /* Application Type Mask */
+
+
+ /*
+ * Format of E32_MFLAGS(x):
+ *
+ * High word has the following format:
+ *
+ * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no
+ * | |
+ * | +--- Protected memory library module
+ * +----- Device driver
+ */
+
+ #define E32PROTDLL 0x10000L /* Protected memory library module */
+ #define E32DEVICE 0x20000L /* Device driver */
+ #define E32MODEXE 0x00000L /* .EXE module */
+ #define E32MODDLL 0x08000L /* .DLL module */
+ #define E32MODPROTDLL 0x18000L /* Protected memory library module */
+ #define E32MODPDEV 0x20000L /* Physical device driver */
+ #define E32MODVDEV 0x28000L /* Virtual device driver */
+ #define E32MODMASK 0x38000L /* Module type mask */
+
+ /*
+ * RELOCATION DEFINITIONS - RUN-TIME FIXUPS
+ */
+
+ typedef union _RELOC_OFS
+ {
+ unsigned short offset16;
+ unsigned long offset32;
+ } RELOC_OFS; /* 16-bit or 32-bit offset */
+
+
+ /***ET+ r32_rlc - Relocation item */
+
+ struct r32_rlc /* Relocation item */
+ {
+ unsigned char nr_stype; /* Source type - field shared with new_rlc */
+ unsigned char nr_flags; /* Flag byte - field shared with new_rlc */
+ short r32_soff; /* Source offset */
+ unsigned short r32_objmod; /* Target object number or Module ordinal */
+
+ union targetid
+ {
+ RELOC_OFS intref; /* Internal fixup */
+
+ union extfixup
+ {
+ RELOC_OFS proc; /* Procedure name offset */
+ unsigned long ord; /* Procedure odrinal */
+ } extref; /* External fixup */
+
+ struct addfixup
+ {
+ unsigned short entry; /* Entry ordinal */
+ RELOC_OFS addval; /* Value added to the address */
+ } addfix; /* Additive fixup */
+ }
+ r32_target; /* Target data */
+ unsigned short r32_srccount; /* Number of chained fixup records */
+ unsigned short r32_chain; /* Chain head */
+ };
+
+ /*
+ * In 32-bit .EXE file run-time relocations are written as varying size
+ * records, so we need many size definitions.
+ */
+
+ #define RINTSIZE16 8
+ #define RINTSIZE32 10
+ #define RORDSIZE 8
+ #define RNAMSIZE16 8
+ #define RNAMSIZE32 10
+ #define RADDSIZE16 10
+ #define RADDSIZE32 12
+
+ #if FALSE
+ /*
+ * Access macros defined in NEWEXE.H !!!
+ */
+ #define NR_STYPE(x) (x).nr_stype
+ #define NR_FLAGS(x) (x).nr_flags
+ #endif
+
+ #define R32_SOFF(x) (x).r32_soff
+ #define R32_OBJNO(x) (x).r32_objmod
+ #define R32_MODORD(x) (x).r32_objmod
+ #define R32_OFFSET16(x) (x).r32_target.intref.offset16
+ #define R32_OFFSET32(x) (x).r32_target.intref.offset32
+ #define R32_PROCOFF16(x) (x).r32_target.extref.proc.offset16
+ #define R32_PROCOFF32(x) (x).r32_target.extref.proc.offset32
+ #define R32_PROCORD(x) (x).r32_target.extref.ord
+ #define R32_ENTRY(x) (x).r32_target.addfix.entry
+ #define R32_ADDVAL16(x) (x).r32_target.addfix.addval.offset16
+ #define R32_ADDVAL32(x) (x).r32_target.addfix.addval.offset32
+ #define R32_SRCCNT(x) (x).r32_srccount
+ #define R32_CHAIN(x) (x).r32_chain
+
+
+
+ /*
+ * Format of NR_STYPE(x)
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * | | | | | |
+ * | | +-+-+-+--- Source type
+ * | +----------- Fixup to 16:16 alias
+ * +------------- List of source offset follows fixup record
+ */
+
+ #if FALSE
+
+ /* DEFINED in newexe.h !!! */
+
+ #define NRSTYP 0x0f /* Source type mask */
+ #define NRSBYT 0x00 /* lo byte (8-bits)*/
+ #define NRSSEG 0x02 /* 16-bit segment (16-bits) */
+ #define NRSPTR 0x03 /* 16:16 pointer (32-bits) */
+ #define NRSOFF 0x05 /* 16-bit offset (16-bits) */
+ #define NRPTR48 0x06 /* 16:32 pointer (48-bits) */
+ #define NROFF32 0x07 /* 32-bit offset (32-bits) */
+ #define NRSOFF32 0x08 /* 32-bit self-relative offset (32-bits) */
+ #endif
+
+
+ #define NRSRCMASK 0x0f /* Source type mask */
+ #define NRALIAS 0x10 /* Fixup to alias */
+ #define NRCHAIN 0x20 /* List of source offset follows */
+ /* fixup record, source offset field */
+ /* in fixup record contains number */
+ /* of elements in list */
+
+ /*
+ * Format of NR_FLAGS(x) and R32_FLAGS(x):
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * | | | | | | |
+ * | | | | | +-+--- Reference type
+ * | | | | +------- Additive fixup
+ * | | | +----------- 32-bit Target Offset Flag (1 - 32-bit; 0 - 16-bit)
+ * | | +------------- 32-bit Additive Flag (1 - 32-bit; 0 - 16-bit)
+ * | +--------------- 16-bit Object/Module ordinal (1 - 16-bit; 0 - 8-bit)
+ * +----------------- 8-bit import ordinal (1 - 8-bit;
+ * 0 - NR32BITOFF toggles
+ * between 16 and 32 bit
+ * ordinal)
+ */
+
+ #ifdef NEVER_INCLUDE_THE_FOLLWING
+ /* DEFINED in newexe.h !!! */
+ #define NRRTYP 0x03 /* Reference type mask */
+ #define NRRINT 0x00 /* Internal reference */
+ #define NRRORD 0x01 /* Import by ordinal */
+ #define NRRNAM 0x02 /* Import by name */
+ #define NRADD 0x04 /* Additive fixup */
+ #endif
+
+ #define NRRENT 0x03 /* Internal entry table fixup */
+
+ #define NR32BITOFF 0x10 /* 32-bit Target Offset */
+ #define NR32BITADD 0x20 /* 32-bit Additive fixup */
+ #define NR16OBJMOD 0x40 /* 16-bit Object/Module ordinal */
+ #define NR8BITORD 0x80 /* 8-bit import ordinal */
+ /*end*/
+
+ /*
+ * Data structures for storing run-time fixups in linker virtual memory.
+ *
+ * Each object has a list of Object Page Directories which specify
+ * fixups for given page. Each page has its own hash table which is
+ * used to detect fixups to the same target.
+ */
+
+ #define PAGEPERDIR 62
+ #define LG2DIR 7
+
+
+ typedef struct _OBJPAGEDIR
+ {
+ DWORD next; /* Virtual pointer to next dir on list */
+ WORD ht[PAGEPERDIR]; /* Pointers to individual hash tables */
+ }
+ OBJPAGEDIR;
+
+ /*
+ * OBJECT TABLE
+ */
+
+ /***ET+ o32_obj Object Table Entry */
+
+ struct o32_obj /* Flat .EXE object table entry */
+ {
+ unsigned long o32_size; /* Object virtual size */
+ unsigned long o32_base; /* Object base virtual address */
+ unsigned long o32_flags; /* Attribute flags */
+ unsigned long o32_pagemap; /* Object page map index */
+ unsigned long o32_mapsize; /* Number of entries in object page map */
+ unsigned long o32_reserved; /* Reserved */
+ };
+
+
+ #define O32_SIZE(x) (x).o32_size
+ #define O32_BASE(x) (x).o32_base
+ #define O32_FLAGS(x) (x).o32_flags
+ #define O32_PAGEMAP(x) (x).o32_pagemap
+ #define O32_MAPSIZE(x) (x).o32_mapsize
+ #define O32_RESERVED(x) (x).o32_reserved
+
+ /*
+ * Format of O32_FLAGS(x)
+ *
+ * High word of dword flag field is not used for now.
+ * Low word has the following format:
+ *
+ * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - bit no
+ * | | | | | | | | | | | | | | |
+ * | | | | | | | | | | | | | | +--- Readable Object
+ * | | | | | | | | | | | | | +----- Writeable Object
+ * | | | | | | | | | | | | +------- Executable Object
+ * | | | | | | | | | | | +--------- Resource Object
+ * | | | | | | | | | | +----------- Object is Discardable
+ * | | | | | | | | | +------------- Object is Shared
+ * | | | | | | | | +--------------- Object has preload pages
+ * | | | | | | | +----------------- Object has invalid pages
+ * | | | | | | +------------------- Object is permanent and swappable
+ * | | | | | +--------------------- Object is permanent and resident
+ * | | | | +----------------------- Object is permanent and long lockable
+ * | | | +----------------------------- 16:16 alias required (80x86 specific)
+ * | | +-------------------------------- Big/Default bit setting (80x86 specific)
+ * | +----------------------------------- Object is conforming for code (80x86 specific)
+ * +-------------------------------------- Object I/O privilege level (80x86 specific)
+ *
+ */
+
+ #define OBJREAD 0x0001L /* Readable Object */
+ #define OBJWRITE 0x0002L /* Writeable Object */
+ #define OBJRSRC 0x0008L /* Resource Object */
+ #define OBJINVALID 0x0080L /* Object has invalid pages */
+ #define LNKNONPERM 0x0600L /* Object is nonpermanent - should be */
+ #define OBJNONPERM 0x0000L /* zero in the .EXE but LINK386 uses 6 */
+ #define OBJPERM 0x0100L /* Object is permanent and swappable */
+ #define OBJRESIDENT 0x0200L /* Object is permanent and resident */
+ #define OBJCONTIG 0x0300L /* Object is resident and contiguous */
+ #define OBJDYNAMIC 0x0400L /* Object is permanent and long locable */
+ #define OBJTYPEMASK 0x0700L /* Object type mask */
+ #define OBJALIAS16 0x1000L /* 16:16 alias required (80x86 specific) */
+ #define OBJBIGDEF 0x2000L /* Big/Default bit setting (80x86 specific) */
+ #define OBJIOPL 0x8000L /* Object I/O privilege level (80x86 specific) */
+ #if FOR_EXEHDR
+ /*
+ * Name these flags differently for EXEHDR.EXE - avoid conflicts with 286 version
+ */
+ #define OBJDISCARD 0x0010L /* Object is Discardable */
+ #define OBJSHARED 0x0020L /* Object is Shared */
+ #define OBJPRELOAD 0x0040L /* Object has preload pages */
+ #define OBJEXEC 0x0004L /* Executable Object */
+ #define OBJCONFORM 0x4000L /* Object is conforming for code (80x86 specific) */
+ #else
+ /*
+ * Life will be easier, if we keep the same names for the following flags:
+ */
+ #ifndef NSDISCARD
+ #define NSDISCARD 0x0010L /* Object is Discardable */
+ #endif
+ #ifndef NSMOVE
+ #define NSMOVE NSDISCARD /* Moveable object is for sure Discardable */
+ #endif
+ #ifndef NSSHARED
+ #define NSSHARED 0x0020L /* Object is Shared */
+ #endif
+ #ifndef NSPRELOAD
+ #define NSPRELOAD 0x0040L /* Object has preload pages */
+ #endif
+ #ifndef NSEXRD
+ #define NSEXRD 0x0004L /* Executable Object */
+ #endif
+ #ifndef NSCONFORM
+ #define NSCONFORM 0x4000L /* Object is conforming for code (80x86 specific) */
+ #endif
+ #endif
+ /*end*/
+
+ /***ET+ o32_map - Object Page Map entry */
+
+ struct o32_map /* Object Page Table entry */
+ {
+ unsigned long o32_pagedataoffset; /* file offset of page */
+ unsigned short o32_pagesize; /* # bytes of page data */
+ unsigned short o32_pageflags; /* Per-Page attributes */
+ };
+
+
+ #define GETPAGEIDX(x) ((x).o32_pagedataoffset)
+
+ #define PUTPAGEIDX(x,i) ((x).o32_pagedataoffset = ((unsigned long)(i)))
+
+ #define PUTPAGESIZ(x,i) ((x).o32_pagesize = ((unsigned int)(i)))
+
+ #define GETPAGESIZ(x) ((x).o32_pagesize)
+
+ #define PAGEFLAGS(x) (x).o32_pageflags
+
+
+ #define VALID 0x0000 /* Valid Physical Page in .EXE */
+ #define ITERDATA 0x0001 /* Iterated Data Page */
+ #define INVALID 0x0002 /* Invalid Page */
+ #define ZEROED 0x0003 /* Zero Filled Page */
+ #define RANGE 0x0004 /* Range of pages */
+ #define ITERDATA2 0x0005 /* Iterated Data Page Type II */
+ /*end*/
+
+ /*
+ * RESOURCE TABLE
+ */
+
+ /***ET+ rsrc32 - Resource Table Entry */
+
+ struct rsrc32 /* Resource Table Entry */
+ {
+ unsigned short type; /* Resource type */
+ unsigned short name; /* Resource name */
+ unsigned long cb; /* Resource size */
+ unsigned short obj; /* Object number */
+ unsigned long offset; /* Offset within object */
+ };
+ /*end*/
+
+
+ /*
+ * Iteration Record format for 'EXEPACK'ed pages.
+ */
+ struct LX_Iter
+ {
+ unsigned short LX_nIter; /* number of iterations */
+ unsigned short LX_nBytes; /* number of bytes */
+ unsigned char LX_Iterdata; /* iterated data byte(s) */
+ };
+
+
+ /*
+ * ENTRY TABLE DEFINITIONS
+ */
+
+ /***ET+ b32_bundle - Entry Table */
+
+ struct b32_bundle
+ {
+ unsigned char b32_cnt; /* Number of entries in this bundle */
+ unsigned char b32_type; /* Bundle type */
+ unsigned short b32_obj; /* Object number */
+ }; /* Follows entry types */
+
+ struct e32_entry
+ {
+ unsigned char e32_flags; /* Entry point flags */
+ union entrykind
+ {
+ RELOC_OFS e32_offset; /* 16-bit/32-bit offset entry */
+ struct callgate
+ {
+ unsigned short offset; /* Offset in segment */
+ unsigned short callgate; /* Callgate selector */
+ }
+ e32_callgate; /* 286 (16-bit) call gate */
+ struct fwd
+ {
+ unsigned short modord; /* Module ordinal number */
+ unsigned long value; /* Proc name offset or ordinal */
+ }
+ e32_fwd; /* Forwarder */
+ }
+ e32_variant; /* Entry variant */
+ };
+
+
+
+ #define B32_CNT(x) (x).b32_cnt
+ #define B32_TYPE(x) (x).b32_type
+ #define B32_OBJ(x) (x).b32_obj
+
+ #define E32_EFLAGS(x) (x).e32_flags
+ #define E32_OFFSET16(x) (x).e32_variant.e32_offset.offset16
+ #define E32_OFFSET32(x) (x).e32_variant.e32_offset.offset32
+ #define E32_GATEOFF(x) (x).e32_variant.e32_callgate.offset
+ #define E32_GATE(x) (x).e32_variant.e32_callgate.callgate
+ #define E32_MODORD(x) (x).e32_variant.e32_fwd.modord
+ #define E32_VALUE(x) (x).e32_variant.e32_fwd.value
+
+ #define FIXENT16 3
+ #define FIXENT32 5
+ #define GATEENT16 5
+ #define FWDENT 7
+
+ /*
+ * BUNDLE TYPES
+ */
+
+ #define EMPTY 0x00 /* Empty bundle */
+ #define ENTRY16 0x01 /* 16-bit offset entry point */
+ #define GATE16 0x02 /* 286 call gate (16-bit IOPL) */
+ #define ENTRY32 0x03 /* 32-bit offset entry point */
+ #define ENTRYFWD 0x04 /* Forwarder entry point */
+ #define TYPEINFO 0x80 /* Typing information present flag */
+
+
+ /*
+ * Format for E32_EFLAGS(x)
+ *
+ * 7 6 5 4 3 2 1 0 - bit no
+ * | | | | | | | |
+ * | | | | | | | +--- exported entry
+ * | | | | | | +----- uses shared data
+ * +-+-+-+-+-+------- parameter word count
+ */
+
+ #define E32EXPORT 0x01 /* Exported entry */
+ #define E32SHARED 0x02 /* Uses shared data */
+ #define E32PARAMS 0xf8 /* Parameter word count mask */
+
+ /*
+ * Flags for forwarders only:
+ */
+
+ #define FWD_ORDINAL 0x01 /* Imported by ordinal */
+
+
+ #pragma pack() /* Restore default alignment */
+
+ /*end*/
+
+ #endif /* __EXE386__ */
+
+#endif
diff --git a/sal/osl/os2/helpers/dosh.h b/sal/osl/os2/helpers/dosh.h
new file mode 100644
index 000000000000..fe51ee9bc488
--- /dev/null
+++ b/sal/osl/os2/helpers/dosh.h
@@ -0,0 +1,49 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/* This file Copyright (C) 1997-2006 Ulrich M�ller,
+ * Dmitry A. Steklenev.
+ * This file is part of the "XWorkplace helpers" source package.
+ *
+ * 2009-06-15 published under LGPL3 with Ulrich M�ller permission.
+ *
+ */
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef DOSH_HEADER_INCLUDED
+ #define DOSH_HEADER_INCLUDED
+
+ CHAR doshQueryBootDrive(VOID);
+
+#endif
+
+#if __cplusplus
+}
+#endif
diff --git a/sal/osl/os2/helpers/except.h b/sal/osl/os2/helpers/except.h
new file mode 100644
index 000000000000..af303a9827e3
--- /dev/null
+++ b/sal/osl/os2/helpers/except.h
@@ -0,0 +1,255 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*
+ *@@sourcefile except.h:
+ * header file for except.c. See remarks there.
+ *
+ * Note: Version numbering in this file relates to XWorkplace version
+ * numbering.
+ *
+ *@@include #define INCL_DOSEXCEPTIONS
+ *@@include #define INCL_DOSPROCESS
+ *@@include #include <os2.h>
+ *@@include #include <stdio.h>
+ *@@include #include <setjmp.h>
+ *@@include #include "helpers\except.h"
+ */
+
+/*
+ * Copyright (C) 1999-2000 Ulrich M�ller.
+ *
+ * 2009-06-15 published under LGPL3 with Ulrich M�ller permission.
+ *
+ */
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef EXCEPT_HEADER_INCLUDED
+ #define EXCEPT_HEADER_INCLUDED
+
+ #if defined __IBMCPP__ || defined __IBMC__
+ #ifndef INCL_DOSEXCEPTIONS
+ #error except.h requires INCL_DOSEXCEPTIONS to be defined.
+ #endif
+ #ifndef INCL_DOSPROCESS
+ #error except.h requires INCL_DOSPROCESS to be defined.
+ #endif
+
+ #ifndef __stdio_h
+ #error except.h requires stdio.h to be included.
+ #endif
+ #ifndef __setjmp_h
+ #error except.h requires setjmp.h to be included.
+ #endif
+ #endif
+
+ /********************************************************************
+ *
+ * Declarations
+ *
+ ********************************************************************/
+
+ // forward declaration
+ typedef struct _EXCEPTIONREGISTRATIONRECORD2 *PEXCEPTIONREGISTRATIONRECORD2;
+
+ // "OnKill" function prototype for EXCEPTIONREGISTRATIONRECORD2
+ // added V0.9.0 (99-10-22) [umoeller]
+ // removed V0.9.7 (2000-12-08) [umoeller]
+ // typedef VOID APIENTRY FNEXCONKILL(PEXCEPTIONREGISTRATIONRECORD2);
+ // typedef FNEXCONKILL *PFNEXCONKILL;
+
+ /*
+ *@@ EXCEPTIONREGISTRATIONRECORD2:
+ * replacement EXCEPTIONREGISTRATIONRECORD
+ * struct for thread exception handling.
+ *
+ *@@changed V0.9.0 (99-10-22) [umoeller]: pfnOnKill added
+ *@@changed V0.9.0 (99-10-22) [umoeller]: renamed from REGREC2
+ */
+
+ typedef struct _EXCEPTIONREGISTRATIONRECORD2
+ {
+ PVOID pNext; // as in EXCEPTIONREGISTRATIONRECORD
+ PFN pfnHandler; // as in EXCEPTIONREGISTRATIONRECORD
+ jmp_buf jmpThread; // additional buffer for setjmp
+ EXCEPTIONREPORTRECORD err; // exception handlers copy the report rec here
+ PVOID pvUser; // user ptr
+ } EXCEPTIONREGISTRATIONRECORD2;
+
+ /*
+ *@@ EXCEPTSTRUCT:
+ * structure used with TRY_xxx macros.
+ */
+
+ typedef struct _EXCEPTSTRUCT
+ {
+ EXCEPTIONREGISTRATIONRECORD2 RegRec2;
+ ULONG ulExcpt; // != NULL if exception caught
+ APIRET arc; // rc of DosSetExceptionHandler
+ } EXCEPTSTRUCT, *PEXCEPTSTRUCT;
+
+ // function prototypes for exception hooks (V0.9.0)
+
+ // "open traplog file" hook
+ typedef FILE* APIENTRY FNEXCOPENFILE(VOID);
+ typedef FNEXCOPENFILE *PFNEXCOPENFILE;
+
+ // "exception" hook
+ typedef VOID APIENTRY FNEXCHOOK(FILE*, PTIB, ULONG); // V0.9.16 (2001-12-02) [pr]
+ typedef FNEXCHOOK *PFNEXCHOOK;
+
+ // "error" hook
+ typedef VOID APIENTRY FNEXCHOOKERROR(const char *pcszFile,
+ ULONG ulLine,
+ const char *pcszFunction,
+ APIRET arc);
+ typedef FNEXCHOOKERROR *PFNEXCHOOKERROR;
+
+ /********************************************************************
+ *
+ * Prototypes
+ *
+ ********************************************************************/
+
+ VOID excExplainException(FILE *file,
+ PSZ pszHandlerName,
+ PEXCEPTIONREPORTRECORD pReportRec,
+ PCONTEXTRECORD pContextRec);
+
+ VOID excRegisterHooks(PFNEXCOPENFILE pfnExcOpenFileNew,
+ PFNEXCHOOK pfnExcHookNew,
+ PFNEXCHOOKERROR pfnExcHookError,
+ BOOL fBeepOnExceptionNew);
+
+ ULONG _System excHandlerLoud(PEXCEPTIONREPORTRECORD pReportRec,
+ PEXCEPTIONREGISTRATIONRECORD2 pRegRec2,
+ PCONTEXTRECORD pContextRec,
+ PVOID pv);
+
+ ULONG _System excHandlerQuiet(PEXCEPTIONREPORTRECORD pReportRec,
+ PEXCEPTIONREGISTRATIONRECORD2 pRegRec2,
+ PCONTEXTRECORD pContextRec,
+ PVOID pv);
+
+ extern PFNEXCHOOKERROR G_pfnExcHookError;
+
+ extern ULONG G_ulExplainExceptionRunning;
+
+ /********************************************************************
+ *
+ * Macros
+ *
+ ********************************************************************/
+
+ /* See except.c for explanations how to use these. */
+
+ #ifdef __NO_EXCEPTION_HANDLERS__
+ // exception handlers can completely be disabled
+ #define TRY_LOUD(excptstruct)
+ #else
+ #ifdef __NO_LOUD_EXCEPTION_HANDLERS__
+ #define TRY_LOUD(e) TRY_QUIET(e)
+ #else // __NO_LOUD_EXCEPTION_HANDLERS__
+ #define TRY_LOUD(excptstruct) \
+ { \
+ EXCEPTSTRUCT excptstruct = {0}; \
+ excptstruct.RegRec2.pfnHandler = (PFN)excHandlerLoud; \
+ excptstruct.arc = DosSetExceptionHandler( \
+ (PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); \
+ if (excptstruct.arc) \
+ if (G_pfnExcHookError) \
+ G_pfnExcHookError(__FILE__, __LINE__, __FUNCTION__, excptstruct.arc); \
+ else \
+ DosBeep(1000, 1000); \
+ excptstruct.ulExcpt = setjmp(excptstruct.RegRec2.jmpThread); \
+ if (excptstruct.ulExcpt == 0) \
+ {
+
+ #endif // __NO_LOUD_EXCEPTION_HANDLERS__
+ #endif
+
+ #ifdef __NO_EXCEPTION_HANDLERS__
+ // exception handlers can completely be disabled
+ #define TRY_QUIET(excptstruct)
+ #else
+ #define TRY_QUIET(excptstruct) \
+ { \
+ EXCEPTSTRUCT excptstruct = {0}; \
+ excptstruct.RegRec2.pfnHandler = (PFN)excHandlerQuiet; \
+ excptstruct.arc = DosSetExceptionHandler( \
+ (PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); \
+ if (excptstruct.arc) \
+ if (G_pfnExcHookError) \
+ G_pfnExcHookError(__FILE__, __LINE__, __FUNCTION__, excptstruct.arc); \
+ else \
+ DosBeep(1000, 1000); \
+ excptstruct.ulExcpt = setjmp(excptstruct.RegRec2.jmpThread); \
+ if (excptstruct.ulExcpt == 0) \
+ {
+
+ #endif
+
+ #ifdef __NO_EXCEPTION_HANDLERS__
+ // exception handlers can completely be disabled
+ #define CATCH(excptstruct) if (FALSE) {
+ #else
+ #define CATCH(excptstruct) \
+ DosUnsetExceptionHandler( \
+ (PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); \
+ } /* end of TRY block */ \
+ else \
+ { /* exception occured: */ \
+ DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2));
+ #endif
+
+ #ifdef __NO_EXCEPTION_HANDLERS__
+ // exception handlers can completely be disabled
+ #define END_CATCH() }
+ #else
+ #define END_CATCH() \
+ } /* end of exception-occured block */ \
+ }
+ #endif
+
+ /*
+ * CRASH:
+ * this macro is helpful for testing
+ * the exception handlers.
+ * This is not for general use. ;-)
+ */
+
+ #define CRASH {PSZ p = NULL; *p = 'a'; }
+
+#endif // EXCEPT_HEADER_INCLUDED
+
+#if __cplusplus
+}
+#endif
+
diff --git a/sal/osl/os2/helpers/setup.h b/sal/osl/os2/helpers/setup.h
new file mode 100644
index 000000000000..b9c6e50f0111
--- /dev/null
+++ b/sal/osl/os2/helpers/setup.h
@@ -0,0 +1,147 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*
+ * setup.h:
+ * sample master include file which gets included
+ * from all helpers *.c sources.
+ */
+
+#ifndef SETUP_HEADER_INCLUDED
+ #define SETUP_HEADER_INCLUDED
+
+ // XWPEXPORT defines the standard linkage for the
+ // XWorkplace helpers.
+ #ifdef __EMX__
+ #define XWPENTRY
+ #elif defined (__IBMCPP__) || defined (__IBMC__)
+ #define XWPENTRY _Optlink
+ #endif
+
+ /*************************************************************
+ * *
+ * Additional stuff for EMX *
+ * *
+ *************************************************************/
+
+ #ifdef __EMX__
+ // EMX doesn't have all these 16-bit typedefs;
+ // added (99-10-22) [umoeller]
+ #define APIENTRY16 _Far16 _Pascal
+ #define PASCAL16 _Far16 _Pascal
+ #define CDECL16 _Far16 _Cdecl
+
+ typedef unsigned short APIRET16;
+ typedef unsigned long APIRET32;
+
+#if 0
+//YD do not use with gcc 3.3.5
+ #define _System
+ #define APIENTRY
+ // with VAC++, this defines _System linkage, which
+ // EMX doesn't have, or does it?!?
+#endif // 0
+
+ #endif
+
+ // the following is a VAC++-specific macro, which doesn't exist
+ // with EMX, so we need to implement this... this was one of
+ // the "undefined symbols" we got (99-10-23) [umoeller]
+ // changed this to prefix underscore, because the STL apparently
+ // redefines this V0.9.3 (2000-05-15) [umoeller]
+ #define _min(a,b) ( ((a) > (b)) ? b : a )
+ #define _max(a,b) ( ((a) > (b)) ? a : b )
+
+ // Uncomment the following if you have trouble with the
+ // exception handlers in helpers\except.c; WarpIN will
+ // then install _no_ additional exception handlers at all
+ // (include\helpers\except.h reacts to these defines).
+ // I'm not sure if the handlers work well with EMX.
+
+ #ifdef __EMX__00
+ #define __NO_EXCEPTION_HANDLERS__
+ #endif
+
+ /*************************************************************
+ * *
+ * Additional stuff for VAC++ 3.0 *
+ * *
+ *************************************************************/
+
+ // all this added V0.9.2 (2000-03-10) [umoeller]
+ #if ( defined ( __IBMCPP__ ) && ( __IBMCPP__ < 400 ) )
+ typedef int bool;
+ #define true 1
+ #define false 0
+ #define _BooleanConst // needed for some VAC headers, which define bool also
+ #endif
+
+ #ifndef __stdlib_h // <stdlib.h>
+ #include <stdlib.h>
+ #endif
+ #ifndef __string_h // <string.h>
+ #include <string.h>
+ #endif
+
+ /*************************************************************
+ * *
+ * Debugging *
+ * *
+ *************************************************************/
+
+ // All the following redone (99-10-23) [umoeller]:
+ // __DEBUG__ is defined as a macro on the compiler
+ // command line by the makefiles if DEBUG was enabled
+ // in \setup.in
+ #ifdef __DEBUG__
+
+ // with debug code, disable the exception handlers
+ #define __NO_EXCEPTION_HANDLERS__
+
+ // If the following is commented out, no PMPRINTF will be
+ // used at all. WarpIN uses Dennis Bareis' PMPRINTF
+ // package to do this.
+
+ // NOTE: We cannot use PmPrintf with EMX,
+ // because pmprintf.lib imports the VAC++ runtimes.
+ // That's the strange errors I was reporting yesterday.
+ #ifndef __EMX__
+ #ifdef OS2_INCLUDED
+ #define _PMPRINTF_
+ #include "helpers/pmprintf.h"
+ #endif
+ #endif
+ #endif
+
+ #ifndef _PMPRINTF_
+ // not defined: define empty macro so we don't
+ // get compiler errors
+ #define _Pmpf(x)
+ #endif
+
+#endif
+
diff --git a/sal/osl/os2/interlck.c b/sal/osl/os2/interlck.c
new file mode 100644
index 000000000000..589005f215b9
--- /dev/null
+++ b/sal/osl/os2/interlck.c
@@ -0,0 +1,51 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <386/builtin.h>
+
+#include "system.h"
+
+#include <osl/interlck.h>
+#include <osl/diagnose.h>
+
+/*****************************************************************************/
+/* osl_incrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
+{
+ return __atomic_increment_s32( pCount);
+}
+
+/*****************************************************************************/
+/* osl_decrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
+{
+ return __atomic_decrement_s32( pCount);
+}
+
+
diff --git a/sal/osl/os2/libutil.c b/sal/osl/os2/libutil.c
new file mode 100644
index 000000000000..e0f94a8b3235
--- /dev/null
+++ b/sal/osl/os2/libutil.c
@@ -0,0 +1,52 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if 0 // YD
+
+#include <windows.h>
+
+static BOOL g_bInit = FALSE;
+static DWORD g_dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
+
+DWORD GetPlatformId()
+{
+
+ if (!g_bInit)
+ {
+ OSVERSIONINFO aInfo;
+
+ aInfo.dwOSVersionInfoSize = sizeof(aInfo);
+ if (GetVersionEx(&aInfo))
+ g_dwPlatformId = aInfo.dwPlatformId;
+
+ g_bInit = TRUE;
+ }
+
+ return g_dwPlatformId;
+}
+
+#endif // 0
diff --git a/sal/osl/os2/makefile.mk b/sal/osl/os2/makefile.mk
new file mode 100644
index 000000000000..c9bfd3f96771
--- /dev/null
+++ b/sal/osl/os2/makefile.mk
@@ -0,0 +1,118 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=sal
+TARGET=cpposl
+USE_LDUMP2=TRUE
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=cont_pch
+PROJECTPCHSOURCE=cont_pch
+
+MULTITHREAD_OBJ=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# Uncomment the following line if you want to compile with -Wall
+# it disables lots of unnecessary warnings comming from the Win32
+# header files (disabling warnings via command line only works with
+# MSVC >= 7.x)
+#
+# CFLAGS+=/wd4668 /wd4711 /wd4201 /wd4710 /wd4619 /wd4514 /wd4820
+
+# --- Files --------------------------------------------------------
+
+.IF "$(header)" == ""
+
+SLOFILES= $(SLO)$/conditn.obj \
+ $(SLO)$/diagnose.obj \
+ $(SLO)$/dllentry.obj \
+ $(SLO)$/semaphor.obj \
+ $(SLO)$/interlck.obj \
+ $(SLO)$/nlsupport.obj\
+ $(SLO)$/mutex.obj \
+ $(SLO)$/module.obj \
+ $(SLO)$/process.obj \
+ $(SLO)$/time.obj \
+ $(SLO)$/signal.obj \
+ $(SLO)$/pipe.obj \
+ $(SLO)$/util.obj \
+ $(SLO)$/socket.obj \
+ $(SLO)$/thread.obj \
+ $(SLO)$/security.obj \
+ $(SLO)$/profile.obj \
+ $(SLO)$/tempfile.obj \
+ $(SLO)$/process_impl.obj\
+ $(SLO)$/uunxapi.obj\
+ $(SLO)$/file.obj \
+ $(SLO)$/file_url.obj \
+ $(SLO)$/file_error_transl.obj \
+ $(SLO)$/file_path_helper.obj \
+ $(SLO)$/debug.obj \
+ $(SLO)$/except.obj \
+ $(SLO)$/salinit.obj
+
+OBJFILES= $(OBJ)$/conditn.obj \
+ $(OBJ)$/diagnose.obj \
+ $(OBJ)$/libutil.obj \
+ $(OBJ)$/semaphor.obj \
+ $(OBJ)$/interlck.obj \
+ $(OBJ)$/nlsupport.obj\
+ $(OBJ)$/mutex.obj \
+ $(OBJ)$/module.obj \
+ $(OBJ)$/process.obj \
+ $(OBJ)$/time.obj \
+ $(OBJ)$/signal.obj \
+ $(OBJ)$/pipe.obj \
+ $(OBJ)$/util.obj \
+ $(OBJ)$/socket.obj \
+ $(OBJ)$/thread.obj \
+ $(OBJ)$/security.obj \
+ $(OBJ)$/profile.obj \
+ $(OBJ)$/tempfile.obj \
+ $(OBJ)$/process_impl.obj\
+ $(OBJ)$/uunxapi.obj\
+ $(OBJ)$/file.obj \
+ $(OBJ)$/file_url.obj \
+ $(OBJ)$/file_error_transl.obj \
+ $(OBJ)$/file_path_helper.obj \
+ $(OBJ)$/debug.obj \
+ $(OBJ)$/except.obj \
+ $(SLO)$/salinit.obj
+
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+
+
diff --git a/sal/osl/os2/module.c b/sal/osl/os2/module.c
new file mode 100644
index 000000000000..421b78195d83
--- /dev/null
+++ b/sal/osl/os2/module.c
@@ -0,0 +1,281 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/module.h>
+#include <osl/diagnose.h>
+#include <osl/file.h>
+#include <osl/thread.h>
+
+#include <stdlib.h>
+
+int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32);
+
+// static data for holding SAL dll module and full path
+static HMODULE hModSal;
+static char szSalDir[ _MAX_PATH];
+static char szSalDrive[ _MAX_PATH];
+
+/*****************************************************************************/
+/* osl_loadModule */
+/*****************************************************************************/
+
+ULONG APIENTRY _DosLoadModule (PSZ pszObject, ULONG uObjectLen, PCSZ pszModule,
+ PHMODULE phmod)
+{
+ APIRET rc;
+ rc = DosLoadModule( pszObject, uObjectLen, pszModule, phmod);
+ // YD 22/05/06 issue again if first call fails (why?)
+ if (rc == ERROR_INVALID_PARAMETER)
+ rc = DosLoadModule( pszObject, uObjectLen, pszModule, phmod);
+ return rc;
+}
+
+oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
+{
+ HMODULE hModule;
+ BYTE szErrorMessage[256];
+ APIRET rc;
+ oslModule pModule=0;
+ rtl_uString* ustrTmp = NULL;
+
+ OSL_ENSURE(ustrModuleName,"osl_loadModule : string is not valid");
+
+ /* ensure ustrTmp hold valid string */
+ if( osl_File_E_None != osl_getSystemPathFromFileURL( ustrModuleName, &ustrTmp ) )
+ rtl_uString_assign( &ustrTmp, ustrModuleName );
+
+ if( ustrTmp )
+ {
+ char buffer[PATH_MAX];
+
+ if( UnicodeToText( buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length ) )
+ {
+ char drive[_MAX_DRIVE], dir[_MAX_DIR];
+ char fname[_MAX_FNAME], ext[_MAX_EXT];
+ char* dot;
+ // 21/02/2006 YD dll names must be 8.3: since .uno.dll files
+ // have hardcoded names, I'm truncating names here and also in
+ // the build system
+ _splitpath (buffer, drive, dir, fname, ext);
+ if (strlen(fname)>8)
+ fname[8] = 0; // truncate to 8.3
+ dot = strchr( fname, '.');
+ if (dot)
+ *dot = '\0'; // truncate on dot
+ // if drive is not specified, remove starting \ from dir name
+ // so dll is loaded from LIBPATH
+ if (drive[0] == 0 && dir[0] == '\\' && dir[1] == '\\') {
+ while( dir[0] == '\\')
+ strcpy( dir, dir+1);
+ }
+ _makepath( buffer, drive, dir, fname, ext);
+
+ rc = _DosLoadModule( szErrorMessage, sizeof( szErrorMessage), (PCSZ)buffer, &hModule);
+ if (rc == NO_ERROR )
+ pModule = (oslModule)hModule;
+ else
+ {
+ if (rc == NO_ERROR )
+ pModule = (oslModule)hModule;
+ else
+ {
+ sal_Char szError[ PATH_MAX*2 ];
+ sprintf( szError, "Module: %s; rc: %d;\nReason: %s;\n"
+ "Please contact technical support and report above informations.\n\n",
+ buffer, rc, szErrorMessage );
+#if OSL_DEBUG_LEVEL>0
+ fprintf( stderr, szError);
+#endif
+ //OSL_TRACE(szError);
+#ifndef OSL_DEBUG_LEVEL
+ WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,
+ szError, "Critical error: DosLoadModule failed",
+ 0, MB_ERROR | MB_OK | MB_MOVEABLE);
+#endif
+ }
+ }
+ }
+ }
+
+ rtl_uString_release( ustrTmp );
+
+ return pModule;
+}
+
+/*****************************************************************************/
+/* osl_getModuleHandle */
+/*****************************************************************************/
+
+sal_Bool SAL_CALL
+osl_getModuleHandle(rtl_uString *pModuleName, oslModule *pResult)
+{
+ HMODULE hmod;
+ APIRET rc;
+ rc = DosQueryModuleHandle(pModuleName->buffer, &hmod);
+ if( rc == NO_ERROR)
+ {
+ *pResult = (oslModule) hmod;
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_unloadModule */
+/*****************************************************************************/
+void SAL_CALL osl_unloadModule(oslModule Module)
+{
+#if OSL_DEBUG_LEVEL>0
+ if (!Module)
+ fprintf( stderr, "osl_unloadModule NULL HANDLE.\n");
+#endif
+
+ DosFreeModule((HMODULE)Module);
+}
+
+/*****************************************************************************/
+/* osl_getSymbol */
+/*****************************************************************************/
+void* SAL_CALL
+osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
+{
+ return (void *) osl_getFunctionSymbol(Module, pSymbolName);
+}
+
+/*****************************************************************************/
+/* osl_getFunctionSymbol */
+/*****************************************************************************/
+oslGenericFunction SAL_CALL osl_getFunctionSymbol( oslModule Module, rtl_uString *strSymbolName )
+{
+ rtl_String *symbolName = NULL;
+ oslGenericFunction address;
+
+ OSL_ASSERT(Module);
+ OSL_ASSERT(strSymbolName);
+
+ rtl_uString2String(
+ &symbolName,
+ strSymbolName->buffer,
+ strSymbolName->length,
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS
+ );
+
+ address=osl_getAsciiFunctionSymbol(Module, rtl_string_getStr(symbolName));
+ rtl_string_release(symbolName);
+
+ return address;
+}
+
+/*****************************************************************************/
+/* osl_getAsciiFunctionSymbol */
+/*****************************************************************************/
+oslGenericFunction SAL_CALL
+osl_getAsciiFunctionSymbol( oslModule Module, const sal_Char *pSymbol )
+{
+ PFN pFunction;
+ APIRET rc;
+ void* pHandle=0;
+
+ OSL_ENSURE(Module,"osl_getSymbol : module handle is not valid");
+ OSL_ENSURE(Module,"osl_getSymbol : ustrSymbolName");
+
+ if ( Module!= 0 && pSymbol != 0 )
+ {
+
+ rc = DosQueryProcAddr( (HMODULE) Module, 0, (PCSZ)pSymbol, &pFunction );
+ if( rc == NO_ERROR )
+ {
+ pHandle = (void*)pFunction;
+ }
+ else
+ {
+ // YD try again adding the '_' prefix
+ char _pszSymbolName[255];
+ strcpy( _pszSymbolName, "_");
+ strcat( _pszSymbolName, pSymbol);
+ rc = DosQueryProcAddr( (HMODULE) Module, 0, (PCSZ)_pszSymbolName, &pFunction );
+ if( rc == NO_ERROR )
+ pHandle = (void*)pFunction;
+ }
+
+ }
+
+ return pHandle;
+}
+
+/*****************************************************************************/
+/* osl_getModuleURLFromAddress */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
+{
+ //APIRET APIENTRY DosQueryModFromEIP (HMODULE *phMod, ULONG *pObjNum,
+ // ULONG BuffLen, PCHAR pBuff, ULONG *pOffset, ULONG Address)
+ HMODULE hMod;
+ ULONG ObjNum;
+ CHAR Buff[2*_MAX_PATH];
+ ULONG Offset;
+ APIRET rc;
+
+ // get module handle (and name)
+ rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff, &Offset, (ULONG)addr);
+ if (rc)
+ return sal_False;
+
+ // get module full path
+ rc = DosQueryModuleName( hMod, sizeof( Buff), Buff);
+ if (rc)
+ return sal_False;
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_TRACE("module.c::osl_getModuleURLFromAddress - %s\n", Buff);
+#endif
+
+ // convert to URL
+ rtl_uString *ustrSysPath = NULL;
+ rtl_string2UString( &ustrSysPath, Buff, strlen(Buff), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(ustrSysPath != NULL);
+ osl_getFileURLFromSystemPath( ustrSysPath, ppLibraryUrl );
+ rtl_uString_release( ustrSysPath );
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_getModuleURLFromFunctionAddress */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress( oslGenericFunction addr, rtl_uString ** ppLibraryUrl )
+{
+ return osl_getModuleURLFromAddress( ( void * )addr, ppLibraryUrl );
+}
+
+/*****************************************************************************/
+
diff --git a/sal/osl/os2/mutex.c b/sal/osl/os2/mutex.c
new file mode 100644
index 000000000000..e86b3f965608
--- /dev/null
+++ b/sal/osl/os2/mutex.c
@@ -0,0 +1,167 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <sys/fmutex.h>
+
+#include "system.h"
+
+#include <osl/mutex.h>
+#include <osl/diagnose.h>
+
+/*
+ Implementation notes:
+ The void* hidden by oslMutex points to an OS/2 mutex semaphore.
+*/
+typedef struct _oslMutexImpl {
+ HMTX m_Mutex;
+ int m_Locks;
+ ULONG m_Owner;
+ ULONG m_Requests;
+} oslMutexImpl;
+
+// static mutex to control access to private members of oslMutexImpl
+static HMTX MutexLock = 0;
+
+/*****************************************************************************/
+/* osl_createMutex */
+/*****************************************************************************/
+oslMutex SAL_CALL osl_createMutex()
+{
+ oslMutexImpl *pMutexImpl;
+ HMTX hMutex;
+ APIRET rc;
+
+ pMutexImpl= (oslMutexImpl*)calloc(sizeof(oslMutexImpl), 1);
+ OSL_ASSERT(pMutexImpl); /* alloc successful? */
+
+ /* create semaphore */
+ rc = DosCreateMutexSem( NULL, &pMutexImpl->m_Mutex, 0, FALSE );
+ if( rc != 0 )
+ {
+ free(pMutexImpl);
+ return NULL;
+ }
+
+ // create static mutex for private members
+ if (MutexLock == 0)
+ DosCreateMutexSem( NULL, &MutexLock, 0, FALSE );
+
+ return (oslMutex)pMutexImpl;
+}
+
+/*****************************************************************************/
+/* osl_destroyMutex */
+/*****************************************************************************/
+void SAL_CALL osl_destroyMutex(oslMutex Mutex)
+{
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+ if (pMutexImpl)
+ {
+ DosCloseMutexSem( pMutexImpl->m_Mutex);
+ free(pMutexImpl);
+ }
+}
+
+/*****************************************************************************/
+/* osl_acquireMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_acquireMutex(oslMutex Mutex)
+{
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+ APIRET rc = 0;
+ OSL_ASSERT(Mutex);
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+ pMutexImpl->m_Requests++;
+ DosReleaseMutexSem( MutexLock);
+
+ rc = DosRequestMutexSem( pMutexImpl->m_Mutex, SEM_INDEFINITE_WAIT );
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+ pMutexImpl->m_Requests--;
+ if (pMutexImpl->m_Locks++ == 0)
+ pMutexImpl->m_Owner = _gettid();
+ DosReleaseMutexSem( MutexLock);
+
+ return( rc == 0 );
+}
+
+/*****************************************************************************/
+/* osl_tryToAcquireMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_tryToAcquireMutex(oslMutex Mutex)
+{
+ sal_Bool ret = sal_False;
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+ OSL_ASSERT(Mutex);
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+
+ if ( ((pMutexImpl->m_Requests == 0) && (pMutexImpl->m_Locks == 0)) ||
+ (pMutexImpl->m_Owner == _gettid()) )
+ ret = osl_acquireMutex(Mutex);
+
+ DosReleaseMutexSem( MutexLock);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* osl_releaseMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_releaseMutex(oslMutex Mutex)
+{
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+ APIRET rc;
+ OSL_ASSERT(Mutex);
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+
+ if (--(pMutexImpl->m_Locks) == 0)
+ pMutexImpl->m_Owner = 0;
+
+ DosReleaseMutexSem( MutexLock);
+
+ rc = DosReleaseMutexSem( pMutexImpl->m_Mutex);
+
+ return sal_True;
+}
+
+
+
+/*****************************************************************************/
+/* osl_getGlobalMutex */
+/*****************************************************************************/
+
+oslMutex g_Mutex = NULL;
+
+oslMutex * SAL_CALL osl_getGlobalMutex(void)
+{
+ if (g_Mutex == NULL)
+ g_Mutex = osl_createMutex();
+ return &g_Mutex;
+}
diff --git a/sal/osl/os2/nlsupport.c b/sal/osl/os2/nlsupport.c
new file mode 100644
index 000000000000..ab00443e57d7
--- /dev/null
+++ b/sal/osl/os2/nlsupport.c
@@ -0,0 +1,445 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define INCL_WIN
+#include "svpm.h"
+
+#include <osl/nlsupport.h>
+#include <osl/diagnose.h>
+#include <osl/process.h>
+#include <rtl/memory.h>
+
+#include <string.h>
+
+/*****************************************************************************
+ typedefs
+ *****************************************************************************/
+
+
+typedef struct {
+ const char *key;
+ const rtl_TextEncoding value;
+} _pair;
+
+
+/*****************************************************************************
+ compare function for binary search
+ *****************************************************************************/
+
+static int
+_pair_compare (const char *key, const _pair *pair)
+{
+ int result = rtl_str_compareIgnoreAsciiCase( key, pair->key );
+ return result;
+}
+
+/*****************************************************************************
+ binary search on encoding tables
+ *****************************************************************************/
+
+static const _pair*
+_pair_search (const char *key, const _pair *base, unsigned int member )
+{
+ unsigned int lower = 0;
+ unsigned int upper = member;
+ unsigned int current;
+ int comparison;
+
+ /* check for validity of input */
+ if ( (key == NULL) || (base == NULL) || (member == 0) )
+ return NULL;
+
+ /* binary search */
+ while ( lower < upper )
+ {
+ current = (lower + upper) / 2;
+ comparison = _pair_compare( key, base + current );
+ if (comparison < 0)
+ upper = current;
+ else if (comparison > 0)
+ lower = current + 1;
+ else
+ return base + current;
+ }
+
+ return NULL;
+}
+
+
+/*****************************************************************************
+ convert rtl_Locale to locale string
+ *****************************************************************************/
+
+static char * _compose_locale( rtl_Locale * pLocale, char * buffer, size_t n )
+{
+ /* check if a valid locale is specified */
+ if( pLocale && pLocale->Language && (pLocale->Language->length == 2) )
+ {
+ size_t offset = 0;
+
+ /* convert language code to ascii */
+ {
+ rtl_String *pLanguage = NULL;
+
+ rtl_uString2String( &pLanguage,
+ pLocale->Language->buffer, pLocale->Language->length,
+ RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ if( pLanguage->length < n )
+ {
+ strcpy( buffer, pLanguage->buffer );
+ offset = pLanguage->length;
+ }
+
+ rtl_string_release( pLanguage );
+ }
+
+ /* convert country code to ascii */
+ if( pLocale->Country && (pLocale->Country->length == 2) )
+ {
+ rtl_String *pCountry = NULL;
+
+ rtl_uString2String( &pCountry,
+ pLocale->Country->buffer, pLocale->Country->length,
+ RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ if( offset + pCountry->length + 1 < n )
+ {
+ strcpy( buffer + offset++, "_" );
+ strcpy( buffer + offset, pCountry->buffer );
+ offset += pCountry->length;
+ }
+
+ rtl_string_release( pCountry );
+ }
+
+ /* convert variant to ascii - check if there is enough space for the variant string */
+ if( pLocale->Variant && pLocale->Variant->length &&
+ ( pLocale->Variant->length < n - 6 ) )
+ {
+ rtl_String *pVariant = NULL;
+
+ rtl_uString2String( &pVariant,
+ pLocale->Variant->buffer, pLocale->Variant->length,
+ RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ if( offset + pVariant->length + 1 < n )
+ {
+ strcpy( buffer + offset, pVariant->buffer );
+ offset += pVariant->length;
+ }
+
+ rtl_string_release( pVariant );
+ }
+
+ return buffer;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************
+ convert locale string to rtl_Locale
+ *****************************************************************************/
+
+static rtl_Locale * _parse_locale( const char * locale )
+{
+ static sal_Unicode c_locale[2] = { (sal_Unicode) 'C', 0 };
+
+ /* check if locale contains a valid string */
+ if( locale )
+ {
+ size_t len = strlen( locale );
+
+ if( len >= 2 )
+ {
+ rtl_uString * pLanguage = NULL;
+ rtl_uString * pCountry = NULL;
+ rtl_uString * pVariant = NULL;
+
+ size_t offset = 2;
+
+ /* convert language code to unicode */
+ rtl_string2UString( &pLanguage, locale, 2, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(pLanguage != NULL);
+
+ /* convert country code to unicode */
+ if( len >= 5 && '_' == locale[2] )
+ {
+ rtl_string2UString( &pCountry, locale + 3, 2, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(pCountry != NULL);
+ offset = 5;
+ }
+
+ /* convert variant code to unicode - do not rely on "." as delimiter */
+ if( len > offset ) {
+ rtl_string2UString( &pVariant, locale + offset, len - offset, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(pVariant != NULL);
+ }
+
+ rtl_Locale * ret = rtl_locale_register( pLanguage->buffer, pCountry ? pCountry->buffer : c_locale + 1, pVariant ? pVariant->buffer : c_locale + 1 );
+
+ if (pVariant) rtl_uString_release(pVariant);
+ if (pCountry) rtl_uString_release(pCountry);
+ if (pLanguage) rtl_uString_release(pLanguage);
+
+ return ret;
+ }
+ else
+ return rtl_locale_register( c_locale, c_locale + 1, c_locale + 1 );
+ }
+
+ return NULL;
+}
+
+/*
+ * This implementation of osl_getTextEncodingFromLocale maps
+ * from the ISO language codes.
+ */
+
+const _pair _full_locale_list[] = {
+ { "ja_JP.eucJP", RTL_TEXTENCODING_EUC_JP },
+ { "ja_JP.EUC", RTL_TEXTENCODING_EUC_JP },
+ { "ko_KR.EUC", RTL_TEXTENCODING_EUC_KR },
+ { "zh_CN.EUC", RTL_TEXTENCODING_EUC_CN },
+ { "zh_TW.EUC", RTL_TEXTENCODING_EUC_TW }
+};
+
+const _pair _locale_extension_list[] = {
+ { "big5", RTL_TEXTENCODING_BIG5 },
+ { "big5hk", RTL_TEXTENCODING_BIG5_HKSCS },
+ { "gb18030", RTL_TEXTENCODING_GB_18030 },
+ { "euc", RTL_TEXTENCODING_EUC_JP },
+ { "iso8859-1", RTL_TEXTENCODING_ISO_8859_1 },
+ { "iso8859-10", RTL_TEXTENCODING_ISO_8859_10 },
+ { "iso8859-13", RTL_TEXTENCODING_ISO_8859_13 },
+ { "iso8859-14", RTL_TEXTENCODING_ISO_8859_14 },
+ { "iso8859-15", RTL_TEXTENCODING_ISO_8859_15 },
+ { "iso8859-2", RTL_TEXTENCODING_ISO_8859_2 },
+ { "iso8859-3", RTL_TEXTENCODING_ISO_8859_3 },
+ { "iso8859-4", RTL_TEXTENCODING_ISO_8859_4 },
+ { "iso8859-5", RTL_TEXTENCODING_ISO_8859_5 },
+ { "iso8859-6", RTL_TEXTENCODING_ISO_8859_6 },
+ { "iso8859-7", RTL_TEXTENCODING_ISO_8859_7 },
+ { "iso8859-8", RTL_TEXTENCODING_ISO_8859_8 },
+ { "iso8859-9", RTL_TEXTENCODING_ISO_8859_9 },
+ { "koi8-r", RTL_TEXTENCODING_KOI8_R },
+ { "koi8-u", RTL_TEXTENCODING_KOI8_U },
+ { "pck", RTL_TEXTENCODING_MS_932 },
+#if (0)
+ { "sun_eu_greek", RTL_TEXTENCODING_DONTKNOW },
+#endif
+ { "utf-16", RTL_TEXTENCODING_UNICODE },
+ { "utf-7", RTL_TEXTENCODING_UTF7 },
+ { "utf-8", RTL_TEXTENCODING_UTF8 }
+};
+
+const _pair _iso_language_list[] = {
+ { "af", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ar", RTL_TEXTENCODING_ISO_8859_6 },
+ { "az", RTL_TEXTENCODING_ISO_8859_9 },
+ { "be", RTL_TEXTENCODING_ISO_8859_5 },
+ { "bg", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ca", RTL_TEXTENCODING_ISO_8859_1 },
+ { "cs", RTL_TEXTENCODING_ISO_8859_2 },
+ { "da", RTL_TEXTENCODING_ISO_8859_1 },
+ { "de", RTL_TEXTENCODING_ISO_8859_1 },
+ { "el", RTL_TEXTENCODING_ISO_8859_7 },
+ { "en", RTL_TEXTENCODING_ISO_8859_1 },
+ { "es", RTL_TEXTENCODING_ISO_8859_1 },
+ { "et", RTL_TEXTENCODING_ISO_8859_4 },
+ { "eu", RTL_TEXTENCODING_ISO_8859_1 },
+ { "fa", RTL_TEXTENCODING_ISO_8859_6 },
+ { "fi", RTL_TEXTENCODING_ISO_8859_1 },
+ { "fo", RTL_TEXTENCODING_ISO_8859_1 },
+ { "fr", RTL_TEXTENCODING_ISO_8859_1 },
+ { "gr", RTL_TEXTENCODING_ISO_8859_7 },
+ { "he", RTL_TEXTENCODING_ISO_8859_8 },
+ { "hi", RTL_TEXTENCODING_DONTKNOW },
+ { "hr", RTL_TEXTENCODING_ISO_8859_2 },
+ { "hu", RTL_TEXTENCODING_ISO_8859_2 },
+ { "hy", RTL_TEXTENCODING_DONTKNOW },
+ { "id", RTL_TEXTENCODING_ISO_8859_1 },
+ { "is", RTL_TEXTENCODING_ISO_8859_1 },
+ { "it", RTL_TEXTENCODING_ISO_8859_1 },
+ { "iw", RTL_TEXTENCODING_ISO_8859_8 },
+ { "ja", RTL_TEXTENCODING_EUC_JP },
+ { "ka", RTL_TEXTENCODING_DONTKNOW },
+ { "kk", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ko", RTL_TEXTENCODING_EUC_KR },
+ { "lt", RTL_TEXTENCODING_ISO_8859_4 },
+ { "lv", RTL_TEXTENCODING_ISO_8859_4 },
+ { "mk", RTL_TEXTENCODING_ISO_8859_5 },
+ { "mr", RTL_TEXTENCODING_DONTKNOW },
+ { "ms", RTL_TEXTENCODING_ISO_8859_1 },
+ { "nl", RTL_TEXTENCODING_ISO_8859_1 },
+ { "no", RTL_TEXTENCODING_ISO_8859_1 },
+ { "pl", RTL_TEXTENCODING_ISO_8859_2 },
+ { "pt", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ro", RTL_TEXTENCODING_ISO_8859_2 },
+ { "ru", RTL_TEXTENCODING_ISO_8859_5 },
+ { "sa", RTL_TEXTENCODING_DONTKNOW },
+ { "sk", RTL_TEXTENCODING_ISO_8859_2 },
+ { "sl", RTL_TEXTENCODING_ISO_8859_2 },
+ { "sq", RTL_TEXTENCODING_ISO_8859_2 },
+ { "sv", RTL_TEXTENCODING_ISO_8859_1 },
+ { "sw", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ta", RTL_TEXTENCODING_DONTKNOW },
+ { "th", RTL_TEXTENCODING_DONTKNOW },
+ { "tr", RTL_TEXTENCODING_ISO_8859_9 },
+ { "tt", RTL_TEXTENCODING_ISO_8859_5 },
+ { "uk", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ur", RTL_TEXTENCODING_ISO_8859_6 },
+ { "uz", RTL_TEXTENCODING_ISO_8859_9 },
+ { "vi", RTL_TEXTENCODING_DONTKNOW },
+ { "zh", RTL_TEXTENCODING_BIG5 }
+};
+
+/*****************************************************************************
+ return the text encoding corresponding to the given locale
+ *****************************************************************************/
+
+rtl_TextEncoding osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
+{
+ const _pair *language = 0;
+ char locale_buf[64] = "";
+ char *cp;
+
+ WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,
+ "Please contact technical support and report above informations.\n\n",
+ "Critical error: osl_getTextEncodingFromLocale",
+ 0, MB_ERROR | MB_OK | MB_MOVEABLE);
+
+ /* default to process locale if pLocale == NULL */
+ if( NULL == pLocale )
+ osl_getProcessLocale( &pLocale );
+
+ /* convert rtl_Locale to locale string */
+ if( _compose_locale( pLocale, locale_buf, 64 ) )
+ {
+ /* check special handling list (EUC) first */
+ const unsigned int members = sizeof( _full_locale_list ) / sizeof( _pair );
+ language = _pair_search( locale_buf, _full_locale_list, members);
+
+ if( NULL == language )
+ {
+ /*
+ * check if there is a charset qualifier at the end of the given locale string
+ * e.g. de.ISO8859-15 or de.ISO8859-15@euro which strongly indicates what
+ * charset to use
+ */
+ cp = strrchr( locale_buf, '.' );
+
+ if( NULL != cp )
+ {
+ const unsigned int members = sizeof( _locale_extension_list ) / sizeof( _pair );
+ language = _pair_search( cp + 1, _locale_extension_list, members);
+ }
+ }
+
+ /* use iso language code to determine the charset */
+ if( NULL == language )
+ {
+ const unsigned int members = sizeof( _iso_language_list ) / sizeof( _pair );
+
+ /* iso lang codes have 2 charaters */
+ locale_buf[2] = '\0';
+
+ language = _pair_search( locale_buf, _iso_language_list, members);
+ }
+ }
+
+ /* a matching item in our list provides a mapping from codeset to
+ * rtl-codeset */
+ if ( language != NULL )
+ return language->value;
+
+ return RTL_TEXTENCODING_DONTKNOW;
+}
+
+/*****************************************************************************
+ return the current process locale
+ *****************************************************************************/
+
+void _imp_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ /* simulate behavior off setlocale */
+ char * locale = getenv( "LC_ALL" );
+
+ if( NULL == locale )
+ locale = getenv( "LC_CTYPE" );
+
+ if( NULL == locale )
+ locale = getenv( "LANG" );
+
+ if( NULL == locale )
+ locale = "C";
+
+ *ppLocale = _parse_locale( locale );
+}
+
+/*****************************************************************************
+ set the current process locale
+ *****************************************************************************/
+
+int _imp_setProcessLocale( rtl_Locale * pLocale )
+{
+ char locale_buf[64];
+
+ /* convert rtl_Locale to locale string */
+ if( NULL != _compose_locale( pLocale, locale_buf, 64 ) )
+ {
+ /* only change env vars that exist already */
+ if( getenv( "LC_ALL" ) ) {
+#if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX ) || defined( __EMX__ )
+ setenv( "LC_ALL", locale_buf, 1);
+#else
+ setenv( "LC_ALL", locale_buf );
+#endif
+ }
+
+ if( getenv( "LC_CTYPE" ) ) {
+#if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX ) || defined( __EMX__ )
+ setenv("LC_CTYPE", locale_buf, 1 );
+#else
+ setenv( "LC_CTYPE", locale_buf );
+#endif
+ }
+
+ if( getenv( "LANG" ) ) {
+#if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX ) || defined( __EMX__ )
+ setenv("LC_CTYPE", locale_buf, 1 );
+#else
+ setenv( "LANG", locale_buf );
+#endif
+ }
+ }
+
+ return 0;
+}
+
+
diff --git a/sal/osl/os2/path_helper.cxx b/sal/osl/os2/path_helper.cxx
new file mode 100644
index 000000000000..6425927a0021
--- /dev/null
+++ b/sal/osl/os2/path_helper.cxx
@@ -0,0 +1,116 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*******************************************************************
+ Includes
+ ******************************************************************/
+
+#include "path_helper.hxx"
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+
+#include <algorithm>
+#include <wchar.h>
+#include <wctype.h>
+
+/*******************************************************************
+ Constants
+ ******************************************************************/
+
+const rtl::OUString BACKSLASH = rtl::OUString::createFromAscii("\\");
+const rtl::OUString SLASH = rtl::OUString::createFromAscii("/");
+
+/*******************************************************************
+ osl_systemPathEnsureSeparator
+ ******************************************************************/
+
+void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath)
+{
+ OSL_PRECOND(ppustrPath && (NULL != *ppustrPath), \
+ "osl_systemPathEnsureSeparator: Invalid parameter");
+
+ rtl::OUString path(*ppustrPath);
+ sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH));
+
+ if (i < (path.getLength()-1))
+ {
+ path += BACKSLASH;
+ rtl_uString_assign(ppustrPath, path.pData);
+ }
+
+ OSL_POSTCOND(path.lastIndexOf(BACKSLASH) == (path.getLength() - 1), \
+ "osl_systemPathEnsureSeparator: Post condition failed");
+}
+
+/*******************************************************************
+ osl_systemPathRemoveSeparator
+ ******************************************************************/
+
+void SAL_CALL osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath)
+{
+ rtl::OUString path(*ppustrPath);
+
+ if (!osl::systemPathIsLogicalDrivePattern(path))
+ {
+ sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH));
+
+ if (i > -1 && (i == (path.getLength() - 1)))
+ {
+ path = rtl::OUString(path.getStr(), path.getLength() - 1);
+ rtl_uString_assign(ppustrPath, path.pData);
+ }
+ }
+}
+
+/*******************************************************************
+ osl_is_logical_drive_pattern
+ ******************************************************************/
+
+// is [A-Za-z]:[/|\]\0
+const sal_Unicode* LDP = L":";
+const sal_Unicode* LDP_WITH_BACKSLASH = L":\\";
+const sal_Unicode* LDP_WITH_SLASH = L":/";
+
+// degenerated case returned by the Windows FileOpen dialog
+// when someone enters for instance "x:filename", the Win32
+// API accepts this case
+const sal_Unicode* LDP_WITH_DOT_BACKSLASH = L":.\\";
+
+sal_Int32 osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath)
+{
+ const sal_Unicode* p = rtl_uString_getStr(const_cast<rtl_uString*>(pustrPath));
+ if (iswalpha(*p++))
+ {
+ return ((0 == wcscmp(p, LDP)) ||
+ (0 == wcscmp(p, LDP_WITH_BACKSLASH)) ||
+ (0 == wcscmp(p, LDP_WITH_SLASH)) ||
+ (0 == wcscmp(p, LDP_WITH_DOT_BACKSLASH)));
+ }
+ return 0;
+}
+
+
diff --git a/sal/osl/os2/path_helper.h b/sal/osl/os2/path_helper.h
new file mode 100644
index 000000000000..79341f538667
--- /dev/null
+++ b/sal/osl/os2/path_helper.h
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _PATH_HELPER_H_
+#define _PATH_HELPER_H_
+
+#include <sal/types.h>
+#include <rtl/ustring.h>
+#include <osl/file.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************
+ osl_systemPathEnsureSeparator
+ Adds a trailing path separator to the given system path if not
+ already there and if the path is not the root path or a logical
+ drive alone
+ ******************************************************************/
+
+void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath);
+
+/*******************************************************************
+ osl_systemPathRemoveSeparator
+ Removes the last separator from the given system path if any and
+ if the path is not the root path '\'
+ ******************************************************************/
+
+void SAL_CALL osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath);
+
+/*******************************************************************
+ osl_is_logical_drive_pattern
+ Returns whether a given path is only a logical drive pattern or not.
+ A logical drive pattern is something like "a:\", "c:\".
+ No logical drive pattern is something like "c:\test"
+ ******************************************************************/
+
+sal_Int32 osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sal/osl/os2/path_helper.hxx b/sal/osl/os2/path_helper.hxx
new file mode 100644
index 000000000000..8a301431f610
--- /dev/null
+++ b/sal/osl/os2/path_helper.hxx
@@ -0,0 +1,73 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// YD #pragma warning (disable : 4800)
+
+#ifndef _PATH_HELPER_HXX_
+#define _PATH_HELPER_HXX_
+
+#include "path_helper.h"
+#include <rtl/ustring.hxx>
+
+namespace osl
+{
+
+/*******************************************************************
+ osl_systemPathEnsureSeparator
+ Adds a trailing path separator to the given system path if not
+ already there and if the path is not the root path or a logical
+ drive alone
+ ******************************************************************/
+
+inline void systemPathEnsureSeparator(/*inout*/ rtl::OUString& Path)
+{
+ osl_systemPathEnsureSeparator(&Path.pData);
+}
+
+/*******************************************************************
+ osl_systemPathRemoveSeparator
+ Removes the last separator from the given system path if any and
+ if the path is not the root path '\'
+ ******************************************************************/
+
+inline void systemPathRemoveSeparator(/*inout*/ rtl::OUString& Path)
+{
+ osl_systemPathRemoveSeparator(&Path.pData);
+}
+
+/*******************************************************************
+ osl_systemPathIsLogicalDrivePattern
+ ******************************************************************/
+
+inline bool systemPathIsLogicalDrivePattern(/*in*/ const rtl::OUString& path)
+{
+ return osl_systemPathIsLogicalDrivePattern(path.pData);
+}
+
+} // end namespace osl
+
+#endif
diff --git a/sal/osl/os2/pipe.cxx b/sal/osl/os2/pipe.cxx
new file mode 100644
index 000000000000..20db94bda9eb
--- /dev/null
+++ b/sal/osl/os2/pipe.cxx
@@ -0,0 +1,555 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+//#define INCL_DOSERRORS
+#include "system.h"
+
+#include <osl/pipe.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/mutex.h>
+#include <osl/semaphor.h>
+#include <osl/conditn.h>
+#include <osl/interlck.h>
+#include <osl/process.h>
+#include <rtl/ustring.hxx>
+
+#define PIPENAMEMASK "OSL_PIPE_%s"
+#define SECPIPENAMEMASK "OSL_PIPE_%s_%s"
+
+typedef enum {
+ MSG_SYN,
+ MSG_FIN,
+ MSG_DATA,
+ MSG_UNKNOWN
+} MessageType;
+
+struct oslPipeImpl {
+ oslInterlockedCount m_Reference;
+ HPIPE hPipe;
+ HMTX m_NamedObject;
+ APIRET nLastError;
+ //oslSecurity m_Security;
+ sal_Bool m_bClosed;
+};
+
+/* default size for input/output buffer */
+static const ULONG ulBufSize = 4096;
+
+/* OS/2 path for pipes */
+static const CHAR pszPipePath[] = "\\PIPE\\";
+static const UCHAR nPipePathLen = sizeof (pszPipePath) - 1;
+
+/* global last error value to be returned from oslGetLastPipeError */
+static APIRET ngLastError;
+
+using rtl::OString;
+using rtl::OUString;
+using rtl::OUStringToOString;
+
+/*****************************************************************************/
+/* osl_create/destroy-PipeImpl */
+/*****************************************************************************/
+
+static oslInterlockedCount nPipes = 0;
+
+oslPipe __osl_createPipeImpl(void)
+{
+ oslPipe pPipe;
+
+ pPipe = (oslPipe) calloc(1,sizeof(struct oslPipeImpl));
+
+ pPipe->m_bClosed = sal_False;
+ pPipe->m_Reference = 1;
+ pPipe->hPipe = NULL;
+ pPipe->m_NamedObject = NULL;
+
+ return pPipe;
+}
+
+void __osl_destroyPipeImpl(oslPipe pPipe)
+{
+ if (pPipe != NULL)
+ {
+ DosCloseMutexSem( pPipe->m_NamedObject);
+ free(pPipe);
+ }
+}
+
+
+/*****************************************************************************/
+/* osl_createPipe */
+/*****************************************************************************/
+oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options,
+ oslSecurity Security)
+{
+ oslPipe pPipe;
+
+ ULONG ulAction;
+ CHAR strPipeNameBuffer [CCHMAXPATHCOMP];
+ rtl_String* strPipeName=0;
+ sal_Char* pszPipeName=0;
+
+ /* check parameters */
+ OSL_ASSERT( ustrPipeName );
+ //YD 17/04/06 OSL_ASSERT( Security == 0 );
+
+ /* allocate impl-structure */
+ pPipe = __osl_createPipeImpl();
+ if (!pPipe)
+ {
+ OSL_TRACE( "osl_createPipe failed allocating memory.\n" );
+ return NULL;
+ }
+
+ /* create pipe name */
+ OString sPipe = OUStringToOString(ustrPipeName, RTL_TEXTENCODING_ASCII_US);
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("osl_createPipe options 0x%x\n", Options);
+#endif
+
+ switch( Options )
+ {
+ case osl_Pipe_OPEN:
+ {
+ APIRET fPipeAvailable;
+
+ sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr());
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("osl_createPipe %s\n", strPipeNameBuffer);
+#endif
+ ngLastError = DosOpen( (PCSZ)strPipeNameBuffer,
+ &(pPipe->hPipe), &ulAction,
+ 0, FILE_NORMAL, FILE_OPEN,
+ OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
+ (PEAOP2) NULL);
+ // if pipe is busy, wait for it
+ if (ngLastError == ERROR_PIPE_BUSY)
+ do
+ {
+ /* free instance should be available first */
+ fPipeAvailable = DosWaitNPipe( (PCSZ)strPipeNameBuffer, -1);
+ /* first try to open system pipe */
+ if ( fPipeAvailable == NO_ERROR )
+ {
+ // We got it !
+ ngLastError = NO_ERROR;
+ break;
+ }
+ // Pipe instance maybe catched by another client -> try again
+ printf("osl_createPipe wait for Pipe available\n");
+ } while ( fPipeAvailable );
+ }
+ break;
+ case osl_Pipe_CREATE:
+ {
+ sprintf (strPipeNameBuffer, "\\SEM32\\OSL_SEM_%s", sPipe.getStr());
+ // check if semaphore exists (pipe create must fail for existig pipes)
+ ngLastError = DosCreateMutexSem( (PCSZ)strPipeNameBuffer, &(pPipe->m_NamedObject), 0, TRUE );
+ if (ngLastError)
+ break;
+
+ sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr());
+#if OSL_DEBUG_LEVEL>0
+ debug_printf("osl_createPipe %s\n", strPipeNameBuffer);
+#endif
+ ngLastError = DosCreateNPipe( (PCSZ)strPipeNameBuffer,
+ &(pPipe->hPipe),
+ NP_ACCESS_DUPLEX, /* open pipe for read and write access */
+ 0xFF, /* allow unlimited number of instances */
+ ulBufSize, /* output buffer size */
+ ulBufSize, /* input buffer size */
+ 0L /* use default time-out time */
+ );
+ }
+ break;
+ default:
+ ngLastError = ERROR_INVALID_PARAMETER;
+ }
+
+ /* if failed, release allocated memory */
+ if (ngLastError)
+ {
+ OSL_TRACE( "osl_createPipe failed %s the pipe %s, Error Code %d.\n",
+ Options == osl_Pipe_OPEN ? "opening" : "creating",
+ strPipeNameBuffer,
+ ngLastError );
+ __osl_destroyPipeImpl(pPipe);
+ return NULL;
+ }
+
+ pPipe->m_Reference= 1;
+ pPipe->m_bClosed = sal_False;
+ //pPipe->m_Security = Security;
+ pPipe->nLastError = NO_ERROR;
+ return (oslPipe)pPipe;
+}
+
+/*****************************************************************************/
+/* osl_copyPipe */
+/*****************************************************************************/
+oslPipe SAL_CALL osl_copyPipe(oslPipe pPipe)
+{
+ //oslPipe* pPipe = (oslPipe*) Pipe;
+ oslPipe pNewPipe;
+
+
+ /* check parameter */
+ OSL_ASSERT (pPipe);
+
+ /* allocate impl-structure */
+ pNewPipe = __osl_createPipeImpl();
+ if (!pNewPipe) return NULL;
+
+ /* create new handle */
+ pNewPipe->hPipe = (HPIPE) -1;
+ ngLastError = DosDupHandle( pPipe->hPipe, &(pNewPipe->hPipe) );
+
+ /* if failed, release allocated memory */
+ if (ngLastError)
+ {
+ OSL_TRACE( "osl_copyPipe failed duplicating pipe handle, Error-Code: %d.\n",
+ ngLastError );
+ free (pNewPipe);
+ return NULL;
+ }
+
+ pNewPipe->nLastError = NO_ERROR;
+ return (oslPipe)pNewPipe;
+}
+
+void SAL_CALL osl_acquirePipe( oslPipe pPipe )
+{
+ osl_incrementInterlockedCount( &(pPipe->m_Reference) );
+}
+
+void SAL_CALL osl_releasePipe( oslPipe pPipe )
+{
+// OSL_ASSERT( pPipe );
+
+ if( 0 == pPipe )
+ return;
+
+ if( 0 == osl_decrementInterlockedCount( &(pPipe->m_Reference) ) )
+ {
+ if( ! pPipe->m_bClosed )
+ osl_closePipe( pPipe );
+
+ __osl_destroyPipeImpl( pPipe );
+ }
+}
+
+/*****************************************************************************/
+/* osl_destroyPipe */
+/*************close****************************************************************/
+void SAL_CALL osl_closePipe(oslPipe pPipe)
+{
+ //oslPipe* pPipe = (oslPipe*) Pipe;
+ /* check parameter */
+ OSL_ASSERT (pPipe);
+
+ if( pPipe && ! pPipe->m_bClosed )
+ {
+ pPipe->m_bClosed = sal_True;
+ /* if we have a system pipe close it */
+ if (pPipe->hPipe != 0)
+ {
+ /* disconnect client */
+ DosDisConnectNPipe (pPipe->hPipe);
+
+ /* close the pipe */
+ DosClose (pPipe->hPipe);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* osl_acceptPipe */
+/*****************************************************************************/
+oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe)
+{
+
+#define PINFO ((PIPEINFO *) &PipeInfoBuffer)
+
+ ///oslPipe* pPipe = (oslPipe*) Pipe;
+ oslPipe pNewPipe;
+ BYTE PipeInfoBuffer[sizeof(PIPEINFO) + CCHMAXPATHCOMP];
+
+ /* check parameter */
+ OSL_ASSERT (pPipe);
+
+ /* get pipe information */
+ pPipe->nLastError = DosQueryNPipeInfo(pPipe->hPipe,
+ 1,
+ (PVOID) &PipeInfoBuffer,
+ sizeof(PipeInfoBuffer));
+
+ if (pPipe->nLastError)
+ {
+ OSL_TRACE( "osl_acceptPipe failed for requesting pipe information.\n",
+ pPipe->nLastError );
+ return NULL;
+ }
+
+ /* create a new instance of the pipe if possible */
+ if (PINFO->cbMaxInst == -1 || /* unlimited instances */
+ PINFO->cbMaxInst > PINFO->cbCurInst)
+ {
+ HPIPE hPipe;
+
+ pNewPipe = __osl_createPipeImpl();
+
+ if (!pNewPipe)
+ {
+ OSL_TRACE( "osl_acceptPipe failed creating new instance.\n", ngLastError );
+ free(pNewPipe);
+ return NULL;
+ }
+
+ //pNewPipe->m_Security = pPipe->m_Security;
+
+ pNewPipe->nLastError =
+ DosCreateNPipe( (PCSZ)PINFO->szName,
+ &(pNewPipe->hPipe),
+ NP_ACCESS_DUPLEX, /* open pipe for read and write access */
+ 0xFF, /* allow unlimited number of instances */
+ ulBufSize, /* output buffer size */
+ ulBufSize, /* input buffer size */
+ 0L /* use default time-out time */
+ );
+
+ if (pNewPipe->nLastError)
+ {
+ OSL_TRACE( "osl_acceptPipe failed creating new named pipe, Error-Code: %d.\n",
+ pNewPipe->nLastError );
+ free(pNewPipe);
+ return NULL;
+ }
+
+ /* switch pipe handles */
+ hPipe = pPipe->hPipe;
+ pPipe->hPipe = pNewPipe->hPipe;
+ pNewPipe->hPipe = hPipe;
+
+ /* connect new handle to client */
+ pNewPipe->nLastError = DosConnectNPipe( pNewPipe->hPipe );
+
+ /* if failed, release allocated memory */
+ if (pNewPipe->nLastError)
+ {
+ OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n",
+ pNewPipe->nLastError );
+
+ osl_closePipe((oslPipe)pNewPipe);
+ return NULL;
+ }
+ return (oslPipe)pNewPipe;
+ }
+ else
+ {
+ /* connect original handle to client */
+ pPipe->nLastError = DosConnectNPipe( pPipe->hPipe );
+
+ if (pPipe->nLastError)
+ {
+ OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n",
+ pPipe->nLastError );
+ return NULL;
+ }
+
+ return (oslPipe)pPipe;
+ }
+}
+
+/*****************************************************************************/
+/* osl_receivePipe */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe,
+ void* pBuffer,
+ sal_Int32 BytesToRead)
+{
+ //oslPipe* pPipe = (oslPipe*) Pipe;
+ ULONG ulActual;
+
+ /* check parameter */
+ OSL_ASSERT (pPipe);
+
+ /* read data from pipe */
+ pPipe->nLastError = DosRead( pPipe->hPipe, pBuffer, BytesToRead, &ulActual );
+
+ /* return -1 if failed */
+ if( pPipe->nLastError )
+ {
+ OSL_TRACE( "osl_receivePipe failed receiving from Pipe, Error-Code: %d.\n",
+ pPipe->nLastError );
+ return -1;
+ }
+
+ return ulActual;
+}
+
+
+/*****************************************************************************/
+/* osl_sendPipe */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe,
+ const void* pBuffer,
+ sal_Int32 BytesToSend)
+{
+ //oslPipe* pPipe = (oslPipe*) Pipe;
+ ULONG ulActual;
+
+ /* check parameter */
+ OSL_ASSERT (pPipe);
+
+ /* read data from pipe */
+ pPipe->nLastError = DosWrite( pPipe->hPipe, (PVOID) pBuffer, BytesToSend, &ulActual );
+
+ /* return -1 if failed */
+ if( pPipe->nLastError )
+ {
+ OSL_TRACE( "osl_receivePipe failed writing to Pipe, Error-Code: %d.\n",
+ pPipe->nLastError );
+ return -1;
+ }
+
+ return ulActual;
+}
+
+
+/*****************************************************************************/
+/* osl_getLastPipeError */
+/*****************************************************************************/
+
+oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe)
+{
+ //oslPipe* pPipe = (oslPipe*) Pipe;
+ APIRET rc;
+
+ /* return local error value if possible */
+ if (pPipe)
+ {
+ rc = pPipe->nLastError;
+ pPipe->nLastError = NO_ERROR;
+ } else
+ rc = ngLastError;
+
+ /* map OS/2 error values */
+ switch (rc)
+ {
+ case NO_ERROR: return osl_Pipe_E_None;
+ case ERROR_PATH_NOT_FOUND: return osl_Pipe_E_NotFound;
+ case ERROR_NOT_ENOUGH_MEMORY: return osl_Pipe_E_NoBufferSpace;
+ default: return osl_Pipe_E_invalidError;
+ }
+}
+
+/*****************************************************************************/
+
+sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n )
+{
+ /* loop until all desired bytes were send or an error occured */
+ sal_Int32 BytesSend= 0;
+ sal_Int32 BytesToSend= n;
+
+ OSL_ASSERT(pPipe);
+ while (BytesToSend > 0)
+ {
+ sal_Int32 RetVal;
+
+ RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend);
+
+ /* error occured? */
+ 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 occured */
+ sal_Int32 BytesRead= 0;
+ sal_Int32 BytesToRead= n;
+
+ OSL_ASSERT( pPipe );
+ while (BytesToRead > 0)
+ {
+ sal_Int32 RetVal;
+ RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToRead -= RetVal;
+ BytesRead += RetVal;
+ pBuffer= (sal_Char*)pBuffer + RetVal;
+ }
+ return BytesRead;
+}
+
+
+/******************************************************************************
+ *
+ * New io resource transfer functions
+ *
+ *****************************************************************************/
+
+
+/**********************************************
+ osl_sendResourcePipe
+ *********************************************/
+
+sal_Bool osl_sendResourcePipe(oslPipe pPipe, oslSocket pSocket)
+{
+ sal_Bool bRet = sal_False;
+
+ return bRet;
+}
+
+/**********************************************
+ osl_receiveResourcePipe
+ *********************************************/
+
+oslSocket osl_receiveResourcePipe(oslPipe pPipe)
+{
+ oslSocket pSocket=0;
+
+ return (oslSocket) pSocket;
+}
+
+
diff --git a/sal/osl/os2/pipeimpl.cxx b/sal/osl/os2/pipeimpl.cxx
new file mode 100644
index 000000000000..d08a370c428c
--- /dev/null
+++ b/sal/osl/os2/pipeimpl.cxx
@@ -0,0 +1,755 @@
+# include "pipeimpl.h"
+
+#ifndef _INC_MALLOC
+# include <malloc.h>
+#endif
+
+#ifndef _INC_TCHAR
+# ifdef UNICODE
+# define _UNICODE
+# endif
+# include <tchar.h>
+#endif
+
+const TCHAR PIPE_NAME_PREFIX_MAPPING[] = TEXT("PIPE_FILE_MAPPING_");
+const TCHAR PIPE_NAME_PREFIX_SYNCHRONIZE[] = TEXT("PIPE_SYNCHRONIZE_MUTEX_");
+const TCHAR PIPE_NAME_PREFIX_CONNECTION[] = TEXT("PIPE_CONNECTION_SEMAPHORE_");
+
+const DWORD PIPE_BUFFER_SIZE = 4096;
+
+
+//============================================================================
+// PipeData
+//============================================================================
+
+struct PipeData
+{
+ DWORD dwProcessId;
+ HANDLE hReadPipe;
+ HANDLE hWritePipe;
+};
+
+//============================================================================
+// Pipe
+//============================================================================
+
+#ifdef UNICODE
+#define Pipe PipeW
+#define ClientPipe ClientPipeW
+#define ServerPipe ServerPipeW
+#else
+#define Pipe PipeA
+#define ClientPipe ClientPipeA
+#define ServerPipe ServerPipeA
+#endif
+
+class Pipe
+{
+protected:
+ HANDLE m_hReadPipe; // Handle to use for reading
+ HANDLE m_hWritePipe; // Handle to use for writing
+
+ Pipe( HANDLE hReadPipe, HANDLE hWritePipe );
+
+ static HANDLE CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner );
+ static HANDLE CreatePipeDataMapping( LPCTSTR lpName );
+ static HANDLE OpenPipeDataMapping( LPCTSTR lpName );
+ static HANDLE CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumcount );
+
+public:
+ Pipe( const Pipe& );
+ const Pipe& operator = ( const Pipe& );
+ virtual ~Pipe();
+
+ virtual bool Close();
+ virtual bool Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait = true );
+ virtual bool Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait = true );
+
+ virtual Pipe *AcceptConnection()
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return NULL;
+ }
+
+ void * operator new( size_t nBytes )
+ {
+ return HeapAlloc( GetProcessHeap(), 0, nBytes );
+ }
+
+ void operator delete( void *ptr )
+ {
+ HeapFree( GetProcessHeap(), 0, ptr );
+ }
+
+ bool is() const
+ {
+ return (FALSE != HeapValidate( GetProcessHeap(), 0, this ));
+ }
+
+};
+
+//============================================================================
+// ClientPipe
+//============================================================================
+
+class ClientPipe : public Pipe
+{
+protected:
+ ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe );
+public:
+ static ClientPipe* Create( LPCTSTR lpName );
+};
+
+//============================================================================
+// ServerPipe
+//============================================================================
+
+class ServerPipe : public Pipe
+{
+protected:
+ HANDLE m_hMapping;
+ HANDLE m_hSynchronize;
+ LPTSTR m_lpName;
+
+ ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe );
+public:
+ virtual ~ServerPipe();
+
+ static ServerPipe *Create( LPCTSTR lpName );
+
+ virtual Pipe *AcceptConnection();
+};
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeDataMapping( LPCTSTR lpName )
+{
+ HANDLE hMapping = NULL;
+ LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
+
+ if ( lpMappingName )
+ {
+ _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
+ _tcscat( lpMappingName, lpName );
+
+ LPTSTR lpMappingFileName = (LPTSTR)alloca( MAX_PATH * sizeof(TCHAR) );
+
+ if ( lpMappingFileName )
+ {
+ DWORD nChars = GetTempPath( MAX_PATH, lpMappingFileName );
+
+ if ( MAX_PATH + _tcslen(lpName) < nChars + 1 )
+ {
+ lpMappingFileName = (LPTSTR)alloca( (nChars + 1 + _tcslen(lpName)) * sizeof(TCHAR) );
+ if ( lpMappingFileName )
+ nChars = GetTempPath( nChars, lpMappingFileName );
+ else
+ {
+ nChars = 0;
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ }
+ }
+
+ if ( nChars )
+ {
+ _tcscat( lpMappingFileName, lpMappingName );
+
+ HANDLE hFile = CreateFile(
+ lpMappingFileName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
+ NULL );
+
+ if ( IsValidHandle(hFile) )
+ {
+ hMapping = CreateFileMapping(
+ (HANDLE)hFile,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ PAGE_READWRITE,
+ 0,
+ sizeof(PipeData),
+ lpMappingName );
+
+ CloseHandle( hFile );
+ }
+ }
+ }
+ else
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ }
+
+ return hMapping;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::OpenPipeDataMapping( LPCTSTR lpName )
+{
+ HANDLE hMapping = NULL;
+ LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
+
+ if ( lpMappingName )
+ {
+ _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
+ _tcscat( lpMappingName, lpName );
+
+ hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpMappingName );
+ }
+
+ return hMapping;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner )
+{
+ HANDLE hMutex = NULL;
+ LPTSTR lpMutexName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_SYNCHRONIZE) );
+
+ if ( lpMutexName )
+ {
+ _tcscpy( lpMutexName, PIPE_NAME_PREFIX_SYNCHRONIZE );
+ _tcscat( lpMutexName, lpName );
+
+ hMutex = CreateMutex( NULL, bInitialOwner, lpMutexName );
+ }
+
+ return hMutex;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumCount )
+{
+ HANDLE hSemaphore = NULL;
+ LPTSTR lpSemaphoreName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_CONNECTION) );
+
+ if ( lpSemaphoreName )
+ {
+ _tcscpy( lpSemaphoreName, PIPE_NAME_PREFIX_CONNECTION );
+ _tcscat( lpSemaphoreName, lpName );
+
+ hSemaphore = CreateSemaphore( NULL, lInitialCount, lMaximumCount, lpSemaphoreName );
+ }
+
+ return hSemaphore;
+}
+
+
+//----------------------------------------------------------------------------
+// Pipe copy ctor
+//----------------------------------------------------------------------------
+
+Pipe::Pipe( const Pipe& rPipe ) :
+m_hReadPipe( INVALID_HANDLE_VALUE ),
+m_hWritePipe( INVALID_HANDLE_VALUE )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+}
+
+//----------------------------------------------------------------------------
+// Pipe assignment operator
+//----------------------------------------------------------------------------
+
+const Pipe& Pipe::operator = ( const Pipe& rPipe )
+{
+ Close();
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+// Pipe ctor
+//----------------------------------------------------------------------------
+
+Pipe::Pipe( HANDLE hReadPipe, HANDLE hWritePipe ) :
+m_hReadPipe( INVALID_HANDLE_VALUE ),
+m_hWritePipe( INVALID_HANDLE_VALUE )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+}
+
+//----------------------------------------------------------------------------
+// Pipe dtor
+//----------------------------------------------------------------------------
+
+Pipe::~Pipe()
+{
+ Close();
+}
+
+//----------------------------------------------------------------------------
+// Pipe Close
+//----------------------------------------------------------------------------
+
+bool Pipe::Close()
+{
+ bool fSuccess = false; // Assume failure
+
+ if ( IsValidHandle(m_hReadPipe) )
+ {
+ CloseHandle( m_hReadPipe );
+ m_hReadPipe = INVALID_HANDLE_VALUE;
+ }
+
+ if ( IsValidHandle(m_hWritePipe) )
+ {
+ CloseHandle( m_hWritePipe );
+ m_hWritePipe = INVALID_HANDLE_VALUE;
+ }
+
+ return fSuccess;
+}
+
+//----------------------------------------------------------------------------
+// Pipe Write
+//----------------------------------------------------------------------------
+
+bool Pipe::Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait )
+{
+ DWORD dwBytesAvailable = 0;
+ BOOL fSuccess = TRUE;
+
+ if ( !bWait )
+ fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
+
+ if ( fSuccess )
+ {
+ if ( !bWait && dwBytesToWrite > PIPE_BUFFER_SIZE - dwBytesAvailable )
+ dwBytesToWrite = PIPE_BUFFER_SIZE - dwBytesAvailable ;
+
+ return !!WriteFile( m_hWritePipe, lpBuffer, dwBytesToWrite, lpBytesWritten, NULL );
+ }
+
+ return false;
+}
+
+//----------------------------------------------------------------------------
+// Pipe Read
+//----------------------------------------------------------------------------
+
+bool Pipe::Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait )
+{
+ DWORD dwBytesAvailable = 0;
+ BOOL fSuccess = TRUE;
+
+ if ( !bWait )
+ fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
+
+ if ( fSuccess )
+ {
+ if ( bWait || dwBytesAvailable )
+ return !!ReadFile( m_hReadPipe, lpBuffer, dwBytesToRead, lpBytesRead, NULL );
+ else
+ {
+ *lpBytesRead = 0;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+
+//----------------------------------------------------------------------------
+// Client pipe dtor
+//----------------------------------------------------------------------------
+
+ClientPipe::ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe )
+{
+}
+
+//----------------------------------------------------------------------------
+// Client pipe creation
+//----------------------------------------------------------------------------
+
+ClientPipe *ClientPipe::Create( LPCTSTR lpName )
+{
+ ClientPipe *pPipe = NULL; // Assume failure
+
+ HANDLE hMapping = OpenPipeDataMapping( lpName );
+
+ if ( IsValidHandle(hMapping) )
+ {
+ PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
+
+ if ( pData )
+ {
+ HANDLE hSourceProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, pData->dwProcessId );
+
+ if ( IsValidHandle(hSourceProcess) )
+ {
+ BOOL fSuccess;
+ HANDLE hReadPipe = INVALID_HANDLE_VALUE, hWritePipe = INVALID_HANDLE_VALUE;
+
+ fSuccess = DuplicateHandle(
+ hSourceProcess,
+ pData->hReadPipe,
+ GetCurrentProcess(),
+ &hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ fSuccess = fSuccess && DuplicateHandle(
+ hSourceProcess,
+ pData->hWritePipe,
+ GetCurrentProcess(),
+ &hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ if ( fSuccess )
+ pPipe = new ClientPipe( hReadPipe, hWritePipe );
+
+ if ( IsValidHandle(hWritePipe) )
+ CloseHandle( hWritePipe );
+
+ if ( IsValidHandle(hReadPipe) )
+ CloseHandle( hReadPipe );
+
+ HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( lpName, 0, 1 );
+
+ ReleaseSemaphore( hConnectionRequest, 1, NULL );
+
+ CloseHandle( hConnectionRequest );
+
+ CloseHandle( hSourceProcess );
+ }
+
+ UnmapViewOfFile( pData );
+ }
+
+ CloseHandle( hMapping );
+ }
+
+ return pPipe;
+}
+
+
+
+//----------------------------------------------------------------------------
+// ServerPipe ctor
+//----------------------------------------------------------------------------
+
+ServerPipe::ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe ),
+m_hMapping( NULL ),
+m_hSynchronize( NULL ),
+m_lpName( NULL )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hMapping,
+ GetCurrentProcess(),
+ &m_hMapping,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hSynchronize,
+ GetCurrentProcess(),
+ &m_hSynchronize,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS
+ );
+ m_lpName = new TCHAR[_tcslen(lpName) + 1];
+ if ( m_lpName )
+ _tcscpy( m_lpName, lpName );
+}
+
+//----------------------------------------------------------------------------
+// ServerPipe dtor
+//----------------------------------------------------------------------------
+
+ServerPipe::~ServerPipe()
+{
+ if ( IsValidHandle(m_hMapping) )
+ CloseHandle( m_hMapping );
+ if ( m_lpName )
+ delete[]m_lpName;
+}
+
+//----------------------------------------------------------------------------
+// ServerPipe AcceptConnection
+//----------------------------------------------------------------------------
+
+Pipe *ServerPipe::AcceptConnection()
+{
+ Pipe *pPipe = NULL; // Assume failure;
+
+ HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( m_lpName, 0, 1 );
+
+ if ( WAIT_OBJECT_0 == WaitForSingleObject( hConnectionRequest, INFINITE ) )
+ {
+ pPipe = new Pipe( *this );
+ Close();
+
+ // Create new inbound Pipe
+
+ HANDLE hClientWritePipe = NULL, hServerReadPipe = NULL;
+
+ BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+
+ if ( fSuccess )
+ {
+ // Create outbound pipe
+
+ HANDLE hClientReadPipe = NULL, hServerWritePipe = NULL;
+
+ if ( CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE ) )
+ {
+ m_hReadPipe = hServerReadPipe;
+ m_hWritePipe = hServerWritePipe;
+
+ PipeData *pData = (PipeData *)MapViewOfFile( m_hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(PipeData) );
+
+ HANDLE hSynchronize = CreatePipeDataMutex( m_lpName, TRUE );
+
+ CloseHandle( pData->hReadPipe );
+ CloseHandle( pData->hWritePipe );
+
+ pData->hReadPipe = hClientReadPipe;
+ pData->hWritePipe = hClientWritePipe;
+
+ ReleaseMutex( hSynchronize );
+
+ CloseHandle( hSynchronize );
+
+ }
+ else
+ {
+ CloseHandle( hClientWritePipe );
+ CloseHandle( hServerWritePipe );
+ }
+ }
+
+ ReleaseMutex( hConnectionRequest );
+ }
+
+ CloseHandle( hConnectionRequest );
+
+ return pPipe;
+}
+
+//----------------------------------------------------------------------------
+// Pipe creation
+//----------------------------------------------------------------------------
+
+ServerPipe *ServerPipe::Create( LPCTSTR lpName )
+{
+ ServerPipe *pPipe = NULL;
+
+ HANDLE hMapping = CreatePipeDataMapping( lpName );
+
+ if ( IsValidHandle(hMapping) )
+ {
+ if ( ERROR_FILE_EXISTS != GetLastError() )
+ {
+ HANDLE hSynchronize = CreatePipeDataMutex( lpName, FALSE);
+
+ WaitForSingleObject( hSynchronize, INFINITE );
+
+ PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
+
+ if ( pData )
+ {
+
+ // Initialize pipe data
+
+ pData->dwProcessId = 0;
+ pData->hReadPipe = NULL;
+ pData->hWritePipe = NULL;
+
+ // Create inbound pipe
+
+ HANDLE hServerReadPipe = NULL, hClientWritePipe = NULL;
+
+ BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+ if ( fSuccess )
+ {
+ // Create outbound pipe
+
+ HANDLE hServerWritePipe = NULL, hClientReadPipe = NULL;
+
+ fSuccess = CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+ if ( fSuccess )
+ {
+ pData->dwProcessId = GetCurrentProcessId();
+ pData->hReadPipe = hClientReadPipe;
+ pData->hWritePipe = hClientWritePipe;
+ pPipe = new ServerPipe( lpName, hMapping, hSynchronize, hServerReadPipe, hServerWritePipe );
+
+ CloseHandle( hServerWritePipe );
+ CloseHandle( hServerReadPipe );
+ }
+ else
+ {
+ CloseHandle( hServerReadPipe );
+ CloseHandle( hClientWritePipe );
+ }
+ }
+
+ UnmapViewOfFile( pData );
+ }
+
+ ReleaseMutex( hSynchronize );
+ CloseHandle( hSynchronize );
+ }
+
+ CloseHandle( hMapping );
+ }
+
+ return pPipe;
+}
+
+
+//----------------------------------------------------------------------------
+// C style API
+//----------------------------------------------------------------------------
+
+const TCHAR LOCAL_PIPE_PREFIX[] = TEXT("\\\\.\\PIPE\\" );
+
+extern "C" HANDLE WINAPI CreateSimplePipe( LPCTSTR lpName )
+{
+ int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
+ if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
+ lpName += nPrefixLen;
+ return (HANDLE)ServerPipe::Create( lpName );
+}
+
+extern "C" HANDLE WINAPI OpenSimplePipe( LPCTSTR lpName )
+{
+ int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
+ if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
+ lpName += nPrefixLen;
+ return (HANDLE)ClientPipe::Create( lpName );
+}
+
+extern "C" HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return (HANDLE)pPipe->AcceptConnection();
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return NULL;
+ }
+}
+
+extern "C" BOOL WINAPI WaitForSimplePipe( LPCTSTR /*lpName*/, DWORD /*dwTimeOut*/ )
+{
+ return FALSE;
+}
+
+extern "C" BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return pPipe->Write( lpBuffer, dwBytesToWrite, lpBytesWritten, bWait );
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
+
+extern "C" BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return pPipe->Read( lpBuffer, dwBytesToRead, lpBytesRead, bWait );
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
+
+extern "C" BOOL WINAPI CloseSimplePipe( HANDLE hPipe )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ {
+ delete pPipe;
+ return TRUE;
+ }
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
diff --git a/sal/osl/os2/pipeimpl.h b/sal/osl/os2/pipeimpl.h
new file mode 100644
index 000000000000..cff082dee5a3
--- /dev/null
+++ b/sal/osl/os2/pipeimpl.h
@@ -0,0 +1,82 @@
+#ifndef _PIPEIMPL_H_
+#define _PIPEIMPL_H_
+
+#ifndef _WINDOWS_
+# include <windows.h>
+#endif
+
+#ifndef _INC_MALLOC
+# include <malloc.h>
+#endif
+
+#ifndef _INC_TCHAR
+# ifdef UNICODE
+# define _UNICODE
+# endif
+# include <tchar.h>
+#endif
+
+#define EXPORT_PIPE_API
+
+//============================================================================
+// Helper functions
+//============================================================================
+
+// Because the value of an invalid HANDLE returned by API functions differs
+// between different functions and differs on different Windows platforms,
+// this function checks wether the handle has a meaningfull value.
+#ifndef __cplusplus
+
+#define IsValidHandle( handle ) ((DWORD)(handle) + 1 > 1)
+
+#else
+
+inline bool IsValidHandle( HANDLE handle )
+{
+ return INVALID_HANDLE_VALUE != handle && NULL != handle;
+}
+
+extern "C" {
+
+#endif // __cplusplus
+
+
+EXPORT_PIPE_API HANDLE WINAPI CreateSimplePipeA( LPCSTR lpName );
+EXPORT_PIPE_API HANDLE WINAPI CreateSimplePipeW( LPCWSTR lpName );
+
+#ifdef UNICODE
+#define CreateSimplePipe CreateSimplePipeW
+#else
+#define CreateSimplePipe CreateSimplePipeA
+#endif
+
+EXPORT_PIPE_API HANDLE WINAPI OpenSimplePipeA( LPCSTR lpName );
+EXPORT_PIPE_API HANDLE WINAPI OpenSimplePipeW( LPCWSTR lpName );
+
+#ifdef UNICODE
+#define OpenSimplePipe OpenSimplePipeW
+#else
+#define OpenSimplePipe OpenSimplePipeA
+#endif
+
+EXPORT_PIPE_API HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe );
+
+EXPORT_PIPE_API BOOL WINAPI WaitForSimplePipeA( LPCSTR lpName, DWORD dwTimeOut );
+EXPORT_PIPE_API BOOL WINAPI WaitForSimplePipeW( LPCWSTR lpName, DWORD dwTimeOut );
+
+#ifdef UNICODE
+#define WaitForSimplePipe WaitForSimplePipeW
+#else
+#define WaitForSimplePipe WaitForSimplePipeA
+#endif
+
+
+EXPORT_PIPE_API BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait );
+EXPORT_PIPE_API BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait );
+EXPORT_PIPE_API BOOL WINAPI CloseSimplePipe( HANDLE hPipe );
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PIPEIMPL_H_
diff --git a/sal/osl/os2/process.c b/sal/osl/os2/process.c
new file mode 100644
index 000000000000..e83552192bfb
--- /dev/null
+++ b/sal/osl/os2/process.c
@@ -0,0 +1,1013 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+#include <osl/thread.h>
+
+#include <osl/diagnose.h>
+//#include <osl/socket.h>
+
+#ifndef _OSL_FILE_PATH_HELPER_H_
+#include "file_path_helper.h"
+#endif
+
+#include "procimpl.h"
+//#include "sockimpl.h"
+//#include "secimpl.h"
+
+#include <ctype.h>
+
+//#ifndef _RTL_USTRING_HXX_
+#include <rtl/ustring.hxx>
+//#endif
+
+// for exception logging
+#include <stdio.h>
+#include <setjmp.h>
+#include "helpers/except.h"
+
+
+#define MAX_ARGS 255
+#define PIPENAMEMASK "\\PIPE\\OSL_PIPE_%u"
+#define SEMNAMEMASK "\\SEM32\\OSL_SEM_%u"
+
+typedef enum {
+ MSG_DATA,
+ MSG_END,
+ MSG_ACK,
+ MSG_REL,
+ MSG_UNKNOWN
+} MessageType;
+
+typedef struct {
+ MessageType m_Type;
+ oslDescriptorFlag m_Flags;
+ oslDescriptorType m_Data;
+ HANDLE m_Value;
+} Message;
+
+typedef struct {
+ HPIPE m_hPipe;
+} Pipe;
+
+typedef struct _oslSocketCallbackArg {
+ HANDLE m_socket;
+ Pipe* m_pipe;
+} oslSocketCallbackArg;
+
+/* process termination queue */
+static sal_Bool bInitSessionTerm = sal_False;
+static const sal_Char * const SessionTermQueueName = "\\QUEUES\\SESSIONS.QUE";
+static HQUEUE SessionTermQueue;
+
+/******************************************************************************
+ *
+ * Function Declarations
+ *
+ *****************************************************************************/
+
+oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
+ sal_Char *pszArguments[],
+ oslProcessOption Options,
+ oslSecurity Security,
+ sal_Char *pszDirectory,
+ sal_Char *pszEnvironments[],
+ oslProcess *pProcess,
+ oslFileHandle *pInputWrite,
+ oslFileHandle *pOutputRead,
+ oslFileHandle *pErrorRead );
+
+/* implemented in file.c */
+extern oslFileError FileURLToPath( char *, size_t, rtl_uString* );
+
+static sal_Bool InitSessionTerm( void )
+{
+ DosCreateQueue( &SessionTermQueue, QUE_FIFO, (PCSZ) SessionTermQueueName );
+
+ return sal_True;
+}
+
+/******************************************************************************
+ *
+ * Functions for starting a process
+ *
+ *****************************************************************************/
+
+/**********************************************
+ osl_executeProcess_WithRedirectedIO
+ *********************************************/
+
+oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO(
+ rtl_uString *ustrImageName,
+ rtl_uString *ustrArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *ustrWorkDir,
+ rtl_uString *ustrEnvironment[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess,
+ oslFileHandle *pInputWrite,
+ oslFileHandle *pOutputRead,
+ oslFileHandle *pErrorRead
+ )
+{
+
+ oslProcessError Error;
+ sal_Char* pszWorkDir=0;
+ sal_Char** pArguments=0;
+ sal_Char** pEnvironment=0;
+ unsigned int index;
+
+ char szImagePath[PATH_MAX] = "";
+ char szWorkDir[PATH_MAX] = "";
+
+#if 0
+ if (Options & osl_Process_SEARCHPATH)
+ {
+ const rtl::OUString PATH1;
+ OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH"));
+
+ rtl_uString * pSearchPath = 0;
+ osl_getEnvironment (PATH.pData, &pSearchPath);
+ if (pSearchPath)
+ {
+ rtl_uString * pSearchResult = 0;
+ osl_searchPath (ustrImageName, pSearchPath, &pSearchResult);
+ if (pSearchResult)
+ {
+ rtl_uString_assign (ustrImageName, pSearchResult);
+ rtl_uString_release (pSearchResult);
+ }
+ rtl_uString_release (pSearchPath);
+ }
+ }
+#endif
+
+ if ( ustrImageName && ustrImageName->length )
+ {
+ FileURLToPath( szImagePath, PATH_MAX, ustrImageName );
+ }
+
+ if ( ustrWorkDir != 0 && ustrWorkDir->length )
+ {
+ FileURLToPath( szWorkDir, PATH_MAX, ustrWorkDir );
+ pszWorkDir = szWorkDir;
+ }
+
+ if ( pArguments == 0 && nArguments > 0 )
+ {
+ pArguments = (sal_Char**) malloc( ( nArguments + 2 ) * sizeof(sal_Char*) );
+ }
+
+
+ for ( index = 0 ; index < nArguments ; ++index )
+ {
+ rtl_String* strArg =0;
+
+
+ rtl_uString2String( &strArg,
+ rtl_uString_getStr(ustrArguments[index]),
+ rtl_uString_getLength(ustrArguments[index]),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pArguments[index]=strdup(rtl_string_getStr(strArg));
+ rtl_string_release(strArg);
+ pArguments[index+1]=0;
+ }
+
+ for ( index = 0 ; index < nEnvironmentVars ; ++index )
+ {
+ rtl_String* strEnv=0;
+
+ if ( pEnvironment == 0 )
+ {
+ pEnvironment = (sal_Char**) malloc( ( nEnvironmentVars + 2 ) * sizeof(sal_Char*) );
+ }
+
+ rtl_uString2String( &strEnv,
+ rtl_uString_getStr(ustrEnvironment[index]),
+ rtl_uString_getLength(ustrEnvironment[index]),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pEnvironment[index]=strdup(rtl_string_getStr(strEnv));
+ rtl_string_release(strEnv);
+ pEnvironment[index+1]=0;
+ }
+
+ int rc, pid;
+ int saveOutput = -1, saveInput = -1, saveError = -1;
+ int stdOutput[2] = { -1, -1 }, stdInput[2] = { -1, -1 }, stdError[2] = { -1, -1 };
+ FILE *i, *o, *e;
+
+ if (pInputWrite)
+ pipe( stdInput);
+ if (pOutputRead)
+ pipe( stdOutput);
+ if (pErrorRead)
+ pipe( stdError);
+
+ fcntl( stdInput[0], F_SETFD, FD_CLOEXEC);
+ fcntl( stdInput[1], F_SETFD, FD_CLOEXEC);
+ fcntl( stdOutput[0], F_SETFD, FD_CLOEXEC);
+ fcntl( stdOutput[1], F_SETFD, FD_CLOEXEC);
+ fcntl( stdError[0], F_SETFD, FD_CLOEXEC);
+ fcntl( stdError[1], F_SETFD, FD_CLOEXEC);
+
+ saveInput = dup( STDIN_FILENO);
+ fcntl( saveInput, F_SETFD, FD_CLOEXEC);
+ dup2( stdInput[0], STDIN_FILENO );
+ close( stdInput[0] );
+
+ saveOutput = dup( STDOUT_FILENO);
+ fcntl( saveOutput, F_SETFD, FD_CLOEXEC);
+ dup2( stdOutput[1], STDOUT_FILENO );
+ close( stdOutput[1] );
+
+ saveError = dup( STDERR_FILENO);
+ fcntl( saveError, F_SETFD, FD_CLOEXEC);
+ dup2( stdError[1], STDERR_FILENO );
+ close( stdError[1] );
+
+ Error = osl_psz_executeProcess(szImagePath,
+ pArguments,
+ Options,
+ Security,
+ pszWorkDir,
+ pEnvironment,
+ pProcess,
+ pInputWrite,
+ pOutputRead,
+ pErrorRead
+ );
+
+ if ( pInputWrite )
+ *(pInputWrite) = osl_createFileHandleFromFD( stdInput[1] );
+
+ if ( pOutputRead )
+ *(pOutputRead) = osl_createFileHandleFromFD( stdOutput[0] );
+
+ if ( pErrorRead )
+ *(pErrorRead) = osl_createFileHandleFromFD( stdError[0] );
+
+ // restore handles
+ dup2( saveInput, STDIN_FILENO);
+ close( saveInput);
+ dup2( saveOutput, STDOUT_FILENO);
+ close( saveOutput);
+ dup2( saveError, STDERR_FILENO);
+ close( saveError);
+
+ if ( pArguments != 0 )
+ {
+ for ( index = 0 ; index < nArguments ; ++index )
+ {
+ if ( pArguments[index] != 0 )
+ {
+ free(pArguments[index]);
+ }
+ }
+ free(pArguments);
+ }
+
+ if ( pEnvironment != 0 )
+ {
+ for ( index = 0 ; index < nEnvironmentVars ; ++index )
+ {
+ if ( pEnvironment[index] != 0 )
+ {
+ free(pEnvironment[index]);
+ }
+ }
+ free(pEnvironment);
+ }
+
+ return Error;
+}
+
+/**********************************************
+ osl_executeProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_executeProcess(
+ rtl_uString *ustrImageName,
+ rtl_uString *ustrArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *ustrWorkDir,
+ rtl_uString *ustrEnvironment[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess
+ )
+{
+ return osl_executeProcess_WithRedirectedIO(
+ ustrImageName,
+ ustrArguments,
+ nArguments,
+ Options,
+ Security,
+ ustrWorkDir,
+ ustrEnvironment,
+ nEnvironmentVars,
+ pProcess,
+ NULL,
+ NULL,
+ NULL
+ );
+}
+
+/**********************************************
+ osl_psz_executeProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
+ sal_Char *pszArguments[],
+ oslProcessOption Options,
+ oslSecurity Security,
+ sal_Char *pszDirectory,
+ sal_Char *pszEnvironments[],
+ oslProcess *pProcess,
+ oslFileHandle *pInputWrite,
+ oslFileHandle *pOutputRead,
+ oslFileHandle *pErrorRead
+ )
+{
+ ULONG ulSessID = 0; /* Session ID returned */
+ PID pidProcess;
+ APIRET rc;
+ sal_Char* pStr;
+ sal_Char* args;
+ sal_Char* envs;
+ int i;
+ int n = 1;
+ oslProcessImpl* pProcImpl;
+ ULONG nAppType, nOwnAppType;
+ ULONG nCurrentDisk, nDriveMap, nBufSize;
+ int first = 0;
+ sal_Char path[ _MAX_PATH ];
+ sal_Char currentDir[ _MAX_PATH ];
+ sal_Char ownfilename[ _MAX_PATH ];
+ RESULTCODES resultCode;
+ char** p;
+
+ /* get imagename from arg list, if not specified */
+ if (pszImageName == NULL)
+ pszImageName = pszArguments[first++];
+
+ OSL_ASSERT(pszImageName != NULL);
+
+ /* check application type */
+ rc = DosQueryAppType( (PCSZ) pszImageName, &nAppType );
+ if( rc != NO_ERROR )
+ {
+ if( (rc == ERROR_FILE_NOT_FOUND) || (rc == ERROR_PATH_NOT_FOUND) )
+ return osl_Process_E_NotFound;
+ else
+ return osl_Process_E_Unknown;
+ }
+
+ /* backup current disk information */
+ if(DosQueryCurrentDisk(&nCurrentDisk, &nDriveMap))
+ {
+ nCurrentDisk = 0;
+ }
+
+ /* backup current directory information */
+ nBufSize = _MAX_PATH;
+ if(DosQueryCurrentDir(0, (BYTE*)currentDir, &nBufSize))
+ {
+ *currentDir = '\0';
+ }
+
+ /* change to working directory */
+ if(pszDirectory && pszDirectory[1] == ':')
+ {
+ BYTE nDrive = toupper(pszDirectory[0]) - 'A' + 1;
+
+ if(NO_ERROR == DosSetDefaultDisk(nDrive))
+ {
+ DosSetCurrentDir((PSZ) pszDirectory);
+ }
+ }
+
+ /* query current executable filename and application type */
+ {
+ CHAR szName[CCHMAXPATH];
+ PPIB ppib;
+ PTIB ptib;
+ APIRET rc;
+ rc = DosGetInfoBlocks(&ptib, &ppib);
+ rc = DosQueryModuleName(ppib->pib_hmte, sizeof(szName), szName);
+ DosQueryAppType( (PCSZ)szName, &nOwnAppType );
+ }
+
+ /* combination of flags WAIT and DETACHED not supported */
+ if( (Options & osl_Process_DETACHED) && (Options & osl_Process_WAIT) )
+ Options &= !osl_Process_DETACHED;
+
+ /* start in same session if possible and detached flag not set */
+ if( ((nAppType & 0x00000007) == (nOwnAppType & 0x00000007))
+/* && ((Options & osl_Process_DETACHED) == 0) */ )
+ {
+ CHAR szbuf[CCHMAXPATH];
+
+ /* calculate needed space for arguments */
+ n = strlen( pszImageName ) + 1;
+ if( pszArguments )
+ for (i = first; pszArguments[i] != NULL; i++)
+ n += strlen(pszArguments[i]) + 1;
+
+ /* allocate space for arguments */
+ args = (sal_Char*)malloc(n + 1);
+ pStr = args;
+
+ /* add program name as first string to arguments */
+ memcpy(pStr, pszImageName, strlen( pszImageName ) );
+ pStr += strlen( pszImageName );
+ *pStr++ = '\0';
+
+ /* add given strings to arguments */
+ if( pszArguments )
+ for (i = first; pszArguments[i] != NULL; i++)
+ {
+ memcpy(pStr, pszArguments[i], strlen( pszArguments[i] ) );
+ pStr += strlen( pszArguments[i] );
+ if (pszArguments[i+1] != NULL)
+ *pStr++ = ' ';
+ }
+
+ /* set end marker for arguments */
+ *pStr++ = '\0';
+ *pStr = '\0';
+
+ OSL_TRACE( "osl_executeProcess with DosExecPgm (args: %s)\n", args );
+
+ /* calculate needed space for environment: since enviroment var search
+ is a linear scan of the current enviroment, we place new variables
+ before existing ones; so the child will find new definitions before
+ olders; this doesn't require us to replace existing vars */
+ // existing enviroment size
+ n = 0;
+ p = environ;
+ while( *p)
+ {
+ int l = strlen( *p);
+ n += l + 1;
+ p++;
+ }
+ // new env size (if exists)
+ if( pszEnvironments )
+ {
+ for (i = 0; pszEnvironments[i] != NULL; i++)
+ n += strlen(pszEnvironments[i]) + 1;
+ }
+ /* allocate space for environment */
+ envs = (sal_Char*)malloc(n + 1);
+ pStr = envs;
+
+ // add new vars
+ if( pszEnvironments )
+ {
+ /* add given strings to environment */
+ for (i = 0; pszEnvironments[i] != NULL; i++)
+ {
+ memcpy(pStr, pszEnvironments[i], strlen( pszEnvironments[i] ) );
+ pStr += strlen( pszEnvironments[i] );
+ *pStr++ = '\0';
+ }
+ }
+ // add existing vars
+ p = environ;
+ while( *p)
+ {
+ memcpy(pStr, *p, strlen( *p ) );
+ pStr += strlen( *p );
+ *pStr++ = '\0';
+ p++;
+ }
+ /* set end marker for environment */
+ *pStr = '\0';
+
+
+ if(Options & osl_Process_DETACHED)
+ {
+ rc = DosExecPgm( szbuf, sizeof( szbuf ), EXEC_BACKGROUND,
+ (PSZ) args, (PSZ) envs, &resultCode, (PSZ) pszImageName );
+ }
+ else
+ {
+ rc = DosExecPgm( szbuf, sizeof( szbuf ), EXEC_ASYNCRESULT,
+ (PSZ) args, (PSZ) envs, &resultCode, (PSZ) pszImageName );
+ }
+
+ pidProcess = resultCode.codeTerminate;
+
+ /* cleanup */
+ free(envs);
+ free(args);
+
+ /* error handling */
+ if( rc != NO_ERROR )
+ return osl_Process_E_Unknown;
+ }
+
+ else
+ {
+ STARTDATA SData = { 0 };
+ UCHAR achObjBuf[ 256 ] = { 0 };
+
+ /* combine arguments separated by spaces */
+ if( pszArguments )
+ {
+ for (i = first; pszArguments[i] != NULL; i++)
+ n += strlen(pszArguments[i]) + 1;
+ // YD DosStartSession requires low-mem buffers!
+ args = (sal_Char*)_tmalloc(n);
+ *args = '\0';
+ for (i = first; pszArguments[i] != NULL; i++)
+ {
+ strcat(args, pszArguments[i]);
+ strcat(args, " ");
+ }
+ }
+ else
+ args = NULL;
+
+ /* combine environment separated by NULL */
+ if( pszEnvironments )
+ {
+ for (i = 0; pszEnvironments[i] != NULL; i++)
+ n += strlen(pszEnvironments[i]) + 1;
+ // YD DosStartSession requires low-mem buffers!
+ envs = (sal_Char*)_tmalloc(n + 1);
+ pStr = (sal_Char*)envs;
+ for (i = 0; pszEnvironments[i] != NULL; i++)
+ {
+ memcpy(pStr, pszEnvironments[i], strlen( pszEnvironments[i] ) );
+ pStr += strlen( pszEnvironments[i] );
+ *pStr = '\0';
+ pStr++;
+ }
+ *pStr = '\0';
+ }
+ else
+ envs = NULL;
+
+ /* initialize data structure */
+ memset( &SData, 0, sizeof( STARTDATA ) );
+ SData.Length = sizeof(STARTDATA);
+
+ OSL_TRACE( "osl_executeProcess with DosStartSession (args: %s)\n", args );
+
+ /* OS/2 Application ? */
+ if(nAppType & 0x00000007)
+ {
+
+ /* inherit options from parent */
+ SData.InheritOpt = SSF_INHERTOPT_PARENT;
+
+ switch (Options & (osl_Process_NORMAL | osl_Process_MINIMIZED |
+ osl_Process_MAXIMIZED | osl_Process_FULLSCREEN))
+ {
+ case osl_Process_MINIMIZED:
+ SData.SessionType = SSF_TYPE_DEFAULT;
+ SData.PgmControl |= SSF_CONTROL_MINIMIZE;
+ break;
+
+ case osl_Process_MAXIMIZED:
+ SData.SessionType = SSF_TYPE_DEFAULT;
+ SData.PgmControl |= SSF_CONTROL_MAXIMIZE;
+ break;
+
+ case osl_Process_FULLSCREEN:
+ SData.SessionType = SSF_TYPE_FULLSCREEN;
+ break;
+
+ default:
+ SData.SessionType = SSF_TYPE_DEFAULT;
+ } /* switch */
+ }
+
+
+ if( Options & osl_Process_DETACHED )
+ {
+ /* start an independent session */
+ SData.Related = SSF_RELATED_INDEPENDENT;
+ SData.TermQ = NULL;
+ }
+ else
+ {
+ /* start a child session and set Termination Queue */
+ SData.Related = SSF_RELATED_CHILD;
+
+ if(! bInitSessionTerm)
+ bInitSessionTerm = InitSessionTerm();
+
+ SData.TermQ = (BYTE*) SessionTermQueueName;
+ }
+
+ SData.FgBg = SSF_FGBG_FORE; /* start session in foreground */
+ SData.TraceOpt = SSF_TRACEOPT_NONE; /* No trace */
+
+ SData.PgmTitle = NULL;
+ SData.PgmInputs = (BYTE*)args;
+ SData.PgmName = (PSZ) pszImageName;
+ SData.Environment = (BYTE*)envs;
+
+ if( Options & osl_Process_HIDDEN )
+ SData.PgmControl |= SSF_CONTROL_INVISIBLE;
+ else
+ SData.PgmControl |= SSF_CONTROL_VISIBLE;
+
+ SData.ObjectBuffer = (PSZ) achObjBuf;
+ SData.ObjectBuffLen = (ULONG) sizeof(achObjBuf);
+
+
+ /* Start the session */
+ rc = DosStartSession( &SData, &ulSessID, &pidProcess );
+
+ /* ignore error "session started in background" */
+ if( rc == ERROR_SMG_START_IN_BACKGROUND )
+ rc = NO_ERROR;
+
+
+ if(envs)
+ _tfree(envs);
+ if(args)
+ _tfree(args);
+
+ if( rc != NO_ERROR )
+ return osl_Process_E_Unknown;
+
+ } /* else */
+
+
+ /* restore current disk */
+ if(nCurrentDisk)
+ {
+ DosSetDefaultDisk(nCurrentDisk);
+ }
+
+ /* restore current drive information */
+ if(*currentDir)
+ {
+ DosSetCurrentDir((PCSZ)currentDir);
+ }
+
+ /* allocate intern process structure and store child process ID */
+ pProcImpl = (oslProcessImpl*)malloc(sizeof(oslProcessImpl));
+ pProcImpl->pProcess = pidProcess;
+ pProcImpl->nSessionID = ulSessID;
+
+ pProcImpl->bResultCodeValid = FALSE;
+
+ if( Options & osl_Process_WAIT )
+ osl_joinProcess(pProcImpl);
+
+ *pProcess = (oslProcess)pProcImpl;
+
+ if( rc == NO_ERROR )
+ return osl_Process_E_None;
+ else
+
+ return osl_Process_E_Unknown;
+}
+
+/*----------------------------------------------------------------------------*/
+
+oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
+{
+ if (Process == NULL)
+ return osl_Process_E_Unknown;
+
+ /* Stop the session */
+ DosStopSession( STOP_SESSION_SPECIFIED, ((oslProcessImpl*)Process)->nSessionID );
+
+ return osl_Process_E_None;
+}
+
+/*----------------------------------------------------------------------------*/
+
+oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
+{
+ HANDLE hProcess;
+ oslProcessImpl* pProcImpl;
+
+ /* check, if given PID is a valid process */
+ if (FALSE)
+ {
+ pProcImpl = (oslProcessImpl*)malloc(sizeof(oslProcessImpl));
+/*
+ pProcImpl->pProcess = pidProcess;
+ pProcImpl->nSessionID = ulSessID;
+*/
+ }
+ else
+ pProcImpl = NULL;
+
+ return (pProcImpl);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void SAL_CALL osl_freeProcessHandle(oslProcess Process)
+{
+ /* free intern process structure */
+ if (Process != NULL)
+ free((oslProcessImpl*)Process);
+}
+
+/*----------------------------------------------------------------------------*/
+
+oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
+{
+ oslProcessImpl* pProcImpl = (oslProcessImpl*) Process;
+ APIRET rc;
+
+ if (Process == NULL)
+ return osl_Process_E_Unknown;
+
+ /* process of same session ? */
+ if( pProcImpl->nSessionID == 0 )
+ {
+ RESULTCODES resultCode;
+ PID pidEnded;
+
+ rc = DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &resultCode,
+ &pidEnded, pProcImpl->pProcess );
+
+ if( rc == NO_ERROR )
+ {
+ pProcImpl->nResultCode = resultCode.codeResult;
+ pProcImpl->bResultCodeValid = TRUE;
+
+ return osl_Process_E_None;
+ }
+ }
+ else
+ {
+ ULONG pcbData, ulElement = 0;
+ REQUESTDATA rdData;
+ BYTE bPriority;
+ struct {
+ USHORT SessionID;
+ USHORT ReturnValue;
+ } *pvBuffer;
+
+ /* search/wait for the correct entry in termination queue */
+ while( ( rc = DosPeekQueue( SessionTermQueue, &rdData, &pcbData,
+ (PPVOID) &pvBuffer, &ulElement, DCWW_WAIT,
+ &bPriority, NULLHANDLE )) == NO_ERROR )
+ {
+
+ if( pvBuffer->SessionID == pProcImpl->nSessionID )
+ {
+ pProcImpl->nResultCode = pvBuffer->ReturnValue;
+ pProcImpl->bResultCodeValid = TRUE;
+
+ /* remove item from queue */
+ rc = DosReadQueue( SessionTermQueue, &rdData, &pcbData,
+ (PPVOID)&pvBuffer, ulElement, DCWW_WAIT,
+ &bPriority, NULLHANDLE );
+
+ if( rc == NO_ERROR )
+ return osl_Process_E_None;
+ else
+ return osl_Process_E_Unknown;
+ }
+ } /* while */
+ }
+ return osl_Process_E_Unknown;
+}
+
+/***************************************************************************/
+
+//YD FIXME incomplete!
+oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
+{
+ return osl_joinProcess( Process);
+}
+
+/*----------------------------------------------------------------------------*/
+
+oslProcessError SAL_CALL osl_getCommandArgs( sal_Char* pszBuffer, sal_uInt32 Max)
+{
+
+ static int CmdLen = -1;
+ static sal_Char CmdLine[_MAX_CMD];
+
+ OSL_ASSERT(pszBuffer);
+ OSL_ASSERT(Max > 1);
+
+ /* Query commandline during first call of function only */
+ if (CmdLen < 0)
+ {
+ sal_Bool bEscaped = sal_False;
+ sal_Bool bSeparated = sal_True;
+ sal_Char* pszBufferOrg = pszBuffer;
+ sal_Char* pszCmdLine;
+
+ /* get pointer to commandline */
+ {
+ PTIB pptib = NULL;
+ PPIB pppib = NULL;
+
+ DosGetInfoBlocks(&pptib, &pppib);
+ pszCmdLine = pppib->pib_pchcmd;
+ }
+
+ /* skip first string */
+ while( *pszCmdLine )
+ pszCmdLine++;
+
+ /* concatenate commandline arguments for the given string */
+ Max -= 2;
+ while ( !((*pszCmdLine == '\0') && (*(pszCmdLine + 1) == '\0')) && (Max > 0))
+ {
+ /*
+ * C-Runtime expects char to be unsigned and so to be
+ * preceeded with 00 instead of FF when converting to int
+ */
+ int n = *((unsigned char *) pszCmdLine);
+ if (! (isspace(n) || (*pszCmdLine == '\0')) )
+ {
+ if (*pszCmdLine == '"')
+ {
+ if (*(pszCmdLine + 1) != '"')
+ bEscaped = ! bEscaped;
+ else
+ {
+ pszCmdLine++;
+ *pszBuffer++ = *pszCmdLine;
+ Max--;
+ }
+ }
+ else
+ {
+ *pszBuffer++ = *pszCmdLine;
+ Max--;
+ }
+ bSeparated = sal_False;
+ }
+ else
+ {
+ if (bEscaped)
+ *pszBuffer++ = *pszCmdLine;
+ else
+ if (! bSeparated)
+ {
+ *pszBuffer++ = '\0';
+ bSeparated = sal_True;
+ }
+ Max--;
+ }
+
+ pszCmdLine++;
+ }
+
+ *pszBuffer++ = '\0';
+ *pszBuffer++ = '\0';
+
+ /* restore pointer and save commandline for next query */
+ CmdLen = pszBuffer - pszBufferOrg;
+ pszBuffer = pszBufferOrg;
+ memcpy( CmdLine, pszBuffer, CmdLen );
+ }
+ else
+ memcpy( pszBuffer, CmdLine, CmdLen );
+
+ OSL_TRACE( "osl_getCommandArgs (args: %s)\n", pszBuffer );
+
+ return osl_Process_E_None;
+}
+
+/*----------------------------------------------------------------------------*/
+
+oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields,
+ oslProcessInfo* pInfo)
+{
+ if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
+ return osl_Process_E_Unknown;
+
+ pInfo->Fields = 0;
+
+ if (Fields & osl_Process_IDENTIFIER)
+ {
+ if( Process == NULL )
+ {
+ PTIB pptib = NULL;
+ PPIB pppib = NULL;
+
+ DosGetInfoBlocks( &pptib, &pppib );
+ pInfo->Ident = pppib->pib_ulpid;
+ }
+ else
+ pInfo->Ident = ((oslProcessImpl*)Process)->pProcess;
+
+ pInfo->Fields |= osl_Process_IDENTIFIER;
+ }
+
+ if (Fields & osl_Process_EXITCODE)
+ {
+ oslProcessImpl* pProcImpl = (oslProcessImpl*) Process;
+
+ if( pProcImpl->bResultCodeValid )
+ {
+ pInfo->Code = pProcImpl->nResultCode;
+ pInfo->Fields |= osl_Process_EXITCODE;
+ }
+ else
+ {
+ APIRET rc;
+
+ if( pProcImpl->nSessionID == 0 )
+ {
+ RESULTCODES resultCode;
+ PID pidEnded;
+
+ rc = DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &resultCode,
+ &pidEnded, pProcImpl->pProcess );
+
+ if( rc == NO_ERROR )
+ {
+ pProcImpl->nResultCode = resultCode.codeResult;
+ pProcImpl->bResultCodeValid = TRUE;
+
+ pInfo->Code = pProcImpl->nResultCode;
+ pInfo->Fields |= osl_Process_EXITCODE;
+
+ return osl_Process_E_None;
+ }
+ }
+ else
+ {
+ ULONG pcbData, ulElement = 0;
+ REQUESTDATA rdData;
+ BYTE bPriority;
+ struct {
+ USHORT SessionID;
+ USHORT ReturnValue;
+ } *pvBuffer;
+
+ /* search/wait for the correct entry in termination queue */
+ while( ( rc = DosPeekQueue( SessionTermQueue, &rdData, &pcbData,
+ (PPVOID) &pvBuffer, &ulElement, DCWW_WAIT,
+ &bPriority, NULLHANDLE )) == NO_ERROR )
+ {
+
+ if( pvBuffer->SessionID == pProcImpl->nSessionID )
+ {
+ pProcImpl->nResultCode = pvBuffer->ReturnValue;
+ pProcImpl->bResultCodeValid = TRUE;
+
+ pInfo->Code = pProcImpl->nResultCode;
+ pInfo->Fields |= osl_Process_EXITCODE;
+
+ /* remove item from queue */
+ rc = DosReadQueue( SessionTermQueue, &rdData, &pcbData,
+ (PPVOID)&pvBuffer, ulElement, DCWW_WAIT,
+ &bPriority, NULLHANDLE );
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (Fields & osl_Process_HEAPUSAGE)
+ {
+ }
+ if (Fields & osl_Process_CPUTIMES)
+ {
+ }
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+}
diff --git a/sal/osl/os2/process_impl.cxx b/sal/osl/os2/process_impl.cxx
new file mode 100644
index 000000000000..27b12bbe0f6a
--- /dev/null
+++ b/sal/osl/os2/process_impl.cxx
@@ -0,0 +1,371 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#define INCL_DOS
+#include <os2.h>
+
+#include "osl/process.h"
+#include <osl/mutex.h>
+
+#ifndef INCLUDED_LIMITS_H
+#include <limits.h>
+#define INCLUDED_LIMITS_H
+#endif
+
+#ifndef INCLUDED_PTHREAD_H
+#include <pthread.h>
+#define INCLUDED_PTHREAD_H
+#endif
+
+#ifndef INCLUDED_STDLIB_H
+#include <stdlib.h>
+#define INCLUDED_STDLIB_H
+#endif
+
+#ifndef INCLUDED_STRING_H
+#include <string.h>
+#define INCLUDED_STRING_H
+#endif
+#include "osl/diagnose.h"
+#include <osl/file.h>
+#include "osl/module.h"
+#include "osl/thread.h"
+#include "rtl/ustring.hxx"
+
+#ifndef _OSL_FILE_PATH_HELPER_H_
+#include "file_path_helper.h"
+#endif
+
+#ifndef _OSL_UUNXAPI_H_
+#include "uunxapi.h"
+#endif
+
+/***************************************
+ osl_bootstrap_getExecutableFile_Impl().
+
+ @internal
+ @see rtl_bootstrap
+ @see #i37371#
+
+ **************************************/
+
+extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
+ rtl_uString ** ppFileURL
+) SAL_THROW_EXTERN_C();
+
+
+oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
+ rtl_uString ** ppFileURL
+) SAL_THROW_EXTERN_C()
+{
+ oslProcessError result = osl_Process_E_NotFound;
+ CHAR szName[CCHMAXPATH];
+ PPIB ppib;
+ PTIB ptib;
+ APIRET rc;
+
+ rc = DosGetInfoBlocks(&ptib, &ppib);
+ rc = DosQueryModuleName(ppib->pib_hmte, sizeof(szName), szName);
+
+ if (rc == 0)
+ {
+ rtl_uString * pAbsPath = 0;
+
+ rtl_string2UString(
+ &pAbsPath,
+ szName, strlen(szName), osl_getThreadTextEncoding(),
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+
+ if (pAbsPath)
+ {
+ /* Convert from path to url. */
+ if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
+ {
+ /* Success. */
+ result = osl_Process_E_None;
+ }
+ rtl_uString_release (pAbsPath);
+ }
+ }
+
+ return (result);
+}
+
+/***************************************
+ CommandArgs_Impl.
+ **************************************/
+struct CommandArgs_Impl
+{
+ oslMutex m_mutex;
+ sal_uInt32 m_nCount;
+ rtl_uString ** m_ppArgs;
+};
+
+static struct CommandArgs_Impl g_command_args =
+{
+ osl_createMutex(),
+ 0,
+ 0
+};
+
+/***************************************
+ osl_getExecutableFile().
+ **************************************/
+oslProcessError SAL_CALL osl_getExecutableFile (rtl_uString ** ppustrFile)
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ osl_acquireMutex(g_command_args.m_mutex);
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > 0)
+ {
+ /* CommandArgs set. Obtain argv[0]. */
+ rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
+ result = osl_Process_E_None;
+ }
+ osl_releaseMutex(g_command_args.m_mutex);
+
+ return (result);
+}
+
+/***************************************
+ osl_getCommandArgCount().
+ **************************************/
+sal_uInt32 SAL_CALL osl_getCommandArgCount (void)
+{
+ sal_uInt32 result = 0;
+
+ osl_acquireMutex(g_command_args.m_mutex);
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > 0)
+ result = g_command_args.m_nCount - 1;
+ osl_releaseMutex(g_command_args.m_mutex);
+
+ return (result);
+}
+
+/***************************************
+ osl_getCommandArg().
+ **************************************/
+oslProcessError SAL_CALL osl_getCommandArg (sal_uInt32 nArg, rtl_uString ** strCommandArg)
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ osl_acquireMutex(g_command_args.m_mutex);
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > (nArg + 1))
+ {
+ rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
+ result = osl_Process_E_None;
+ }
+ osl_releaseMutex(g_command_args.m_mutex);
+
+ return (result);
+}
+
+/***************************************
+ osl_setCommandArgs().
+ **************************************/
+void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
+{
+ OSL_ASSERT(argc > 0);
+ osl_acquireMutex(g_command_args.m_mutex);
+ OSL_ENSURE (g_command_args.m_nCount == 0, "osl_setCommandArgs(): CommandArgs already set.");
+ if (g_command_args.m_nCount == 0)
+ {
+ rtl_uString** ppArgs = (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
+ if (ppArgs != 0)
+ {
+ rtl_TextEncoding encoding = osl_getThreadTextEncoding();
+ for (int i = 0; i < argc; i++)
+ {
+ rtl_string2UString (
+ &(ppArgs[i]),
+ argv[i], rtl_str_getLength (argv[i]), encoding,
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+ }
+ if (ppArgs[0] != 0)
+ {
+ /* see @ osl_getExecutableFile(). */
+ if (rtl_ustr_indexOfChar (rtl_uString_getStr(ppArgs[0]), sal_Unicode('/')) == -1)
+ {
+ const rtl::OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH"));
+
+ rtl_uString * pSearchPath = 0;
+ osl_getEnvironment (PATH.pData, &pSearchPath);
+ if (pSearchPath)
+ {
+ rtl_uString * pSearchResult = 0;
+ osl_searchPath (ppArgs[0], pSearchPath, &pSearchResult);
+ if (pSearchResult)
+ {
+ rtl_uString_assign (&(ppArgs[0]), pSearchResult);
+ rtl_uString_release (pSearchResult);
+ }
+ rtl_uString_release (pSearchPath);
+ }
+ }
+
+ rtl_uString * pArg0 = 0;
+ if (realpath_u (ppArgs[0], &pArg0))
+ {
+ osl_getFileURLFromSystemPath (pArg0, &(ppArgs[0]));
+ rtl_uString_release (pArg0);
+ }
+ }
+ g_command_args.m_nCount = argc;
+ g_command_args.m_ppArgs = ppArgs;
+ }
+ }
+ osl_releaseMutex(g_command_args.m_mutex);
+
+}
+
+/***************************************
+ osl_getEnvironment().
+ **************************************/
+oslProcessError SAL_CALL osl_getEnvironment(rtl_uString* pustrEnvVar, rtl_uString** ppustrValue)
+{
+ oslProcessError result = osl_Process_E_NotFound;
+ rtl_TextEncoding encoding = osl_getThreadTextEncoding();
+ rtl_String* pstr_env_var = 0;
+
+ OSL_PRECOND(pustrEnvVar, "osl_getEnvironment(): Invalid parameter");
+ OSL_PRECOND(ppustrValue, "osl_getEnvironment(): Invalid parameter");
+
+ rtl_uString2String(
+ &pstr_env_var,
+ rtl_uString_getStr(pustrEnvVar), rtl_uString_getLength(pustrEnvVar), encoding,
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+ if (pstr_env_var != 0)
+ {
+ const char* p_env_var = getenv (rtl_string_getStr (pstr_env_var));
+ if (p_env_var != 0)
+ {
+ rtl_string2UString(
+ ppustrValue,
+ p_env_var, strlen(p_env_var), encoding,
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(*ppustrValue != NULL);
+
+ result = osl_Process_E_None;
+ }
+ rtl_string_release(pstr_env_var);
+ }
+
+ return (result);
+}
+
+/***************************************
+ osl_getProcessWorkingDir().
+ **************************************/
+oslProcessError SAL_CALL osl_getProcessWorkingDir(rtl_uString **ppustrWorkingDir)
+{
+ oslProcessError result = osl_Process_E_Unknown;
+ char buffer[PATH_MAX];
+
+ OSL_PRECOND(ppustrWorkingDir, "osl_getProcessWorkingDir(): Invalid parameter");
+
+ if (getcwd (buffer, sizeof(buffer)) != 0)
+ {
+ rtl_uString* ustrTmp = 0;
+
+ rtl_string2UString(
+ &ustrTmp,
+ buffer, strlen(buffer), osl_getThreadTextEncoding(),
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+ if (ustrTmp != 0)
+ {
+ if (osl_getFileURLFromSystemPath (ustrTmp, ppustrWorkingDir) == osl_File_E_None)
+ result = osl_Process_E_None;
+ rtl_uString_release (ustrTmp);
+ }
+ }
+
+ return (result);
+}
+
+/******************************************************************************
+ *
+ * new functions to set/return the current process locale
+ *
+ *****************************************************************************/
+
+struct ProcessLocale_Impl
+{
+ oslMutex m_mutex;
+ rtl_Locale * m_pLocale;
+};
+
+static struct ProcessLocale_Impl g_process_locale =
+{
+ osl_createMutex(),
+ 0
+};
+
+extern "C" void _imp_getProcessLocale( rtl_Locale ** );
+extern "C" int _imp_setProcessLocale( rtl_Locale * );
+
+/**********************************************
+ osl_getProcessLocale().
+ *********************************************/
+oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ OSL_PRECOND(ppLocale, "osl_getProcessLocale(): Invalid parameter.");
+
+ osl_acquireMutex(g_process_locale.m_mutex);
+
+ if (g_process_locale.m_pLocale == 0)
+ _imp_getProcessLocale (&(g_process_locale.m_pLocale));
+ *ppLocale = g_process_locale.m_pLocale;
+
+ osl_releaseMutex(g_process_locale.m_mutex);
+
+ return (osl_Process_E_None);
+}
+
+/**********************************************
+ osl_setProcessLocale().
+ *********************************************/
+oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
+{
+ oslProcessError result = osl_Process_E_Unknown;
+
+ OSL_PRECOND(pLocale, "osl_setProcessLocale(): Invalid parameter.");
+
+ osl_acquireMutex(g_process_locale.m_mutex);
+ if (_imp_setProcessLocale (pLocale) == 0)
+ {
+ g_process_locale.m_pLocale = pLocale;
+ result = osl_Process_E_None;
+ }
+ osl_releaseMutex(g_process_locale.m_mutex);
+
+ return (result);
+}
+
diff --git a/sal/osl/os2/procimpl.h b/sal/osl/os2/procimpl.h
new file mode 100644
index 000000000000..5ff7a9f36b91
--- /dev/null
+++ b/sal/osl/os2/procimpl.h
@@ -0,0 +1,52 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_PROCIMPL_H_
+#define _OSL_PROCIMPL_H_
+
+
+#include <osl/process.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _oslProcessImpl {
+
+ PID pProcess;
+ sal_uInt32 nSessionID;
+ sal_uInt32 nResultCode;
+ BOOL bResultCodeValid;
+} oslProcessImpl;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/sal/osl/os2/profile.c b/sal/osl/os2/profile.c
new file mode 100644
index 000000000000..d9d166d0e091
--- /dev/null
+++ b/sal/osl/os2/profile.c
@@ -0,0 +1,2295 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+// YD #define min(a,b) (((a) < (b)) ? (a) : (b))
+
+#include <osl/security.h>
+#include <osl/diagnose.h>
+#include <osl/profile.h>
+#include <osl/process.h>
+#include <osl/thread.h>
+#include <osl/file.h>
+
+#define LINES_INI 32
+#define LINES_ADD 10
+#define SECTIONS_INI 5
+#define SECTIONS_ADD 3
+#define ENTRIES_INI 5
+#define ENTRIES_ADD 3
+
+
+#define STR_INI_EXTENSION ".ini"
+#define STR_INI_METAHOME "?~"
+#define STR_INI_METASYS "?$"
+#define STR_INI_METACFG "?^"
+#define STR_INI_METAINS "?#"
+
+#define STR_INI_BOOLYES "yes"
+#define STR_INI_BOOLON "on"
+#define STR_INI_BOOLONE "1"
+#define STR_INI_BOOLNO "no"
+#define STR_INI_BOOLOFF "off"
+#define STR_INI_BOOLZERO "0"
+
+#define FLG_USER 0x00FF
+#define FLG_AUTOOPEN 0x0100
+#define FLG_MODIFIED 0x0200
+
+#define SVERSION_LOCATION STR_INI_METACFG
+#define SVERSION_FALLBACK STR_INI_METASYS
+#define SVERSION_NAME "sversion"
+#define SVERSION_SECTION "Versions"
+#define SVERSION_SOFFICE "StarOffice"
+#define SVERSION_PROFILE "soffice.ini"
+#define SVERSION_OPTION "userid:"
+#define SVERSION_DIRS { "bin", "program" }
+#define SVERSION_USER "user"
+
+#define _BUILD_STR_(n) # n
+#define BUILD_STR(n) _BUILD_STR_(n)
+
+/* implemented in file.c */
+extern oslFileError FileURLToPath( char *, size_t, rtl_uString* );
+
+/*****************************************************************************/
+/* Data Type Definition */
+/*****************************************************************************/
+
+typedef struct _osl_TStamp
+{
+ FDATE m_Date;
+ FTIME m_Time;
+} osl_TStamp;
+
+typedef enum _osl_TLockMode
+{
+ un_lock, read_lock, write_lock
+} osl_TLockMode;
+
+typedef struct _osl_TFile
+{
+ HFILE m_Handle;
+/*
+ sal_Char* m_pReadPtr;
+ sal_Char m_ReadBuf[512];
+ sal_Char* m_pWritePtr;
+ sal_Char m_WriteBuf[512];
+*/
+ sal_Char* m_pReadPtr;
+ sal_Char m_ReadBuf[512];
+/* sal_Char* m_pWritePtr; */
+/* sal_Char m_WriteBuf[512]; */
+ sal_Char* m_pWriteBuf;
+ sal_uInt32 m_nWriteBufLen;
+ sal_uInt32 m_nWriteBufFree;
+} osl_TFile;
+
+typedef struct _osl_TProfileEntry
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+} osl_TProfileEntry;
+
+typedef struct _osl_TProfileSection
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+ sal_uInt32 m_NoEntries;
+ sal_uInt32 m_MaxEntries;
+ osl_TProfileEntry* m_Entries;
+} osl_TProfileSection;
+
+
+/*
+ Profile-data structure hidden behind oslProfile:
+*/
+typedef struct _osl_TProfileImpl
+{
+ sal_uInt32 m_Flags;
+ osl_TFile* m_pFile;
+ osl_TStamp m_Stamp;
+ //sal_Char m_Filename[_MAX_PATH + 1];
+ sal_uInt32 m_NoLines;
+ sal_uInt32 m_MaxLines;
+ sal_uInt32 m_NoSections;
+ sal_uInt32 m_MaxSections;
+ sal_Char** m_Lines;
+ rtl_uString *m_strFileName;
+ osl_TProfileSection* m_Sections;
+ HINI m_hIni;
+} osl_TProfileImpl;
+
+
+/*****************************************************************************/
+/* Static Module Function Declarations */
+/*****************************************************************************/
+
+//static osl_TFile* openFile(rtl_uString* pszFilename, sal_Bool bWriteable);
+//static osl_TStamp closeFile(osl_TFile* pFile);
+static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags );
+static osl_TStamp closeFileImpl(osl_TFile* pFile);
+static sal_Bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
+static sal_Bool rewindFile(osl_TFile* pFile, sal_Bool bTruncate);
+static osl_TStamp getFileStamp(osl_TFile* pFile);
+
+static sal_Bool getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen);
+static sal_Bool putLine(osl_TFile* pFile, const sal_Char *pszLine);
+static const sal_Char* stripBlanks(const sal_Char* String, sal_uInt32* pLen);
+static const sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line);
+static const sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo);
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ const sal_Char* Entry, sal_uInt32 Len);
+static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, const sal_Char* Entry, sal_uInt32 Len);
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
+static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len);
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
+ const sal_Char* Entry, sal_uInt32 *pNoEntry);
+static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
+static sal_Bool storeProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile, sal_Bool bCleanup);
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable);
+static sal_Bool releaseProfile(osl_TProfileImpl* pProfile);
+static sal_Bool lookupProfile(const sal_Char *pszPath, const sal_Char *pszFile, sal_Char *pPath);
+
+
+static sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName);
+
+sal_Bool SAL_CALL osl_getFullPath(rtl_uString* pszFilename, sal_Char* pszPath, sal_uInt32 MaxLen)
+{
+ return NO_ERROR == DosQueryPathInfo( (PCSZ)pszFilename, FIL_QUERYFULLNAME, pszPath, MaxLen);
+}
+
+
+
+/*****************************************************************************/
+/* Exported Module Functions */
+/*****************************************************************************/
+
+oslProfile SAL_CALL osl_openProfile(rtl_uString *strProfileName, sal_uInt32 Flags)
+{
+ osl_TFile* pFile;
+ osl_TProfileImpl* pProfile;
+ rtl_uString *FileName=NULL;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_openProfile\n");
+#endif
+ OSL_VERIFY(strProfileName);
+
+/* if (rtl_uString_getLength(strProfileName) == 0 )
+ {
+ OSL_VERIFY(osl_getProfileName(NULL, NULL, &FileName));
+ }
+ else
+*/
+ {
+ rtl_uString_assign(&FileName, strProfileName);
+ }
+
+ osl_getSystemPathFromFileURL(FileName, &FileName);
+
+#ifdef DEBUG_OSL_PROFILE
+ Flags=osl_Profile_FLUSHWRITE;
+
+ // OSL_TRACE("opening '%s'\n",FileName);
+ if ( Flags == osl_Profile_DEFAULT )
+ {
+ OSL_TRACE("with osl_Profile_DEFAULT \n");
+ }
+ if ( Flags & osl_Profile_SYSTEM )
+ {
+ OSL_TRACE("with osl_Profile_SYSTEM \n");
+ }
+ if ( Flags & osl_Profile_READLOCK )
+ {
+ OSL_TRACE("with osl_Profile_READLOCK \n");
+ }
+ if ( Flags & osl_Profile_WRITELOCK )
+ {
+ OSL_TRACE("with osl_Profile_WRITELOCK \n");
+ }
+/* if ( Flags & osl_Profile_READWRITE ) */
+/* { */
+/* OSL_TRACE("with osl_Profile_READWRITE \n"); */
+/* } */
+ if ( Flags & osl_Profile_FLUSHWRITE )
+ {
+ OSL_TRACE("with osl_Profile_FLUSHWRITE \n");
+ }
+#endif
+
+ if ((! (Flags & osl_Profile_SYSTEM)) &&
+ ((pFile = openFileImpl(FileName, (Flags & osl_Profile_WRITELOCK) ? sal_True : sal_False)) == NULL))
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_openProfile [not opened]\n");
+#endif
+ if( FileName)
+ rtl_uString_release( FileName);
+
+ return (NULL);
+ }
+
+ pProfile = (osl_TProfileImpl*)calloc(1, sizeof(osl_TProfileImpl));
+
+ pProfile->m_Flags = Flags & FLG_USER;
+ osl_getSystemPathFromFileURL(strProfileName, &pProfile->m_strFileName);
+// rtl_uString_assign(&pProfile->m_strFileName, strProfileName);
+
+ if (Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK))
+ pProfile->m_pFile = pFile;
+
+ pProfile->m_Stamp = getFileStamp(pFile);
+
+ loadProfile(pFile, pProfile);
+
+ if (pProfile->m_pFile == NULL)
+ closeFileImpl(pFile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_openProfile [ok]\n");
+#endif
+ if( FileName)
+ rtl_uString_release( FileName);
+
+ return pProfile;
+}
+
+sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_closeProfile\n");
+#endif
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [profile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ pProfile = acquireProfile(Profile,sal_True);
+
+ if ( pProfile != 0 )
+ {
+ if ( !( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
+ {
+/* if (pProfile->m_pFile == NULL) */
+/* pProfile->m_pFile = openFileImpl(pProfile->m_Filename, sal_True); */
+
+ storeProfile(pProfile->m_pFile, pProfile, sal_False);
+ }
+ }
+ else
+ {
+ pProfile = acquireProfile(Profile,sal_False);
+ }
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [pProfile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (pProfile->m_pFile != NULL)
+ closeFileImpl(pProfile->m_pFile);
+ }
+
+ pProfile->m_pFile = NULL;
+ rtl_uString_release(pProfile->m_strFileName);
+ pProfile->m_strFileName = NULL;
+
+ /* release whole profile data types memory */
+ if ( pProfile->m_NoLines > 0)
+ {
+ unsigned int index=0;
+ if ( pProfile->m_Lines != 0 )
+ {
+ for ( index = 0 ; index < pProfile->m_NoLines ; ++index)
+ {
+ if ( pProfile->m_Lines[index] != 0 )
+ {
+ free(pProfile->m_Lines[index]);
+ }
+ }
+ free(pProfile->m_Lines);
+ }
+ if ( pProfile->m_Sections != 0 )
+ {
+ /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
+ for ( index = 0 ; index < pProfile->m_NoSections ; ++index )
+ {
+ if ( pProfile->m_Sections[index].m_Entries != 0 )
+ {
+ free(pProfile->m_Sections[index].m_Entries);
+ }
+ }
+ free(pProfile->m_Sections);
+ }
+
+ }
+ free(pProfile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*) Profile;
+ osl_TFile* pFile;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_flushProfile()\n");
+#endif
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [pProfile == 0]\n");
+#endif
+ return sal_False;
+ }
+
+ pFile = pProfile->m_pFile;
+ if ( !( pFile != 0 && pFile->m_Handle >= 0 ) )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [invalid file]\n");
+#endif
+ return sal_False;
+ }
+
+ if ( pProfile->m_Flags & FLG_MODIFIED )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("swapping to storeprofile\n");
+#endif
+ bRet = storeProfile(pFile,pProfile,sal_False);
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [ok]\n");
+#endif
+ return bRet;
+}
+
+sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Char* pszString, sal_uInt32 MaxLen,
+ const sal_Char* pszDefault)
+{
+ sal_uInt32 NoEntry;
+ const sal_Char* pStr = 0;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileString\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [pProfile==0]\n");
+#endif
+
+
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
+ (NoEntry < pSec->m_NoEntries) &&
+ ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
+ '=')) != NULL))
+ pStr++;
+ else
+ pStr = pszDefault;
+
+ if ( pStr != 0 )
+ {
+ pStr = stripBlanks(pStr, NULL);
+ MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
+ pStr = stripBlanks(pStr, &MaxLen);
+ strncpy(pszString, pStr, MaxLen);
+ pszString[MaxLen] = '\0';
+ }
+ }
+ else
+ PrfQueryProfileString(pProfile->m_hIni, (PCSZ)pszSection,
+ (PCSZ)pszEntry, (PCSZ)pszDefault,
+ pszString, MaxLen);
+
+ releaseProfile(pProfile);
+
+ if ( pStr == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [pStr==0]\n");
+#endif
+
+
+ return (sal_False);
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [ok]\n");
+#endif
+
+ return (sal_True);
+}
+
+
+sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Bool Default)
+{
+ sal_Char Line[32];
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileBool\n");
+#endif
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ if ((stricmp(Line, STR_INI_BOOLYES) == 0) ||
+ (stricmp(Line, STR_INI_BOOLON) == 0) ||
+ (stricmp(Line, STR_INI_BOOLONE) == 0))
+ Default = sal_True;
+ else
+ if ((stricmp(Line, STR_INI_BOOLNO) == 0) ||
+ (stricmp(Line, STR_INI_BOOLOFF) == 0) ||
+ (stricmp(Line, STR_INI_BOOLZERO) == 0))
+ Default = sal_False;
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileBool [ok]\n");
+#endif
+
+ return (Default);
+}
+
+
+sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_uInt32 FirstId, const sal_Char* Strings[],
+ sal_uInt32 Default)
+{
+ sal_uInt32 i;
+ sal_Char Line[256];
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileIdent\n");
+#endif
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ i = 0;
+ while (Strings[i] != NULL)
+ {
+ if (stricmp(Line, Strings[i]) == 0)
+ {
+ Default = i + FirstId;
+ break;
+ }
+ i++;
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileIdent [ok]\n");
+#endif
+ return (Default);
+}
+
+
+sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ const sal_Char* pszString)
+{
+ sal_uInt32 i;
+ sal_Bool bRet = sal_False;
+ sal_uInt32 NoEntry;
+ const sal_Char* pStr;
+ sal_Char Line[4096];
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileString\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_True);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [pProfile==0]\n");
+#endif
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == NULL)
+ {
+ Line[0] = '\0';
+ addLine(pProfile, Line);
+
+ Line[0] = '[';
+ strcpy(&Line[1], pszSection);
+ Line[1 + strlen(pszSection)] = ']';
+ Line[2 + strlen(pszSection)] = '\0';
+
+ if (((pStr = addLine(pProfile, Line)) == NULL) ||
+ (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
+ {
+ releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [not added]\n");
+#endif
+ return (sal_False);
+ }
+
+ pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
+ NoEntry = pSec->m_NoEntries;
+ }
+
+ Line[0] = '\0';
+ strcpy(&Line[0], pszEntry);
+ Line[0 + strlen(pszEntry)] = '=';
+ strcpy(&Line[1 + strlen(pszEntry)], pszString);
+
+ if (NoEntry >= pSec->m_NoEntries)
+ {
+ if (pSec->m_NoEntries > 0)
+ i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
+ else
+ i = pSec->m_Line + 1;
+
+ if (((pStr = insertLine(pProfile, Line, i)) == NULL) ||
+ (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
+ {
+ releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [not inserted]\n");
+#endif
+ return (sal_False);
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ else
+ {
+ i = pSec->m_Entries[NoEntry].m_Line;
+ free(pProfile->m_Lines[i]);
+ pProfile->m_Lines[i] = strdup(Line);
+ setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else
+ PrfWriteProfileString(pProfile->m_hIni, (PCSZ)pszSection,
+ (PCSZ)pszEntry, (PCSZ)pszString);
+
+ bRet = releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [ok]\n");
+#endif
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Bool Value)
+{
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileBool\n");
+#endif
+
+ if (Value)
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
+ else
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileBool [ok]\n");
+#endif
+
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_uInt32 FirstId, const sal_Char* Strings[],
+ sal_uInt32 Value)
+{
+ int i, n;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileIdent\n");
+#endif
+
+ for (n = 0; Strings[n] != NULL; n++);
+
+ if ((i = Value - FirstId) >= n)
+ bRet=sal_False;
+ else
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileIdent\n");
+#endif
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
+ const sal_Char *pszSection, const sal_Char *pszEntry)
+{
+ sal_uInt32 NoEntry;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_removeProfileEntry\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_True);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]\n");
+#endif
+
+
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
+ (NoEntry < pSec->m_NoEntries))
+ {
+ removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
+ removeEntry(pSec, NoEntry);
+ if (pSec->m_NoEntries == 0)
+ {
+ removeLine(pProfile, pSec->m_Line);
+
+ /* remove any empty separation line */
+ if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
+ removeLine(pProfile, pSec->m_Line - 1);
+
+ removeSection(pProfile, pSec);
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else
+ PrfWriteProfileString(pProfile->m_hIni, (PCSZ)pszSection, (PCSZ)pszEntry, NULL);
+
+ bRet = releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [ok]\n");
+#endif
+ return bRet;
+}
+
+
+sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile, const sal_Char *pszSection,
+ sal_Char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ sal_uInt32 NoEntry;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_getProfileSectionEntries\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [pProfile=0]\n");
+#endif
+
+
+ return (0);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != NULL)
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
+ n += pSec->m_Entries[i].m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ break;
+
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ n += pSec->m_Entries[i].m_Len + 1;
+
+ n += 1;
+ }
+ }
+ else
+ n = 0;
+ }
+ else
+ n = PrfQueryProfileString(pProfile->m_hIni, (PCSZ)pszSection, NULL, NULL,
+ pszBuffer, MaxLen );
+
+ releaseProfile(pProfile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [ok]\n");
+#endif
+
+ return (n);
+}
+
+sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile, sal_Char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ return (0);
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if ((n + pSec->m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
+ pSec->m_Len);
+ n += pSec->m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ break;
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ n += pProfile->m_Sections[i].m_Len + 1;
+
+ n += 1;
+ }
+ }
+ else
+ n = PrfQueryProfileString(pProfile->m_hIni, NULL, NULL, NULL,
+ pszBuffer, MaxLen );
+
+ releaseProfile(pProfile);
+
+ return (n);
+}
+
+#if 0 // YD
+sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName)
+{
+ sal_Bool bFailed;
+ sal_Char File[_MAX_PATH];
+ sal_Char Path[_MAX_PATH];
+ sal_uInt32 nFileLen;
+ sal_uInt32 nPathLen = 0;
+
+ rtl_uString * strTmp = NULL;
+ oslFileError nError;
+
+ /* build file name */
+ if (strName && strName->length)
+ {
+ if(strName->length >= _MAX_PATH)
+ return sal_False;
+
+ strcpy(File, (char*)strName->buffer);
+ nFileLen = strName->length;
+
+ if (rtl_ustr_indexOfChar( File, L'.' ) == -1)
+ {
+ if (nFileLen + strlen(STR_INI_EXTENSION) >= _MAX_PATH)
+ return sal_False;
+
+ /* add default extension */
+ strcpy(File + nFileLen, STR_INI_EXTENSION);
+ nFileLen += strlen(STR_INI_EXTENSION);
+ }
+ }
+ else
+ {
+ rtl_uString *strProgName = NULL;
+ sal_Unicode *pProgName;
+ sal_Int32 nOffset = 0;
+ sal_Int32 nLen;
+ sal_Int32 nPos;
+
+ if (osl_getExecutableFile(&strProgName) != osl_Process_E_None)
+ return sal_False;
+
+ /* remove path and extension from filename */
+ pProgName = strProgName->buffer;
+ nLen = strProgName->length ;
+
+ if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'/' )) != -1)
+ nOffset = nPos + 1;
+ else if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L':' )) != -1)
+ nOffset = nPos + 1;
+
+ if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'.' )) != -1 )
+ nLen -= 4;
+
+ if ((nFileLen = nLen - nOffset) >= _MAX_PATH)
+ return sal_False;
+
+ strncpy(File, pProgName + nOffset, nFileLen);
+
+ if (nFileLen + strlen(STR_INI_EXTENSION) >= _MAX_PATH)
+ return sal_False;
+
+ /* add default extension */
+ strcpy(File + nFileLen, STR_INI_EXTENSION);
+ nFileLen += strlen(STR_INI_EXTENSION);
+
+ rtl_uString_release( strProgName );
+ }
+
+ if (File[0] == 0)
+ return sal_False;
+
+ /* build directory path */
+ if (strPath && strPath->length)
+ {
+ sal_Unicode *pPath = rtl_uString_getStr(strPath);
+ sal_Int32 nLen = rtl_uString_getLength(strPath);
+
+ if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAHOME) , STR_INI_METAHOME) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)] == '/')))
+ {
+ rtl_uString * strHome = NULL;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getHomeDir(security, &strHome);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return (sal_False);
+
+ if (strHome->length >= _MAX_PATH)
+ return sal_False;
+
+ strcpy( Path, strHome->buffer);
+ nPathLen = strHome->length;
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METAHOME))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
+
+ if (nLen + nPathLen >= _MAX_PATH)
+ return sal_False;
+
+ strcpy(Path + nPathLen, pPath);
+ nPathLen += nLen;
+ }
+
+ rtl_uString_release(strHome);
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METACFG), STR_INI_METACFG) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METACFG)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METACFG)] == '/')))
+ {
+ rtl_uString * strConfig = NULL;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getConfigDir(security, &strConfig);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return (sal_False);
+
+ if (strConfig->length >= _MAX_PATH)
+ return sal_False;
+
+ strcpy( Path, strConfig->buffer);
+ nPathLen = strConfig->length;
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METACFG))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
+
+ if (nLen + nPathLen >= _MAX_PATH)
+ return sal_False;
+
+ strcpy(Path + nPathLen, pPath);
+ nPathLen += nLen;
+ }
+
+ rtl_uString_release(strConfig);
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METASYS), STR_INI_METASYS) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METASYS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METASYS)] == '/')))
+ {
+ if (((nPathLen = GetWindowsDirectoryW(Path, _MAX_PATH)) == 0) || (nPathLen >= _MAX_PATH))
+ return (sal_False);
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METASYS))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
+
+ if (nLen + nPathLen >= MAX_PATH)
+ return sal_False;
+
+ strcpy(Path + nPathLen, pPath);
+ nPathLen += nLen;
+ }
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAINS), STR_INI_METAINS) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAINS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '/') ||
+ (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '"') ) )
+ {
+ if (! lookupProfile(pPath + RTL_CONSTASCII_LENGTH(STR_INI_METAINS), File, Path))
+ return (sal_False);
+
+ nPathLen = strlen(Path);
+ }
+
+ else if(nLen < MAX_PATH)
+ {
+ strcpy(Path, pPath);
+ nPathLen = strlen(Path);
+ }
+ else
+ return sal_False;
+ }
+ else
+ {
+ rtl_uString * strConfigDir = NULL;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getConfigDir(security, &strConfigDir);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return (sal_False);
+ if (strConfigDir->length >= MAX_PATH)
+ return sal_False;
+
+ strcpy(Path, strConfigDir->buffer);
+ nPathLen = strConfigDir->length;
+ }
+
+ if (nPathLen && (Path[nPathLen - 1] != L'/') && (Path[nPathLen - 1] != L'\\'))
+ {
+ Path[nPathLen++] = L'\\';
+ Path[nPathLen] = 0;
+ }
+
+ if (nPathLen + nFileLen >= MAX_PATH)
+ return sal_False;
+
+ /* append file name */
+ strcpy(Path + nPathLen, File);
+ nPathLen += nFileLen;
+
+ /* copy filename */
+ rtl_uString_newFromStr_WithLength(&strTmp, Path, nPathLen);
+ nError = osl_getFileURLFromSystemPath(strTmp, strProfileName);
+ rtl_uString_release(strTmp);
+
+ return nError == osl_File_E_None;
+}
+#endif // 0 // YD
+
+
+/*****************************************************************************/
+/* Static Module Functions */
+/*****************************************************************************/
+
+static osl_TStamp getFileStamp(osl_TFile* pFile)
+{
+ osl_TStamp FileTime;
+ FILESTATUS3 FileStatus;
+ sal_uInt32 Bytes;
+
+ Bytes = sizeof( FILESTATUS3 );
+ if ( (!pFile->m_Handle) ||
+ DosQueryFileInfo(pFile->m_Handle, FIL_STANDARD, &FileStatus, Bytes))
+ memset(&FileTime, 0, sizeof(FileTime));
+ else
+ {
+ FileTime.m_Date = FileStatus.fdateLastWrite;
+ FileTime.m_Time = FileStatus.ftimeLastWrite;
+ }
+
+ return (FileTime);
+}
+
+static sal_Bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
+{
+ sal_uInt32 status = 1;
+ FILELOCK Lock;
+
+ if (!pFile->m_Handle)
+ return (sal_False);
+
+ Lock.lOffset = 0;
+ Lock.lRange = 0xFFFFFFFF;
+
+ switch (eMode)
+ {
+ case un_lock:
+ status = DosSetFileLocks(pFile->m_Handle, &Lock, NULL, 1000, 0);
+ break;
+
+ case read_lock:
+ status = DosSetFileLocks(pFile->m_Handle, NULL, &Lock, 1000, 1);
+ break;
+
+ case write_lock:
+ status = DosSetFileLocks(pFile->m_Handle, NULL, &Lock, 1000, 0);
+ break;
+ }
+
+ return (status == 0);
+}
+
+//static osl_TFile* openFile(rtl_uString* pszFilename, sal_Bool bWriteable)
+static osl_TFile* openFileImpl(rtl_uString *ustrFileName, oslProfileOption ProfileFlags )
+{
+ sal_uInt32 action;
+ APIRET rc;
+ osl_TFile* pFile = (osl_TFile*)calloc(1, sizeof(osl_TFile));
+
+ ULONG attributes;
+ ULONG flags;
+ ULONG mode;
+ sal_Bool bWriteable = sal_False;
+ rtl_String* strFileName=0;
+ sal_Char* pszFileName=0;
+
+ /* check parameters */
+ OSL_ASSERT( ustrFileName );
+
+ rtl_uString2String( &strFileName,
+ rtl_uString_getStr(ustrFileName),
+ rtl_uString_getLength(ustrFileName),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszFileName = rtl_string_getStr(strFileName);
+
+/* if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE | osl_Profile_READWRITE ) )*/
+ if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("setting bWriteable to TRUE\n");
+#endif
+ bWriteable=sal_True;
+ }
+
+ if (bWriteable)
+ {
+ flags = FILE_NORMAL | FILE_ARCHIVED;
+ attributes = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
+ mode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE;
+ }
+ else
+ {
+ flags = FILE_NORMAL;
+ attributes = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
+ mode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY;
+ }
+
+ if (rc = DosOpen((PCSZ)pszFileName, &pFile->m_Handle, &action, 0, flags, attributes, mode, NULL))
+ {
+ if (rc == ERROR_TOO_MANY_OPEN_FILES)
+ {
+ LONG fhToAdd = 10;
+ ULONG fhOld = 0;
+ rc = DosSetRelMaxFH(&fhToAdd, &fhOld);
+ rc = DosOpen((PCSZ)pszFileName, &pFile->m_Handle, &action, 0, flags, attributes, mode, NULL);
+ }
+ }
+
+ if ( (rc != NO_ERROR) && bWriteable)
+ {
+ free(pFile);
+ rtl_string_release(strFileName);
+ return (NULL);
+ }
+
+ rtl_string_release(strFileName);
+
+ pFile->m_pWriteBuf=0;
+ pFile->m_nWriteBufFree=0;
+ pFile->m_nWriteBufLen=0;
+
+ if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("locking '%s' file\n",pszFilename);
+#endif
+
+ lockFile(pFile, bWriteable ? write_lock : read_lock);
+ }
+
+ /* mfe: new WriteBuf obsolete */
+/* pFile->m_pWritePtr = pFile->m_Buf;*/
+/* pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);*/
+
+ return (pFile);
+}
+
+//static osl_TStamp closeFile(osl_TFile* pFile)
+static osl_TStamp closeFileImpl(osl_TFile* pFile)
+{
+ osl_TStamp stamp = {0, 0};
+
+ if ( pFile == 0 )
+ {
+ return stamp;
+ }
+
+ if (pFile->m_Handle)
+ {
+ /* mfe: new WriteBuf obsolete */
+ /* we just closing the file here, DO NOT write, it has to be handled in higher levels */
+ //if (pFile->m_pWritePtr > pFile->m_WriteBuf)
+ //{
+ // sal_uInt32 Bytes;
+
+ // DosWrite(pFile->m_Handle, pFile->m_WriteBuf,
+ // pFile->m_pWritePtr - pFile->m_WriteBuf,
+ // &Bytes);
+ //}
+
+ stamp = getFileStamp(pFile);
+
+ lockFile(pFile, un_lock);
+
+ DosClose(pFile->m_Handle);
+ }
+
+ if ( pFile->m_pWriteBuf != 0 )
+ {
+ free(pFile->m_pWriteBuf);
+ }
+
+ free(pFile);
+
+ return(stamp);
+}
+
+static sal_Bool rewindFile(osl_TFile* pFile, sal_Bool bTruncate)
+{
+ if (pFile->m_Handle)
+ {
+ sal_uInt32 Position;
+
+ /* mfe: new WriteBuf obsolete */
+ /* we just closing the file here, DO NOT write, it has to be handled in higher levels */
+ /* if (pFile->m_pWritePtr > pFile->m_WriteBuf)
+ {
+ sal_uInt32 Bytes;
+
+ DosWrite(pFile->m_Handle, pFile->m_WriteBuf,
+ pFile->m_pWritePtr - pFile->m_WriteBuf,
+ &Bytes);
+
+ pFile->m_pWritePtr = pFile->m_WriteBuf;
+ } */
+
+ pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+ DosSetFilePtr(pFile->m_Handle, 0, FILE_BEGIN, &Position);
+
+ if (bTruncate)
+ DosSetFileSize(pFile->m_Handle, 0);
+ }
+
+ return (sal_True);
+}
+
+static sal_Bool getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen)
+{
+ int Free, Bytes;
+ sal_Char* pChr;
+ sal_Char* pLine = (sal_Char *)pszLine;
+ sal_uInt32 Max;
+
+ if (pFile->m_Handle == 0)
+ return (sal_False);
+
+ MaxLen -= 1;
+
+ do
+ {
+ Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
+
+ if (Bytes <= 1)
+ {
+ /* refill buffer */
+ memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
+ pFile->m_pReadPtr = pFile->m_ReadBuf;
+
+ Free = sizeof(pFile->m_ReadBuf) - Bytes;
+
+ if (DosRead(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free, &Max))
+ {
+ *pLine = '\0';
+ return (sal_False);
+ }
+
+ if (Max < Free)
+ {
+ if ((Max == 0) && (pLine == pszLine))
+ {
+ *pLine = '\0';
+ return (sal_False);
+ }
+
+ pFile->m_ReadBuf[Bytes + Max] = '\0';
+ }
+ }
+
+ for (pChr = pFile->m_pReadPtr;
+ (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
+ (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
+ pChr++);
+
+ Max = min(pChr - pFile->m_pReadPtr, MaxLen);
+ memcpy(pLine, pFile->m_pReadPtr, Max);
+ MaxLen -= Max;
+ pLine += Max;
+
+ if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
+ {
+ if (*pChr != '\0')
+ {
+ if ((pChr[0] == '\r') && (pChr[1] == '\n'))
+ pChr += 2;
+ else
+ pChr += 1;
+ }
+
+ if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
+ (*pChr == '\0'))
+ pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+ *pLine = '\0';
+
+ /* setting MaxLen to -1 indicates terminating read loop */
+ MaxLen = -1;
+ }
+
+ pFile->m_pReadPtr = pChr;
+ }
+ while (MaxLen > 0);
+
+ return (sal_True);
+}
+
+static sal_Bool putLine(osl_TFile* pFile, const sal_Char *pszLine)
+{
+ unsigned int Len = strlen(pszLine);
+
+#ifdef DEBUG_OSL_PROFILE
+ int strLen=0;
+#endif
+
+ if ( pFile == 0 || pFile->m_Handle < 0 )
+ {
+ return (sal_False);
+ }
+
+ if ( pFile->m_pWriteBuf == 0 )
+ {
+ pFile->m_pWriteBuf = (sal_Char*) malloc(Len+3);
+ pFile->m_nWriteBufLen = Len+3;
+ pFile->m_nWriteBufFree = Len+3;
+ }
+ else
+ {
+ if ( pFile->m_nWriteBufFree <= Len + 3 )
+ {
+ sal_Char* pTmp;
+
+ pTmp=(sal_Char*) realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) );
+ if ( pTmp == 0 )
+ {
+ return sal_False;
+ }
+ pFile->m_pWriteBuf = pTmp;
+ pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
+ pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
+ memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
+ }
+ }
+
+
+
+ memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
+#ifdef DEBUG_OSL_PROFILE
+ strLen = strlen(pFile->m_pWriteBuf);
+#endif
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\r';
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\n';
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 2]='\0';
+
+ pFile->m_nWriteBufFree-=Len+2;
+
+#ifdef DEBUG_OSL_PROFILE
+/* OSL_TRACE("File Buffer in _putLine '%s' '%i'(%i)\n",pFile->m_pWriteBuf,strlen(pFile->m_pWriteBuf),pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);*/
+#endif
+
+ return (sal_True);
+}
+
+/* platform specific end */
+
+static const sal_Char* stripBlanks(const sal_Char* String, sal_uInt32* pLen)
+{
+ if ( (pLen != NULL) && ( *pLen != 0 ) )
+ {
+ while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
+ (*pLen)--;
+
+ while ((*String == ' ') || (*String == '\t'))
+ {
+ String++;
+ (*pLen)--;
+ }
+ }
+ else
+ while ((*String == ' ') || (*String == '\t'))
+ String++;
+
+ return (String);
+}
+
+static const sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+ else
+ {
+ pProfile->m_MaxLines += LINES_ADD;
+ pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
+ pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return (NULL);
+ }
+
+ }
+
+ pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
+
+ return (pProfile->m_Lines[pProfile->m_NoLines - 1]);
+}
+
+static const sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+ else
+ {
+ pProfile->m_MaxLines += LINES_ADD;
+ pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
+ pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return (NULL);
+ }
+
+ }
+
+ LineNo = LineNo > pProfile->m_NoLines ? pProfile->m_NoLines : LineNo;
+
+ if (LineNo < pProfile->m_NoLines)
+ {
+ sal_uInt32 i, n;
+ osl_TProfileSection* pSec;
+
+ memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
+ (pProfile->m_NoLines - LineNo) * sizeof(sal_Char *));
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line >= LineNo)
+ pSec->m_Line++;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line >= LineNo)
+ pSec->m_Entries[n].m_Line++;
+ }
+ }
+
+ pProfile->m_NoLines++;
+
+ pProfile->m_Lines[LineNo] = strdup(Line);
+
+ return (pProfile->m_Lines[LineNo]);
+}
+
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
+{
+ if (LineNo < pProfile->m_NoLines)
+ {
+ free(pProfile->m_Lines[LineNo]);
+ if (pProfile->m_NoLines - LineNo > 1)
+ {
+ sal_uInt32 i, n;
+ osl_TProfileSection* pSec;
+
+ memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
+ (pProfile->m_NoLines - LineNo - 1) * sizeof(sal_Char *));
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line > LineNo)
+ pSec->m_Line--;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line > LineNo)
+ pSec->m_Entries[n].m_Line--;
+ }
+ }
+ else
+ {
+ pProfile->m_Lines[LineNo] = 0;
+ }
+
+ pProfile->m_NoLines--;
+ }
+
+ return;
+}
+
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ const sal_Char* Entry, sal_uInt32 Len)
+{
+ Entry = stripBlanks(Entry, &Len);
+ pSection->m_Entries[NoEntry].m_Line = Line;
+ pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
+ pSection->m_Entries[NoEntry].m_Len = Len;
+
+ return;
+}
+
+static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, const sal_Char* Entry, sal_uInt32 Len)
+{
+ if (pSection != NULL)
+ {
+ if (pSection->m_NoEntries >= pSection->m_MaxEntries)
+ {
+ if (pSection->m_Entries == NULL)
+ {
+ pSection->m_MaxEntries = ENTRIES_INI;
+ pSection->m_Entries = (osl_TProfileEntry *)malloc(
+ pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
+ }
+ else
+ {
+ pSection->m_MaxEntries += ENTRIES_ADD;
+ pSection->m_Entries = (osl_TProfileEntry *)realloc(pSection->m_Entries,
+ pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
+ }
+
+ if (pSection->m_Entries == NULL)
+ {
+ pSection->m_NoEntries = 0;
+ pSection->m_MaxEntries = 0;
+ return (sal_False);
+ }
+ }
+
+ pSection->m_NoEntries++;
+
+ Entry = stripBlanks(Entry, &Len);
+ setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
+ Entry, Len);
+
+ return (sal_True);
+ }
+
+ return (sal_False);
+}
+
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
+{
+ if (NoEntry < pSection->m_NoEntries)
+ {
+ if (pSection->m_NoEntries - NoEntry > 1)
+ memmove(&pSection->m_Entries[NoEntry],
+ &pSection->m_Entries[NoEntry + 1],
+ (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
+ pSection->m_NoEntries--;
+ }
+
+ return;
+}
+
+static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len)
+{
+ if (pProfile->m_NoSections >= pProfile->m_MaxSections)
+ {
+ if (pProfile->m_Sections == NULL)
+ {
+ pProfile->m_MaxSections = SECTIONS_INI;
+ pProfile->m_Sections = (osl_TProfileSection *)malloc(pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ }
+ else
+ {
+ pProfile->m_MaxSections += SECTIONS_ADD;
+ pProfile->m_Sections = (osl_TProfileSection *)realloc(pProfile->m_Sections,
+ pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ }
+
+ if (pProfile->m_Sections == NULL)
+ {
+ pProfile->m_NoSections = 0;
+ pProfile->m_MaxSections = 0;
+ return (sal_False);
+ }
+ }
+
+ pProfile->m_NoSections++;
+
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = NULL;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
+
+ Section = (sal_Char *)stripBlanks(Section, &Len);
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
+
+ return (sal_True);
+}
+
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
+{
+ sal_uInt32 Section;
+
+ if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
+ {
+ free (pSection->m_Entries);
+ if (pProfile->m_NoSections - Section > 1)
+ {
+ memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
+ (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
+ }
+ else
+ {
+ pSection->m_Entries = 0;
+ }
+
+ pProfile->m_NoSections--;
+ }
+
+ return;
+}
+
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
+ const sal_Char* Entry, sal_uInt32 *pNoEntry)
+{
+static sal_uInt32 Sect = 0;
+ sal_uInt32 i, n;
+ sal_uInt32 Len;
+ const sal_Char* pStr;
+ osl_TProfileSection* pSec;
+
+ Len = strlen(Section);
+ Section = (sal_Char *)stripBlanks(Section, &Len);
+
+ n = Sect;
+
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ n %= pProfile->m_NoSections;
+ pSec = &pProfile->m_Sections[n];
+ if ((Len == pSec->m_Len) &&
+ (strnicmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
+ == 0))
+ break;
+ n++;
+ }
+
+ Sect = n;
+
+ if (i < pProfile->m_NoSections)
+ {
+ Len = strlen(Entry);
+ Entry = stripBlanks(Entry, &Len);
+
+ *pNoEntry = pSec->m_NoEntries;
+
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset];
+ if ((Len == pSec->m_Entries[i].m_Len) &&
+ (strnicmp(Entry, pStr, pSec->m_Entries[i].m_Len)
+ == 0))
+ {
+ *pNoEntry = i;
+ break;
+ }
+ }
+ }
+ else
+ pSec = NULL;
+
+ return (pSec);
+}
+
+static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
+{
+ sal_uInt32 i;
+ sal_Char* pStr;
+ sal_Char* pChar;
+ sal_Char Line[1024];
+
+ pProfile->m_NoLines = 0;
+ pProfile->m_NoSections = 0;
+
+ OSL_VERIFY(rewindFile(pFile, sal_False));
+
+ while (getLine(pFile, Line, sizeof(Line)))
+ {
+ if (! addLine(pProfile, Line))
+ return (sal_False);
+ }
+
+ for (i = 0; i < pProfile->m_NoLines; i++)
+ {
+ pStr = (sal_Char *)stripBlanks(pProfile->m_Lines[i], NULL);
+
+ if ((*pStr == '\0') || (*pStr == ';'))
+ continue;
+
+ if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == NULL) ||
+ ((pChar - pStr) <= 2))
+ {
+ /* insert entry */
+
+ if (pProfile->m_NoSections < 1)
+ continue;
+
+ if ((pChar = strchr(pStr, '=')) == NULL)
+ pChar = pStr + strlen(pStr);
+
+ if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
+ i, pStr, pChar - pStr))
+ return (sal_False);
+ }
+ else
+ {
+ /* new section */
+
+ if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
+ return (sal_False);
+ }
+ }
+
+ return (sal_True);
+}
+
+static sal_Bool storeProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile, sal_Bool bCleanup)
+{
+ if (pProfile->m_Lines != NULL)
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ {
+ sal_uInt32 i;
+
+ OSL_VERIFY(rewindFile(pFile, sal_True));
+
+ for (i = 0; i < pProfile->m_NoLines; i++)
+ OSL_VERIFY(putLine(pFile, pProfile->m_Lines[i]));
+
+ pProfile->m_Flags &= ~FLG_MODIFIED;
+ }
+
+ if (bCleanup)
+ {
+ while (pProfile->m_NoLines > 0)
+ removeLine(pProfile, pProfile->m_NoLines - 1);
+
+ free(pProfile->m_Lines);
+ pProfile->m_Lines = NULL;
+ pProfile->m_MaxLines = 0;
+
+ while (pProfile->m_NoSections > 0)
+ removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
+
+ free(pProfile->m_Sections);
+ pProfile->m_Sections = NULL;
+ pProfile->m_MaxSections = 0;
+ }
+ }
+
+ return (sal_True);
+}
+
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
+ oslProfileOption PFlags=0;
+
+
+ if ( bWriteable )
+ {
+/* PFlags = osl_Profile_DEFAULT | osl_Profile_READWRITE; */
+ PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
+ }
+ else
+ {
+ PFlags = osl_Profile_DEFAULT;
+ }
+
+
+ if (pProfile == NULL)
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("AUTOOPEN MODE\n");
+#endif
+
+ if ((pProfile = (osl_TProfileImpl*)osl_openProfile(NULL, PFlags)) != NULL )
+ {
+ pProfile->m_Flags |= FLG_AUTOOPEN;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("try to acquire\n");
+#endif
+
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
+ osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
+ {
+ osl_TStamp Stamp;
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("DEFAULT MODE\n");
+#endif
+ if (! (pProfile->m_pFile = openFileImpl(pProfile->m_strFileName, pProfile->m_Flags | PFlags)))
+ return NULL;
+
+ Stamp = getFileStamp(pProfile->m_pFile);
+
+ if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
+ {
+ pProfile->m_Stamp = Stamp;
+
+ loadProfile(pProfile->m_pFile, pProfile);
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("READ/WRITELOCK MODE\n");
+#endif
+
+
+ /* A readlock file could not be written */
+ if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
+ {
+ return (NULL);
+ }
+ }
+ }
+ else
+ {
+ sal_Bool bWriteable = sal_False;
+ char pszFilename[PATH_MAX] = "";
+
+ if ( pProfile->m_strFileName != 0 && pProfile->m_strFileName->buffer[0] != 0 )
+ FileURLToPath( pszFilename, PATH_MAX, pProfile->m_strFileName );
+ /* hack: usualy you have a specific HAB, but NULL works here... */
+ pProfile->m_hIni = PrfOpenProfile(NULL, (PCSZ)pszFilename);
+ if (! pProfile->m_hIni)
+ return (NULL);
+ }
+ }
+
+ return (pProfile);
+}
+
+static sal_Bool releaseProfile(osl_TProfileImpl* pProfile)
+{
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In releaseProfile\n");
+#endif
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [profile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (pProfile->m_Flags & FLG_AUTOOPEN)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [AUTOOPEN]\n");
+#endif
+ return (osl_closeProfile((oslProfile)pProfile));
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("DEFAULT MODE\n");
+#endif
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
+ osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ storeProfile(pProfile->m_pFile, pProfile, sal_False);
+
+ closeFileImpl(pProfile->m_pFile);
+ pProfile->m_pFile = NULL;
+ }
+ }
+ }
+ else
+ PrfCloseProfile(pProfile->m_hIni);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+#if 0 // YD
+
+static sal_Bool lookupProfile(const sal_Char *pszPath, const sal_Char *pszFile, sal_Char *pPath)
+{
+ sal_Char *pChr, *pStr;
+ sal_Char Path[_MAX_PATH] = "";
+ sal_Char Product[132] = "";
+ sal_Char Buffer[1024];
+
+ if (*pszPath == '"')
+ {
+ int i = 0;
+
+ pszPath++;
+
+ while ((*pszPath != '"') && (*pszPath != '\0'))
+ Product[i++] = *pszPath++;
+
+ Product[i] = '\0';
+
+ if (*pszPath == '"')
+ pszPath++;
+
+ if ( (*pszPath == '/') || (*pszPath == '\\') )
+ {
+ pszPath++;
+ }
+ }
+ else
+ {
+ /* if we have not product identfication, do a special handling for soffice.ini */
+ if (stricmp(SVERSION_PROFILE, pszFile) == 0)
+ {
+ sal_Char Profile[_MAX_PATH];
+ sal_Char Dir[_MAX_PATH];
+ oslProfile hProfile;
+
+ /* open sversion.ini in the system directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if ((osl_getProfileName(SVERSION_FALLBACK, SVERSION_NAME, Profile, sizeof(Profile))) &&
+ (hProfile = osl_openProfile(Profile, osl_Profile_READLOCK)))
+ {
+ osl_getProfileSectionEntries(hProfile, SVERSION_SECTION,
+ Buffer, sizeof(Buffer));
+
+ for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
+ {
+ if ((strnicmp(pChr, SVERSION_SOFFICE, sizeof(SVERSION_SOFFICE) - 1) == 0) &&
+ (stricmp(Product, pChr) < 0))
+ {
+ osl_readProfileString(hProfile, SVERSION_SECTION, pChr,
+ Dir, sizeof(Dir), "");
+
+ /* check for existence of path */
+ if (access(Dir, 0) >= 0)
+ strcpy(Product, pChr);
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+
+ /* open sversion.ini in the users directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if ((strcmp(SVERSION_LOCATION, SVERSION_FALLBACK) != 0) &&
+ (osl_getProfileName(SVERSION_LOCATION, SVERSION_NAME, Profile, sizeof(Profile))) &&
+ (hProfile = osl_openProfile(Profile, osl_Profile_READLOCK)))
+ {
+ osl_getProfileSectionEntries(hProfile, SVERSION_SECTION,
+ Buffer, sizeof(Buffer));
+
+ for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
+ {
+ if ((strnicmp(pChr, SVERSION_SOFFICE, sizeof(SVERSION_SOFFICE) - 1) == 0) &&
+ (stricmp(Product, pChr) < 0))
+ {
+ osl_readProfileString(hProfile, SVERSION_SECTION, pChr,
+ Dir, sizeof(Dir), "");
+
+ /* check for existence of path */
+ if (access(Dir, 0) >= 0)
+ strcpy(Product, pChr);
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+
+ /* remove any trailing build number */
+ if ((pChr = strrchr(Product, '/')) != NULL)
+ *pChr = '\0';
+ }
+ }
+
+
+ /* if we have an userid option eg. "-userid:rh[/usr/home/rh/staroffice]",
+ this will supercede all other locations */
+ if (osl_getCommandArgs(Buffer, sizeof(Buffer)) == osl_Process_E_None)
+ {
+ sal_Char *pStart, *pEnd;
+
+ for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
+ if (((*pChr == '-') || (*pChr == '+')) &&
+ (strnicmp(pChr + 1, SVERSION_OPTION, sizeof(SVERSION_OPTION) - 1) == 0))
+ {
+ if (((pStart = strchr(pChr + sizeof(SVERSION_OPTION), '[')) != NULL) &&
+ ((pEnd = strchr(pStart + 1, ']')) != NULL))
+ {
+ strncpy(Path, pStart + 1, pEnd - (pStart + 1));
+ Path[pEnd - (pStart + 1)] = '\0';
+
+ /* build full path */
+ if ((Path[strlen(Path) - 1] != '/') && (Path[strlen(Path) - 1] != '\\'))
+ {
+ strcat(Path, "\\");
+ }
+
+ pChr =&Path[strlen(Path)];
+ if ( strlen(pszPath) <= 0 )
+ {
+ strcat(Path,SVERSION_USER);
+
+ if ( access(Path, 0) < 0 )
+ {
+ *pChr='\0';
+ }
+ }
+ else
+ {
+ strcat(Path, pszPath);
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (strlen(Path) <= 0)
+ {
+ /* try to find the file in the directory of the executbale */
+ if (osl_getExecutableFile(Path, sizeof(Path)) != osl_Process_E_None)
+ return (sal_False);
+
+ /* seperate path from filename */
+ if ((pChr = strrchr(Path, '\\')) == NULL)
+ if ((pChr = strrchr(Path, ':')) == NULL)
+ return (sal_False);
+ else
+ *pChr = '\0';
+ else
+ *pChr = '\0';
+
+ /* if we have no product identification use the executable file name */
+ if (strlen(Product) <= 0)
+ {
+ strcpy(Product, pChr + 1);
+
+ /* remove extension */
+ if ((pChr = strrchr(Product, '.')) != NULL)
+ *pChr = '\0';
+ }
+
+ /* remember last subdir */
+ pStr = strrchr(Path, '\\');
+
+ strcat(Path, "\\");
+
+ if ( strlen(pszPath) <= 0 )
+ {
+ strcat(Path, pszPath);
+ }
+ else
+ {
+ strcat(Path,pszPath);
+ }
+
+ /* if file not exists, remove any specified subdirectories
+ like "bin" or "program" */
+ if (((access(Path, 0) < 0) && (pStr != NULL)) || (strlen(pszPath) <= 0))
+ {
+ static sal_Char *SubDirs[] = SVERSION_DIRS;
+
+ int i = 0;
+
+ for (i = 0; i < (sizeof(SubDirs) / sizeof(SubDirs[0])); i++)
+ if (strnicmp(pStr + 1, SubDirs[i], strlen(SubDirs[i])) == 0)
+ {
+ if ( strlen(pszPath) <= 0)
+ {
+ strcpy(pStr + 1,SVERSION_USER);
+ if ( access(Path, 0) < 0 )
+ {
+ *(pStr+1)='\0';
+ }
+ }
+ else
+ {
+ strcpy(pStr + 1, pszPath);
+ }
+
+ break;
+ }
+ }
+
+ pChr = &Path[strlen(Path)];
+ if ((Path[strlen(Path) - 1] != '/') && (Path[strlen(Path) - 1] != '\\'))
+ strcat(Path, "\\");
+ strcat(Path, pszFile);
+
+ if ((access(Path, 0) < 0) && (strlen(Product) > 0))
+ {
+ sal_Char Profile[_MAX_PATH];
+ oslProfile hProfile;
+
+ /* remove appended filename */
+ *pChr = '\0';
+
+ /* open sversion.ini in the system directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if ((osl_getProfileName(SVERSION_LOCATION, SVERSION_NAME, Profile, sizeof(Profile))) &&
+ (hProfile = osl_openProfile(Profile, osl_Profile_READLOCK)))
+ {
+ pChr = &Product[strlen(Product)];
+
+ /* append build number */
+ strcat(Product, "/");
+ strcat(Product, BUILD_STR(SUPD));
+
+ osl_readProfileString(hProfile, SVERSION_SECTION, Product,
+ Buffer, sizeof(Buffer), "");
+
+ /* if not found, try it without build number */
+ if (strlen(Buffer) <= 0)
+ {
+ *pChr = '\0';
+
+ osl_readProfileString(hProfile, SVERSION_SECTION, Product,
+ Buffer, sizeof(Buffer), "");
+
+ osl_closeProfile(hProfile);
+
+ /* if not found, try the fallback */
+ if ((strlen(Buffer) <= 0) && (strcmp(SVERSION_LOCATION, SVERSION_FALLBACK) != 0))
+ {
+ if ((osl_getProfileName(SVERSION_FALLBACK, SVERSION_NAME, Profile, sizeof(Profile))) &&
+ (hProfile = osl_openProfile(Profile, osl_Profile_READLOCK)))
+ {
+ /* prepare build number */
+ *pChr = '/';
+
+ osl_readProfileString(hProfile, SVERSION_SECTION, Product,
+ Buffer, sizeof(Buffer), "");
+
+ /* if not found, try it without build number */
+ if (strlen(Buffer) <= 0)
+ {
+ *pChr = '\0';
+
+ osl_readProfileString(hProfile, SVERSION_SECTION, Product,
+ Buffer, sizeof(Buffer), "");
+ }
+
+ osl_closeProfile(hProfile);
+ }
+ }
+ }
+ else
+ osl_closeProfile(hProfile);
+
+ if (strlen(Buffer) > 0)
+ {
+ strcpy(Path, Buffer);
+
+ /* build full path */
+ if ((Path[strlen(Path) - 1] != '/') && (Path[strlen(Path) - 1] != '\\'))
+ {
+ if ((*pszPath != '/') && (*pszPath != '\\'))
+ strcat(Path, "\\");
+ }
+
+ pChr=&Path[strlen(pszPath)];
+ if ( strlen(pszPath) > 0 )
+ {
+ strcat(Path, pszPath);
+ }
+ else
+ {
+ strcat(Path,SVERSION_USER);
+ if ( access(Path, 0) < 0 )
+ {
+ *pChr='\0';
+ }
+ }
+ }
+ }
+ }
+ else
+ /* remove appended filename */
+ *pChr = '\0';
+ }
+
+ strcpy(pPath, Path);
+
+ return (sal_True);
+}
+
+#endif // 0 // YD
+
diff --git a/sal/osl/os2/salinit.cxx b/sal/osl/os2/salinit.cxx
new file mode 100644
index 000000000000..f932f2ea1b50
--- /dev/null
+++ b/sal/osl/os2/salinit.cxx
@@ -0,0 +1,120 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define INCL_DOS
+#include <os2.h>
+
+#include "precompiled_sal.hxx"
+#include "sal/config.h"
+
+#include "osl/process.h"
+#include "sal/main.h"
+#include "sal/types.h"
+
+// for exception logging
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+#include "helpers/except.h"
+
+extern "C" {
+
+/*----------------------------------------------------------------------------*/
+
+static CHAR szOOoExe[CCHMAXPATH];
+
+static FILE* APIENTRY _oslExceptOpenLogFile(VOID)
+{
+ FILE *file;
+ DATETIME DT;
+ PPIB pib;
+ PSZ slash;
+
+ // get executable fullpath
+ DosGetInfoBlocks(NULL, &pib);
+ DosQueryModuleName(pib->pib_hmte, sizeof(szOOoExe), szOOoExe);
+ // truncate to exe name
+ slash = (PSZ)strrchr( szOOoExe, '.');
+ *slash = '\0';
+ // make log path
+ strcat( szOOoExe, ".log");
+
+ file = fopen( szOOoExe, "a");
+ if (!file) { // e.g. readonly drive
+ // try again, usually C exist and is writable
+ file = fopen( "c:\\OOo.log", "a");
+ }
+ if (file) {
+ DosGetDateTime(&DT);
+ fprintf(file, "\nTrap message -- Date: %04d-%02d-%02d, Time: %02d:%02d:%02d\n",
+ DT.year, DT.month, DT.day,
+ DT.hours, DT.minutes, DT.seconds);
+ fprintf(file, "-------------------------------------------------------\n"
+ "\nAn internal error occurred (Built " __DATE__ "-" __TIME__ ").\n");
+
+ }
+
+ // ok, return handle
+ return (file);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static EXCEPTSTRUCT g_excptstruct = {0};
+
+void SAL_CALL sal_detail_initialize(int argc, char ** argv)
+{
+ APIRET rc = -1;
+
+#if OSL_DEBUG_LEVEL == 0
+ excRegisterHooks(_oslExceptOpenLogFile, NULL, NULL, FALSE);
+
+ g_excptstruct.RegRec2.pfnHandler = (PFN)excHandlerLoud;
+ g_excptstruct.arc = DosSetExceptionHandler(
+ (PEXCEPTIONREGISTRATIONRECORD)&(g_excptstruct.RegRec2));
+
+ if (g_excptstruct.arc)
+ if (G_pfnExcHookError)
+ G_pfnExcHookError(__FILE__, __LINE__, __FUNCTION__, g_excptstruct.arc);
+ else
+ DosBeep(1000, 1000);
+ g_excptstruct.ulExcpt = setjmp(g_excptstruct.RegRec2.jmpThread);
+#endif
+
+ osl_setCommandArgs(argc, argv);
+}
+
+void SAL_CALL sal_detail_deinitialize()
+{
+ APIRET rc = -1;
+
+#if OSL_DEBUG_LEVEL == 0
+ rc = DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)&(g_excptstruct.RegRec2));
+#endif
+}
+
+}
diff --git a/sal/osl/os2/secimpl.h b/sal/osl/os2/secimpl.h
new file mode 100644
index 000000000000..6922a6d3c0ce
--- /dev/null
+++ b/sal/osl/os2/secimpl.h
@@ -0,0 +1,50 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_SECURITYIMPL_H_
+#define _OSL_SECURITYIMPL_H_
+
+#include <osl/security.h>
+
+#define PASSWD_BUFFER_SIZE 1024 /* recommended, see 'man getpwnam_r' */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _oslSecurityImpl {
+ int m_isValid;
+ struct passwd m_pPasswd;
+ sal_Char m_buffer[PASSWD_BUFFER_SIZE];
+} oslSecurityImpl;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sal/osl/os2/security.c b/sal/osl/os2/security.c
new file mode 100644
index 000000000000..f03be57acc85
--- /dev/null
+++ b/sal/osl/os2/security.c
@@ -0,0 +1,317 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/security.h>
+#include <osl/diagnose.h>
+#include <osl/module.h>
+
+#include "osl/thread.h"
+#include "osl/file.h"
+
+#ifdef SOLARIS
+#include <crypt.h>
+#endif
+
+#include "secimpl.h"
+
+#ifndef PAM_BINARY_MSG
+#define PAM_BINARY_MSG 6
+#endif
+
+extern oslModule SAL_CALL osl_psz_loadModule(const sal_Char *pszModuleName, sal_Int32 nRtldMode);
+extern void* SAL_CALL osl_psz_getSymbol(oslModule hModule, const sal_Char* pszSymbolName);
+extern oslSecurityError SAL_CALL
+osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
+ oslSecurity* pSecurity);
+sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax);
+sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax);
+sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
+sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
+
+
+
+oslSecurity SAL_CALL osl_getCurrentSecurity()
+{
+
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*) malloc(sizeof(oslSecurityImpl));
+ struct passwd *pPasswd = getpwuid(getuid());
+
+ if (pPasswd)
+ {
+ memcpy(&pSecImpl->m_pPasswd, pPasswd, sizeof(pSecImpl->m_pPasswd));
+ pSecImpl->m_isValid = sal_True;
+ }
+ else
+ {
+ /* Some UNIX-OS don't implement getpwuid, e.g. NC OS (special NetBSD) 1.2.1 */
+ /* so we have to catch this in this else branch */
+ pSecImpl->m_pPasswd.pw_name = getenv("USER");
+ pSecImpl->m_pPasswd.pw_dir = getenv("HOME");
+ if (pSecImpl->m_pPasswd.pw_name && pSecImpl->m_pPasswd.pw_dir)
+ pSecImpl->m_isValid = sal_True;
+ else
+ {
+ pSecImpl->m_pPasswd.pw_name = "unknown";
+ pSecImpl->m_pPasswd.pw_dir = "/tmp";
+ pSecImpl->m_isValid = sal_False;
+ }
+ pSecImpl->m_pPasswd.pw_passwd = NULL;
+ pSecImpl->m_pPasswd.pw_uid = getuid();
+ pSecImpl->m_pPasswd.pw_gid = getgid();
+ pSecImpl->m_pPasswd.pw_gecos = "unknown";
+ pSecImpl->m_pPasswd.pw_shell = "unknown";
+ }
+
+
+ return ((oslSecurity)pSecImpl);
+}
+
+
+oslSecurityError SAL_CALL osl_loginUser(
+ rtl_uString *ustrUserName,
+ rtl_uString *ustrPassword,
+ oslSecurity *pSecurity
+ )
+{
+ oslSecurityError ret;
+
+ *pSecurity = osl_getCurrentSecurity();
+ ret = osl_Security_E_None;
+
+ return ret;
+}
+
+
+
+oslSecurityError SAL_CALL osl_loginUserOnFileServer(
+ rtl_uString *strUserName,
+ rtl_uString *strPasswd,
+ rtl_uString *strFileServer,
+ oslSecurity *pSecurity
+ )
+{
+ oslSecurityError erg;
+ return erg = osl_Security_E_UserUnknown;
+}
+
+
+oslSecurityError SAL_CALL osl_psz_loginUserOnFileServer( const sal_Char* pszUserName,
+ const sal_Char* pszPasswd,
+ const sal_Char* pszFileServer,
+ oslSecurity* pSecurity )
+{
+ oslSecurityError erg;
+ return erg = osl_Security_E_UserUnknown;
+}
+
+sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **ustrIdent)
+{
+ sal_Bool bRet=sal_False;
+ sal_Char pszIdent[1024];
+
+ pszIdent[0] = '\0';
+
+ bRet = osl_psz_getUserIdent(Security,pszIdent,sizeof(pszIdent));
+
+ rtl_string2UString( ustrIdent, pszIdent, rtl_str_getLength( pszIdent ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*ustrIdent != NULL);
+
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax)
+{
+ sal_Char buffer[32];
+ sal_Int32 nChr;
+
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
+
+ if (pSecImpl == NULL)
+ return sal_False;
+
+ nChr = snprintf(buffer, sizeof(buffer), "%u", pSecImpl->m_pPasswd.pw_uid);
+ if ( nChr < 0 || nChr >= sizeof(buffer) || nChr >= nMax )
+ return sal_False; /* leave *pszIdent unmodified in case of failure */
+
+ memcpy(pszIdent, buffer, nChr+1);
+ return sal_True;
+}
+
+sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **ustrName)
+{
+ sal_Bool bRet=sal_False;
+ sal_Char pszName[1024];
+
+ pszName[0] = '\0';
+
+ bRet = osl_psz_getUserName(Security,pszName,sizeof(pszName));
+
+ rtl_string2UString( ustrName, pszName, rtl_str_getLength( pszName ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*ustrName != NULL);
+
+ return bRet;
+}
+
+
+
+sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax)
+{
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
+
+ if ((pSecImpl == NULL) || (! pSecImpl->m_isValid))
+ return sal_False;
+
+ strncpy(pszName, pSecImpl->m_pPasswd.pw_name, nMax);
+
+ return sal_True;
+}
+
+sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
+{
+ sal_Bool bRet=sal_False;
+ sal_Char pszDirectory[PATH_MAX];
+
+ pszDirectory[0] = '\0';
+
+ bRet = osl_psz_getHomeDir(Security,pszDirectory,sizeof(pszDirectory));
+
+ if ( bRet == sal_True )
+ {
+ rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pustrDirectory != NULL);
+ osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
+ }
+
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
+{
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
+
+ if (pSecImpl == NULL)
+ return sal_False;
+
+ /* if current user, check also environment for HOME */
+ if (getuid() == pSecImpl->m_pPasswd.pw_uid)
+ {
+ sal_Char *pStr = NULL;
+#ifdef SOLARIS
+ char buffer[8192];
+
+ struct passwd pwd;
+ struct passwd *ppwd;
+
+#ifdef _POSIX_PTHREAD_SEMANTICS
+ if ( 0 != getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &ppwd ) )
+ ppwd = NULL;
+#else
+ ppwd = getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer) );
+#endif
+
+ if ( ppwd )
+ pStr = ppwd->pw_dir;
+#else
+ pStr = getenv("HOME");
+#endif
+
+ if ((pStr != NULL) && (strlen(pStr) > 0) &&
+ (access(pStr, 0) == 0))
+ strncpy(pszDirectory, pStr, nMax);
+ else
+ if (pSecImpl->m_isValid)
+ strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
+ else
+ return sal_False;
+ }
+ else
+ strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
+
+ return sal_True;
+}
+
+sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
+{
+ sal_Bool bRet = sal_False;
+ sal_Char pszDirectory[PATH_MAX];
+
+ pszDirectory[0] = '\0';
+
+ bRet = osl_psz_getConfigDir(Security,pszDirectory,sizeof(pszDirectory));
+
+ if ( bRet == sal_True )
+ {
+ rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pustrDirectory != NULL);
+ osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
+ }
+
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
+{
+ return (osl_psz_getHomeDir(Security, pszDirectory, nMax));
+}
+
+sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
+{
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
+
+ if (pSecImpl == NULL)
+ return sal_False;
+
+ if (pSecImpl->m_pPasswd.pw_uid != 0)
+ return (sal_False);
+
+ return (sal_True);
+}
+
+void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
+{
+ if (Security)
+ free ((oslSecurityImpl*)Security);
+}
+
+
+sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
+{
+ return sal_False;
+}
+
+void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
+{
+ return;
+}
+
+
diff --git a/sal/osl/os2/semaphor.c b/sal/osl/os2/semaphor.c
new file mode 100644
index 000000000000..8613e3ecd352
--- /dev/null
+++ b/sal/osl/os2/semaphor.c
@@ -0,0 +1,190 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/semaphor.h>
+
+/*
+ Implemetation notes:
+ The void* represented by oslSemaphore is used
+ to store a OS/2 HANDLE.
+*/
+
+typedef struct _oslSemaphoreImpl
+{
+ HEV hevReachedZero;
+ int nCount;
+} oslSemaphoreImpl;
+
+// static mutex to control access to private members of oslMutexImpl
+static HMTX MutexLock = NULL;
+
+/*****************************************************************************/
+/* osl_createSemaphore */
+/*****************************************************************************/
+
+/*
+- Erzeugen der Semaphore
+- Z„hler auf initialCount setzen
+*/
+oslSemaphore SAL_CALL osl_createSemaphore(sal_uInt32 initialCount)
+{
+ APIRET rc;
+ oslSemaphoreImpl * pSemaphoreImpl;
+
+ /* alloc mem. for our internal data structure */
+ pSemaphoreImpl = (oslSemaphoreImpl *) malloc(sizeof(oslSemaphoreImpl));
+ if( pSemaphoreImpl == NULL )
+ return NULL;
+
+ /* create semaphore */
+ rc = DosCreateEventSem( NULL,
+ &pSemaphoreImpl->hevReachedZero,
+ DC_SEM_SHARED,
+ FALSE );
+ if( rc != NO_ERROR )
+ {
+ free( pSemaphoreImpl );
+ return NULL;
+ }
+
+ pSemaphoreImpl->nCount = initialCount;
+
+ // create static mutex for private members
+ if (MutexLock == NULL)
+ DosCreateMutexSem( NULL, &MutexLock, 0, FALSE );
+
+ return (oslSemaphore) pSemaphoreImpl;
+}
+
+/*****************************************************************************/
+/* osl_destroySemaphore */
+/*****************************************************************************/
+
+/*
+- Semaphore l”schen
+*/
+
+void SAL_CALL osl_destroySemaphore(oslSemaphore Semaphore)
+{
+ oslSemaphoreImpl* pSemaphoreImpl = (oslSemaphoreImpl*)Semaphore;
+ OSL_ASSERT(Semaphore != 0);
+
+ DosCloseEventSem( pSemaphoreImpl->hevReachedZero );
+
+ free( pSemaphoreImpl );
+}
+
+/*****************************************************************************/
+/* osl_acquireSemaphore */
+/*****************************************************************************/
+/*
+- Z„hler -1
+- wenn Z„hler < 0: blockieren
+*/
+
+sal_Bool SAL_CALL osl_acquireSemaphore(oslSemaphore Semaphore)
+{
+ APIRET rc;
+ oslSemaphoreImpl* pSemaphoreImpl = (oslSemaphoreImpl*)Semaphore;
+ int nCount;
+ OSL_ASSERT(Semaphore != 0);
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+
+ while( pSemaphoreImpl->nCount < 1 )
+ {
+ sal_uInt32 nPostCount;
+
+ DosReleaseMutexSem( MutexLock);
+
+ rc = DosWaitEventSem(pSemaphoreImpl->hevReachedZero, SEM_INDEFINITE_WAIT );
+ DosResetEventSem(pSemaphoreImpl->hevReachedZero, &nPostCount);
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+ }
+
+ pSemaphoreImpl->nCount--;
+ DosReleaseMutexSem( MutexLock);
+
+ return( rc == NO_ERROR );
+}
+
+/*****************************************************************************/
+/* osl_tryToAcquireSemaphore */
+/*****************************************************************************/
+/*
+- Z„hler -1, wenn vorher > 0
+- wenn Z„hler < 0: mit FALSE zurueck
+*/
+sal_Bool SAL_CALL osl_tryToAcquireSemaphore(oslSemaphore Semaphore)
+{
+ APIRET rc;
+ oslSemaphoreImpl* pSemaphoreImpl = (oslSemaphoreImpl*)Semaphore;
+ int nCount;
+ OSL_ASSERT(Semaphore != 0);
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+
+ nCount = pSemaphoreImpl->nCount;
+ if( pSemaphoreImpl->nCount > 0 )
+ pSemaphoreImpl->nCount--;
+
+ DosReleaseMutexSem( MutexLock);
+
+ return( nCount > 0 );
+}
+
+/*****************************************************************************/
+/* osl_releaseSemaphore */
+/*****************************************************************************/
+/*
+- Z„hler +1
+*/
+sal_Bool SAL_CALL osl_releaseSemaphore(oslSemaphore Semaphore)
+{
+ APIRET rc;
+ oslSemaphoreImpl* pSemaphoreImpl = (oslSemaphoreImpl*)Semaphore;
+ int nCount;
+ OSL_ASSERT(Semaphore != 0);
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+
+ nCount = pSemaphoreImpl->nCount;
+ pSemaphoreImpl->nCount++;
+
+ DosReleaseMutexSem( MutexLock);
+
+ if( nCount == 0 )
+ DosPostEventSem(pSemaphoreImpl->hevReachedZero);
+
+ return( rc == NO_ERROR );
+}
+
+
diff --git a/sal/osl/os2/signal.c b/sal/osl/os2/signal.c
new file mode 100644
index 000000000000..881db13fe1e1
--- /dev/null
+++ b/sal/osl/os2/signal.c
@@ -0,0 +1,249 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+/* system headers */
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <osl/signal.h>
+
+typedef struct _oslSignalHandlerImpl
+{
+ oslSignalHandlerFunction Handler;
+ void* pData;
+ struct _oslSignalHandlerImpl* pNext;
+} oslSignalHandlerImpl;
+
+static sal_Bool bErrorReportingEnabled = sal_True;
+static sal_Bool bInitSignal = sal_False;
+static oslMutex SignalListMutex;
+static oslSignalHandlerImpl* SignalList;
+
+/*static*//* ULONG _Export APIENTRY SignalHandlerFunction(PEXCEPTIONREPORTRECORD pERepRec,
+ PEXCEPTIONREGISTRATIONRECORD,
+ PCONTEXTRECORD, PVOID);
+*/
+/*static*/ ULONG __declspec(dllexport) APIENTRY SignalHandlerFunction(PEXCEPTIONREPORTRECORD pERepRec,
+ PEXCEPTIONREGISTRATIONRECORD,
+ PCONTEXTRECORD, PVOID);
+static EXCEPTIONREGISTRATIONRECORD ExcptHandler = { 0, SignalHandlerFunction };
+
+static sal_Bool InitSignal( void )
+{
+ SignalListMutex = osl_createMutex();
+
+ ExcptHandler.ExceptionHandler = (_ERR *) &SignalHandlerFunction;
+ /* DosSetExceptionHandler(&ExcptHandler); */
+
+ return sal_True;
+}
+
+static sal_Bool DeInitSignal( void )
+{
+ /* DosUnsetExceptionHandler(&ExcptHandler); */
+
+ osl_destroyMutex(SignalListMutex);
+
+ return sal_False;
+}
+
+static oslSignalAction CallSignalHandler(oslSignalInfo *pInfo)
+{
+ oslSignalHandlerImpl* pHandler = SignalList;
+ oslSignalAction Action = osl_Signal_ActCallNextHdl;
+
+ while (pHandler != NULL)
+ {
+ if ((Action = pHandler->Handler(pHandler->pData, pInfo)) != osl_Signal_ActCallNextHdl)
+ break;
+
+ pHandler = pHandler->pNext;
+ }
+
+ return Action;
+}
+
+/*****************************************************************************/
+/* SignalHandlerFunction */
+/*****************************************************************************/
+/*static*/ ULONG __declspec(dllexport) APIENTRY SignalHandlerFunction(PEXCEPTIONREPORTRECORD pERepRec,
+ PEXCEPTIONREGISTRATIONRECORD pERegRec,
+ PCONTEXTRECORD pConRec, PVOID pReserved)
+{
+ oslSignalInfo Info;
+
+ Info.UserSignal = pERepRec->ExceptionNum;
+ Info.UserData = NULL;
+
+ switch (pERepRec->ExceptionNum)
+ {
+ case XCPT_ACCESS_VIOLATION:
+ Info.Signal = osl_Signal_AccessViolation;
+ break;
+
+ case XCPT_INTEGER_DIVIDE_BY_ZERO:
+ Info.Signal = osl_Signal_IntegerDivideByZero;
+ break;
+
+ case XCPT_BREAKPOINT:
+ Info.Signal = osl_Signal_DebugBreak;
+ break;
+
+ default:
+ Info.Signal = osl_Signal_System;
+ break;
+ }
+
+ switch (CallSignalHandler(&Info))
+ {
+ case osl_Signal_ActCallNextHdl:
+ return (XCPT_CONTINUE_SEARCH);
+
+ case osl_Signal_ActAbortApp:
+ return (XCPT_CONTINUE_SEARCH);
+
+ case osl_Signal_ActKillApp:
+ exit(255);
+ break;
+ }
+
+ return (XCPT_CONTINUE_SEARCH);
+}
+
+/*****************************************************************************/
+/* osl_addSignalHandler */
+/*****************************************************************************/
+oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData)
+{
+ oslSignalHandlerImpl* pHandler;
+
+ OSL_ASSERT(Handler != NULL);
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ pHandler = (oslSignalHandlerImpl*) calloc(1, sizeof(oslSignalHandlerImpl));
+
+ if (pHandler != NULL)
+ {
+ pHandler->Handler = Handler;
+ pHandler->pData = pData;
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler->pNext = SignalList;
+ SignalList = pHandler;
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (pHandler);
+ }
+
+ return (NULL);
+}
+
+/*****************************************************************************/
+/* osl_removeSignalHandler */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler)
+{
+ oslSignalHandlerImpl *pHandler, *pPrevious = NULL;
+
+ OSL_ASSERT(Handler != NULL);
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler = SignalList;
+
+ while (pHandler != NULL)
+ {
+ if (pHandler == Handler)
+ {
+ if (pPrevious)
+ pPrevious->pNext = pHandler->pNext;
+ else
+ SignalList = pHandler->pNext;
+
+ osl_releaseMutex(SignalListMutex);
+
+ if (SignalList == NULL )
+ bInitSignal = DeInitSignal();
+
+ free(pHandler);
+
+ return (sal_True);
+ }
+
+ pPrevious = pHandler;
+ pHandler = pHandler->pNext;
+ }
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (sal_False);
+}
+
+/*****************************************************************************/
+/* osl_raiseSignal */
+/*****************************************************************************/
+oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData)
+{
+ oslSignalInfo Info;
+ oslSignalAction Action;
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ Info.Signal = osl_Signal_User;
+ Info.UserSignal = UserSignal;
+ Info.UserData = UserData;
+
+ Action = CallSignalHandler(&Info);
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (Action);
+}
+
+/*****************************************************************************/
+/* osl_setErrorReporting */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable )
+{
+ sal_Bool bOld = bErrorReportingEnabled;
+ bErrorReportingEnabled = bEnable;
+
+ return bOld;
+}
+
diff --git a/sal/osl/os2/socket.c b/sal/osl/os2/socket.c
new file mode 100644
index 000000000000..6c171016f798
--- /dev/null
+++ b/sal/osl/os2/socket.c
@@ -0,0 +1,3097 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/socket.h>
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <osl/signal.h>
+
+#include <rtl/alloc.h>
+
+#include <ctype.h>
+#include <sal/types.h>
+
+#include "sockimpl.h"
+
+
+/* defines for poll */
+#ifdef HAVE_POLL_H
+#undef HAVE_POLL_H
+#endif
+
+#if defined(LINUX) || defined(NETBSD) || defined ( FREEBSD ) || defined (MACOSX)
+#include <sys/poll.h>
+#define HAVE_POLL_H
+#endif /* HAVE_POLL_H */
+
+#if defined(SOLARIS)
+#include <poll.h>
+#define HAVE_POLL_H
+#endif /* SOLARIS */
+
+#ifndef HAVE_POLL_H
+#define POLLIN 0x0001
+#define POLLOUT 0x0002
+#define POLLPRI 0x0004
+#endif /* HAVE_POLL_H */
+
+
+/* defines for shutdown */
+#define SD_RECEIVE 0
+#define SD_SEND 1
+#define SD_BOTH 2
+
+
+/*
+ oslSocketAddr is a pointer to a Berkeley struct sockaddr.
+ I refrained from using sockaddr_in because of possible further
+ extensions of this socket-interface (IP-NG?).
+ The intention was to hide all Berkeley data-structures from
+ direct access past the osl-interface.
+
+ The current implementation is internet (IP) centered. All
+ the constructor-functions (osl_create...) take parameters
+ that will probably make sense only in the IP-environment
+ (e.g. because of using the dotted-address-format).
+
+ If the interface will be extended to host other protocol-
+ families, I expect no externally visible changes in the
+ existing functions. You'll probably need only new
+ constructor-functions who take the different address
+ formats into consideration (maybe a long dotted address
+ or whatever).
+*/
+
+/* _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr */
+/* are the same! I don't like it very much but see no other easy way to */
+/* conceal the struct sockaddr from the eyes of the user. */
+
+
+#define OSL_INVALID_SOCKET -1
+#define OSL_SOCKET_ERROR -1
+
+
+/* Buffer size for gethostbyname */
+#define MAX_HOSTBUFFER_SIZE 2048
+
+/*****************************************************************************/
+/* enum oslAddrFamily */
+/*****************************************************************************/
+
+/* map */
+static unsigned long FamilyMap[]= {
+ AF_INET, /* osl_Socket_FamilyInet */
+ AF_IPX, /* osl_Socket_FamilyIpx */
+ 0 /* osl_Socket_FamilyInvalid */
+};
+
+/* reverse map */
+static oslAddrFamily osl_AddrFamilyFromNative(sal_uInt32 nativeType)
+{
+ oslAddrFamily i= (oslAddrFamily)0;
+
+ while(i != osl_Socket_FamilyInvalid)
+ {
+ if(FamilyMap[i] == nativeType)
+ return i;
+ i = (oslAddrFamily) ( i + 1 );
+ }
+
+ return i;
+}
+
+/* macros */
+#define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y)
+#define FAMILY_TO_NATIVE(x) (short)FamilyMap[x]
+
+/*****************************************************************************/
+/* enum oslProtocol */
+/*****************************************************************************/
+
+/* map */
+static sal_uInt32 ProtocolMap[]= {
+ 0, /* osl_Socket_ProtocolIp */
+ NSPROTO_IPX, /* osl_Socket_ProtocolIpx */
+ NSPROTO_SPX, /* osl_Socket_ProtocolSpx */
+ NSPROTO_SPXII, /* osl_Socket_ProtocolSpxII */
+ 0 /* osl_Socket_ProtocolInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslProtocol osl_ProtocolFromNative(sal_uInt32 nativeType)
+{
+ oslProtocol i= (oslProtocol)0;
+
+ while(i != osl_Socket_ProtocolInvalid)
+ {
+ if(ProtocolMap[i] == nativeType)
+ return i;
+ i = (oslProtocol) ( i + 1);
+ }
+
+ return i;
+}
+*/
+
+/* macros */
+#define PROTOCOL_FROM_NATIVE(y) osl_ProtocolFromNative(y)
+#define PROTOCOL_TO_NATIVE(x) ProtocolMap[x]
+
+
+/*****************************************************************************/
+/* enum oslSocketType */
+/*****************************************************************************/
+
+/* map */
+static sal_uInt32 TypeMap[]= {
+ SOCK_STREAM, /* osl_Socket_TypeStream */
+ SOCK_DGRAM, /* osl_Socket_TypeDgram */
+ SOCK_RAW, /* osl_Socket_TypeRaw */
+ SOCK_RDM, /* osl_Socket_TypeRdm */
+ SOCK_SEQPACKET, /* osl_Socket_TypeSeqPacket */
+ 0 /* osl_Socket_TypeInvalid */
+};
+
+/* reverse map */
+static oslSocketType osl_SocketTypeFromNative(sal_uInt32 nativeType)
+{
+ oslSocketType i= (oslSocketType)0;
+
+ while(i != osl_Socket_TypeInvalid)
+ {
+ if(TypeMap[i] == nativeType)
+ return i;
+ i = (oslSocketType)(i + 1);
+ }
+
+ return i;
+}
+
+/* macros */
+#define TYPE_TO_NATIVE(x) TypeMap[x]
+#define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y)
+
+
+/*****************************************************************************/
+/* enum oslSocketOption */
+/*****************************************************************************/
+
+/* map */
+static sal_uInt32 OptionMap[]= {
+ SO_DEBUG, /* osl_Socket_OptionDebug */
+ SO_ACCEPTCONN, /* osl_Socket_OptionAcceptConn */
+ SO_REUSEADDR, /* osl_Socket_OptionReuseAddr */
+ SO_KEEPALIVE, /* osl_Socket_OptionKeepAlive */
+ SO_DONTROUTE, /* osl_Socket_OptionDontRoute */
+ SO_BROADCAST, /* osl_Socket_OptionBroadcast */
+ SO_USELOOPBACK, /* osl_Socket_OptionUseLoopback */
+ SO_LINGER, /* osl_Socket_OptionLinger */
+ SO_OOBINLINE, /* osl_Socket_OptionOOBinLine */
+ SO_SNDBUF, /* osl_Socket_OptionSndBuf */
+ SO_RCVBUF, /* osl_Socket_OptionRcvBuf */
+ SO_SNDLOWAT, /* osl_Socket_OptionSndLowat */
+ SO_RCVLOWAT, /* osl_Socket_OptionRcvLowat */
+ SO_SNDTIMEO, /* osl_Socket_OptionSndTimeo */
+ SO_RCVTIMEO, /* osl_Socket_OptionRcvTimeo */
+ SO_ERROR, /* osl_Socket_OptionError */
+ SO_TYPE, /* osl_Socket_OptionType */
+ TCP_NODELAY, /* osl_Socket_OptionTcpNoDelay */
+ 0 /* osl_Socket_OptionInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketOption osl_SocketOptionFromNative(sal_uInt32 nativeType)
+{
+ oslSocketOption i= (oslSocketOption)0;
+
+ while(i != osl_Socket_OptionInvalid)
+ {
+ if(OptionMap[i] == nativeType)
+ return i;
+ i = (oslSocketOption) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+/* macros */
+#define OPTION_TO_NATIVE(x) OptionMap[x]
+#define OPTION_FROM_NATIVE(y) osl_SocketOptionFromNative(y)
+
+
+/*****************************************************************************/
+/* enum oslSocketOptionLevel */
+/*****************************************************************************/
+
+static sal_uInt32 OptionLevelMap[]= {
+ SOL_SOCKET, /* osl_Socket_LevelSocket */
+ IPPROTO_TCP, /* osl_Socket_LevelTcp */
+ 0 /* osl_Socket_LevelInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketOptionLevel osl_SocketOptionLevelFromNative(sal_uInt32 nativeType)
+{
+ oslSocketOptionLevel i= (oslSocketOptionLevel)0;
+
+ while(i != osl_Socket_LevelInvalid)
+ {
+ if(OptionLevelMap[i] == nativeType)
+ return i;
+ i = (oslSocketOptionLevel) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+/* macros */
+#define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x]
+#define OPTION_LEVEL_FROM_NATIVE(y) osl_SocketOptionLevelFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketMsgFlag */
+/*****************************************************************************/
+
+static sal_uInt32 SocketMsgFlagMap[]= {
+ 0, /* osl_Socket_MsgNormal */
+ MSG_OOB, /* osl_Socket_MsgOOB */
+ MSG_PEEK, /* osl_Socket_MsgPeek */
+ MSG_DONTROUTE, /* osl_Socket_MsgDontRoute */
+ MSG_MAXIOVLEN, /* osl_Socket_MsgMaxIOVLen */
+ 0 /* osl_Socket_MsgInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketMsgFlag osl_SocketMsgFlagFromNative(sal_uInt32 nativeType)
+{
+ oslSocketMsgFlag i= (oslSocketMsgFlag)0;
+
+ while(i != osl_Socket_MsgInvalid)
+ {
+ if(SocketMsgFlagMap[i] == nativeType)
+ return i;
+ i = (oslSocketMsgFlag) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+
+/* macros */
+#define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x]
+#define MSG_FLAG_FROM_NATIVE(y) osl_SocketMsgFlagFromNative(y)
+
+
+/*****************************************************************************/
+/* enum oslSocketDirection */
+/*****************************************************************************/
+
+static sal_uInt32 SocketDirection[]= {
+ SD_RECEIVE, /* osl_Socket_DirRead */
+ SD_SEND, /* osl_Socket_DirWrite */
+ SD_BOTH, /* osl_Socket_DirReadWrite */
+ 0 /* osl_Socket_DirInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketDirection osl_SocketDirectionFromNative(sal_uInt32 nativeType)
+{
+ oslSocketDirection i= (oslSocketDirection)0;
+
+ while(i != osl_Socket_DirInvalid)
+ {
+ if(SocketDirection[i] == nativeType)
+ return i;
+ i = (oslSocketDirection) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+
+/* macros */
+#define DIRECTION_TO_NATIVE(x) SocketDirection[x]
+#define DIRECTION_FROM_NATIVE(y) osl_SocketDirectionFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketError */
+/*****************************************************************************/
+
+static struct
+{
+ int errcode;
+ oslSocketError error;
+} SocketError[]= {
+ { 0, osl_Socket_E_None }, /* no error */
+ { ENOTSOCK, osl_Socket_E_NotSocket }, /* Socket operation on non-socket */
+ { EDESTADDRREQ, osl_Socket_E_DestAddrReq }, /* Destination address required */
+ { EMSGSIZE, osl_Socket_E_MsgSize }, /* Message too long */
+ { EPROTOTYPE, osl_Socket_E_Prototype }, /* Protocol wrong type for socket */
+ { ENOPROTOOPT, osl_Socket_E_NoProtocol }, /* Protocol not available */
+ { EPROTONOSUPPORT, osl_Socket_E_ProtocolNoSupport }, /* Protocol not supported */
+ { ESOCKTNOSUPPORT, osl_Socket_E_TypeNoSupport }, /* Socket type not supported */
+ { EOPNOTSUPP, osl_Socket_E_OpNotSupport }, /* Operation not supported on socket */
+ { EPFNOSUPPORT, osl_Socket_E_PfNoSupport }, /* Protocol family not supported */
+ { EAFNOSUPPORT, osl_Socket_E_AfNoSupport }, /* Address family not supported by */
+ /* protocol family */
+ { EADDRINUSE, osl_Socket_E_AddrInUse }, /* Address already in use */
+ { EADDRNOTAVAIL, osl_Socket_E_AddrNotAvail }, /* Can't assign requested address */
+ { ENETDOWN, osl_Socket_E_NetDown }, /* Network is down */
+ { ENETUNREACH, osl_Socket_E_NetUnreachable }, /* Network is unreachable */
+ { ENETRESET, osl_Socket_E_NetReset }, /* Network dropped connection because */
+ /* of reset */
+ { ECONNABORTED, osl_Socket_E_ConnAborted }, /* Software caused connection abort */
+ { ECONNRESET, osl_Socket_E_ConnReset }, /* Connection reset by peer */
+ { ENOBUFS, osl_Socket_E_NoBufferSpace }, /* No buffer space available */
+ { EISCONN, osl_Socket_E_IsConnected }, /* Socket is already connected */
+ { ENOTCONN, osl_Socket_E_NotConnected }, /* Socket is not connected */
+ { ESHUTDOWN, osl_Socket_E_Shutdown }, /* Can't send after socket shutdown */
+ { ETOOMANYREFS, osl_Socket_E_TooManyRefs }, /* Too many references: can't splice */
+ { ETIMEDOUT, osl_Socket_E_TimedOut }, /* Connection timed out */
+ { ECONNREFUSED, osl_Socket_E_ConnRefused }, /* Connection refused */
+ { EHOSTDOWN, osl_Socket_E_HostDown }, /* Host is down */
+ { EHOSTUNREACH, osl_Socket_E_HostUnreachable }, /* No route to host */
+ { EWOULDBLOCK, osl_Socket_E_WouldBlock }, /* call would block on non-blocking socket */
+ { EALREADY, osl_Socket_E_Already }, /* operation already in progress */
+ { EINPROGRESS, osl_Socket_E_InProgress }, /* operation now in progress */
+ { EAGAIN, osl_Socket_E_WouldBlock }, /* same as EWOULDBLOCK */
+ { -1, osl_Socket_E_InvalidError }
+};
+
+/* map */
+/* mfe: NOT USED
+static int osl_NativeFromSocketError(oslSocketError errorCode)
+{
+ int i = 0;
+
+ while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
+ (SocketError[i].error != errorCode)) i++;
+
+ return SocketError[i].errcode;
+}
+*/
+
+/* reverse map */
+static oslSocketError osl_SocketErrorFromNative(int nativeType)
+{
+ int i = 0;
+
+ while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
+ (SocketError[i].errcode != nativeType)) i++;
+
+ return SocketError[i].error;
+}
+
+/* macros */
+#define ERROR_TO_NATIVE(x) osl_NativeFromSocketError(x)
+#define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y)
+
+/*****************************************************************************/
+/* local function prototypes */
+/*****************************************************************************/
+
+oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
+ const sal_Char* pszDottedAddr, sal_Int32 Port);
+
+oslSocketAddr SAL_CALL osl_psz_createIpxSocketAddr (
+ const sal_Char NetNumber[4],
+ const sal_Char NodeNumber[6],
+ sal_uInt32 SocketNumber);
+
+oslHostAddr SAL_CALL osl_psz_createHostAddr (
+ const sal_Char *pszHostname, const oslSocketAddr Addr);
+
+oslHostAddr SAL_CALL osl_psz_createHostAddrByName (
+ const sal_Char *pszHostname);
+
+const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (
+ const oslHostAddr Addr);
+
+oslSocketResult SAL_CALL osl_psz_getLocalHostname (
+ sal_Char *pBuffer, sal_uInt32 nBufLen);
+
+oslSocketAddr SAL_CALL osl_psz_resolveHostname (
+ const sal_Char* pszHostname);
+
+sal_Int32 SAL_CALL osl_psz_getServicePort (
+ const sal_Char* pszServicename, const sal_Char* pszProtocol);
+
+oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr (
+ oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
+
+oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr (
+ oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
+
+void SAL_CALL osl_psz_getLastSocketErrorDescription (
+ oslSocket Socket, sal_Char* pBuffer, sal_uInt32 BufferSize);
+
+/*****************************************************************************/
+/* osl_create/destroy-SocketImpl */
+/*****************************************************************************/
+
+#if OSL_DEBUG_LEVEL > 1
+static sal_uInt32 g_nSocketImpl = 0;
+static sal_uInt32 g_nSocketAddr = 0;
+
+/* sorry, must be implemented otherwise */
+#if 0
+struct LeakWarning
+{
+ ~LeakWarning()
+ {
+ if( g_nSocketImpl )
+ OSL_TRACE( "sal_socket: %d socket instances leak\n" , g_nSocketImpl );
+ if( g_nSocketAddr )
+ OSL_TRACE( "sal_socket: %d socket address instances leak\n" , g_nSocketAddr );
+ }
+};
+LeakWarning socketWarning;
+#endif
+
+#endif /* OSL_DEBUG_LEVEL */
+
+
+oslSocket __osl_createSocketImpl(int Socket)
+{
+ oslSocket pSocket;
+
+ pSocket = (oslSocket)calloc(1, sizeof(struct oslSocketImpl));
+
+ pSocket->m_Socket = Socket;
+ pSocket->m_nLastError = 0;
+ pSocket->m_CloseCallback = 0;
+ pSocket->m_CallbackArg = 0;
+ pSocket->m_nRefCount = 1;
+
+#if defined(LINUX)
+ pSocket->m_bIsAccepting = sal_False;
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketImpl ++;
+#endif
+ return pSocket;
+}
+
+void __osl_destroySocketImpl(oslSocket Socket)
+{
+ if ( Socket != NULL)
+ free((struct oslSocketImpl *) Socket);
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketImpl --;
+#endif
+}
+
+static oslSocketAddr __osl_createSocketAddr( )
+{
+ oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl ));
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketAddr ++;
+#endif
+ return pAddr;
+}
+
+static oslSocketAddr __osl_createSocketAddrWithFamily(
+ oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr )
+{
+ oslSocketAddr pAddr;
+
+ OSL_ASSERT( family == osl_Socket_FamilyInet );
+
+ pAddr = __osl_createSocketAddr();
+ switch( family )
+ {
+ case osl_Socket_FamilyInet:
+ {
+ struct sockaddr_in* pInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet);
+ pInetAddr->sin_addr.s_addr = nAddr;
+ pInetAddr->sin_port = (sal_uInt16)(port&0xffff);
+ break;
+ }
+ default:
+ pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family);
+ }
+ return pAddr;
+}
+
+static oslSocketAddr __osl_createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr )
+{
+ oslSocketAddr pAddr = __osl_createSocketAddr();
+ memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( struct sockaddr ) );
+ return pAddr;
+}
+
+static void __osl_destroySocketAddr( oslSocketAddr addr )
+{
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketAddr --;
+#endif
+ rtl_freeMemory( addr );
+}
+
+/*****************************************************************************/
+/* osl_createEmptySocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family)
+{
+ oslSocketAddr pAddr = 0;
+
+ /* is it an internet-Addr? */
+ if (Family == osl_Socket_FamilyInet)
+ {
+ pAddr = __osl_createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) );
+ }
+ else
+ {
+ pAddr = __osl_createSocketAddrWithFamily( Family , 0 , 0 );
+ }
+
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_copySocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr)
+{
+ oslSocketAddr pCopy = 0;
+ if (Addr)
+ {
+ pCopy = __osl_createSocketAddr();
+
+ if (pCopy)
+ memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr));
+ }
+ return pCopy;
+}
+
+/*****************************************************************************/
+/* osl_isEqualSocketAddr */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isEqualSocketAddr (
+ oslSocketAddr Addr1,
+ oslSocketAddr Addr2)
+{
+ struct sockaddr* pAddr1= &(Addr1->m_sockaddr);
+ struct sockaddr* pAddr2= &(Addr2->m_sockaddr);
+
+ OSL_ASSERT(pAddr1);
+ OSL_ASSERT(pAddr2);
+
+ if (pAddr1->sa_family == pAddr2->sa_family)
+ {
+ switch (pAddr1->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in* pInetAddr1= (struct sockaddr_in*)pAddr1;
+ struct sockaddr_in* pInetAddr2= (struct sockaddr_in*)pAddr2;
+
+ if ((pInetAddr1->sin_family == pInetAddr2->sin_family) &&
+ (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) &&
+ (pInetAddr1->sin_port == pInetAddr2->sin_port))
+ return (sal_True);
+ }
+
+ default:
+ {
+ return (memcmp(pAddr1, Addr2, sizeof(struct sockaddr)) == 0);
+ }
+ }
+ }
+
+ return (sal_False);
+}
+
+/*****************************************************************************/
+/* osl_createInetBroadcastAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createInetBroadcastAddr (
+ rtl_uString *strDottedAddr,
+ sal_Int32 Port)
+{
+ sal_uInt32 nAddr = OSL_INADDR_NONE;
+ oslSocketAddr pAddr;
+
+ if (strDottedAddr && strDottedAddr->length)
+ {
+ /* Dotted host address for limited broadcast */
+ rtl_String *pDottedAddr = NULL;
+
+ rtl_uString2String (
+ &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ nAddr = inet_addr (pDottedAddr->buffer);
+ rtl_string_release (pDottedAddr);
+ }
+
+ if (nAddr != OSL_INADDR_NONE)
+ {
+ /* Limited broadcast */
+ nAddr = ntohl(nAddr);
+ if (IN_CLASSA(nAddr))
+ {
+ nAddr &= IN_CLASSA_NET;
+ nAddr |= IN_CLASSA_HOST;
+ }
+ else if (IN_CLASSB(nAddr))
+ {
+ nAddr &= IN_CLASSB_NET;
+ nAddr |= IN_CLASSB_HOST;
+ }
+ else if (IN_CLASSC(nAddr))
+ {
+ nAddr &= IN_CLASSC_NET;
+ nAddr |= IN_CLASSC_HOST;
+ }
+ else
+ {
+ /* No broadcast in class D */
+ return ((oslSocketAddr)NULL);
+ }
+ nAddr = htonl(nAddr);
+ }
+
+ pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port), nAddr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createInetSocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createInetSocketAddr (
+ rtl_uString *ustrDottedAddr,
+ sal_Int32 Port)
+{
+ rtl_String* strDottedAddr=0;
+ oslSocketAddr Addr;
+ sal_Char* pszDottedAddr=0;
+
+ if ( ustrDottedAddr != 0 )
+ {
+ rtl_uString2String( &strDottedAddr,
+ rtl_uString_getStr(ustrDottedAddr),
+ rtl_uString_getLength(ustrDottedAddr),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+ pszDottedAddr = rtl_string_getStr(strDottedAddr);
+ }
+
+
+ Addr = osl_psz_createInetSocketAddr(pszDottedAddr, Port);
+
+ if ( strDottedAddr != 0 )
+ {
+ rtl_string_release(strDottedAddr);
+ }
+
+ return Addr;
+}
+
+oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
+ const sal_Char* pszDottedAddr,
+ sal_Int32 Port)
+{
+ oslSocketAddr pAddr = 0;
+ sal_Int32 Addr = inet_addr(pszDottedAddr);
+ if(Addr != -1)
+ {
+ /* valid dotted addr */
+ pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port) , Addr );
+ }
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_setAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq )
+{
+ oslSocketResult res = osl_Socket_Error;
+
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( pByteSeq );
+
+ if( pAddr && pByteSeq )
+ {
+ struct sockaddr_in * pSystemInetAddr;
+
+ OSL_ASSERT( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) );
+ OSL_ASSERT( pByteSeq->nElements == 4 );
+
+ pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
+ memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 );
+ res = osl_Socket_Ok;
+ }
+ return res;
+}
+
+/*****************************************************************************/
+/* osl_getAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq )
+{
+ oslSocketResult res = osl_Socket_Error;
+
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( ppByteSeq );
+
+ if( pAddr && ppByteSeq )
+ {
+ struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
+ rtl_byte_sequence_constructFromArray( ppByteSeq , (sal_Int8 *) &(pSystemInetAddr->sin_addr),4);
+ res = osl_Socket_Ok;
+ }
+ return res;
+}
+
+
+/*****************************************************************************/
+/* _osl_getFullQualifiedDomainName */
+/*****************************************************************************/
+
+/** try to figure out a full-qualified hostname, by adding the current domain
+ as given by the domainname program to the given hostname.
+ This function MUST NOT call gethostbyname since pHostName allready points
+ to data returned by gethostname and would be garbled: use gethostname_r
+ instead!
+ */
+
+/* wrap around different interfaces to reentrant gethostbyname */
+static struct hostent* _osl_gethostbyname_r (
+ const char *name, struct hostent *result,
+ char *buffer, int buflen, int *h_errnop)
+{
+
+#ifdef LINUX
+ struct hostent *__result; /* will be the same as result */
+ int __error;
+ __error = gethostbyname_r (name, result, buffer, buflen,
+ &__result, h_errnop);
+ return __error ? NULL : __result ;
+#elif defined OS2
+ // YD FIXME!!!
+ return 0;
+#else
+ return gethostbyname_r( name, result, buffer, buflen, h_errnop);
+#endif
+}
+
+static sal_Bool _osl_getDomainName (sal_Char *buffer, sal_Int32 bufsiz)
+{
+ sal_Bool result;
+ int p[2];
+
+ result = sal_False;
+
+#if 0 // YD 17/04/06 libc panic for fork() from thread!=1
+
+ if (pipe (p) == 0)
+ {
+ pid_t pid;
+ int nStatus;
+
+ pid = fork();
+ if (pid == 0)
+ {
+ char *argv[] =
+ {
+ "/bin/domainname",
+ NULL
+ };
+
+ close (p[0]);
+ dup2 (p[1], 1);
+ close (p[1]);
+
+ execv ("/bin/domainname", argv);
+ // arriving here means exec failed
+ _exit(-1);
+ }
+ else if (pid > 0)
+ {
+ sal_Int32 k = 0, n = bufsiz;
+
+ close (p[1]);
+ if ((k = read (p[0], buffer, n - 1)) > 0)
+ {
+ buffer[k] = 0;
+ if (buffer[k - 1] == '\n')
+ buffer[k - 1] = 0;
+ result = sal_True;
+ }
+ close (p[0]);
+ waitpid (pid, &nStatus, 0);
+ }
+ else
+ {
+ close (p[0]);
+ close (p[1]);
+ }
+ }
+#endif // 0
+
+ return (result);
+}
+
+static sal_Char* _osl_getFullQualifiedDomainName (const sal_Char *pHostName)
+{
+# define DOMAINNAME_LENGTH 512
+ sal_uInt32 nLengthOfHostName;
+ static sal_uInt32 nLengthOfDomainName = 0;
+ static sal_Char *pDomainName = NULL;
+
+ sal_Char *pFullQualifiedName;
+#if 0 /* OBSOLETE */
+ FILE *pPipeToDomainnameExe;
+#endif /* OBSOLETE */
+
+ /* get a '\0' terminated domainname */
+
+ /* read default domainname default from environment */
+ if (nLengthOfDomainName == 0)
+ {
+ sal_Char *pEnvDomain;
+
+ pEnvDomain = getenv ("STAR_OVERRIDE_DOMAINNAME");
+ if (pEnvDomain)
+ {
+ pDomainName = strdup (pEnvDomain);
+ nLengthOfDomainName = strlen (pDomainName);
+ }
+ }
+
+#if 1 /* NEW */
+ if (nLengthOfDomainName == 0)
+ {
+ sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ];
+
+ pDomainNameBuffer[0] = '\0';
+
+ if (_osl_getDomainName (pDomainNameBuffer, DOMAINNAME_LENGTH))
+ {
+ pDomainName = strdup (pDomainNameBuffer);
+ nLengthOfDomainName = strlen (pDomainName);
+ }
+ }
+
+#endif /* NEW */
+#if 0 /* OBSOLETE */
+#ifdef SCO
+
+ /* call 'domainname > /usr/tmp/some-tmp-file', since
+ popen read pclose do block or core-dump,
+ (even the pipe-stuff that comes with pthreads) */
+ if (nLengthOfDomainName == 0)
+ {
+ sal_Char tmp_name[ L_tmpnam ];
+ FILE *tmp_file;
+ sal_Char domain_call [ L_tmpnam + 16 ] = "domainname > ";
+
+ tmp_name[0] = '\0';
+
+ tmpnam ( tmp_name );
+ strcat ( domain_call, tmp_name );
+ if ( (system ( domain_call ) == 0)
+ && ((tmp_file = fopen( tmp_name, "r" )) != NULL ) )
+ {
+ sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ];
+
+ pDomainNameBuffer[0] = '\0';
+
+ if ( fgets ( pDomainNameBuffer, DOMAINNAME_LENGTH, tmp_file ) )
+ {
+ pDomainName = strdup( pDomainNameBuffer );
+ nLengthOfDomainName = strlen( pDomainName );
+ if ( ( nLengthOfDomainName > 0 )
+ && ( pDomainName[ nLengthOfDomainName - 1] == '\n' ) )
+ pDomainName[ --nLengthOfDomainName ] = '\0';
+ }
+ fclose ( tmp_file );
+ }
+ unlink( tmp_name );
+ }
+
+#else /* !SCO */
+
+ /* read the domainname from pipe to the program domainname */
+ if ( (nLengthOfDomainName == 0)
+ && (pPipeToDomainnameExe = popen( "domainname", "r")) )
+ {
+ sal_Char c;
+ sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ];
+ sal_Char *pDomainNamePointer;
+
+ pDomainNameBuffer[0] = '\0';
+
+ pDomainNamePointer = pDomainNameBuffer;
+ while ( ((c = getc( pPipeToDomainnameExe )) != EOF)
+ && (nLengthOfDomainName < (DOMAINNAME_LENGTH - 1)) )
+ {
+ if (! isspace(c))
+ {
+ nLengthOfDomainName++ ;
+ *pDomainNamePointer++ = (sal_Char)c;
+ }
+ }
+ *pDomainNamePointer = '\0';
+ pDomainName = strdup( pDomainNameBuffer );
+
+ pclose( pPipeToDomainnameExe );
+ }
+
+#endif /* !SCO */
+#endif /* OBSOLETE */
+
+ /* compose hostname and domainname */
+ nLengthOfHostName = strlen( pHostName );
+ pFullQualifiedName = (sal_Char*) malloc( (nLengthOfHostName + 1
+ + nLengthOfDomainName + 1) * sizeof(sal_Char) );
+ memcpy( pFullQualifiedName, pHostName,
+ (nLengthOfHostName + 1) * sizeof(sal_Char) );
+
+ if ( nLengthOfDomainName > 0 )
+ {
+ /* fqdn = hostname + '.' + domainname + '\0' */
+ pFullQualifiedName[ nLengthOfHostName ] = '.';
+ memcpy( pFullQualifiedName + nLengthOfHostName + 1, pDomainName,
+ nLengthOfDomainName + 1 );
+ }
+
+ /* check whether full-qualified name and hostname point to the same host
+ * should almost always be true */
+ if ( nLengthOfDomainName > 0 )
+ {
+ struct hostent *pQualifiedHostByName;
+ struct hostent *pHostByName;
+ sal_Bool bHostsAreEqual;
+
+ /* buffer for calls to reentrant version of gethostbyname */
+ struct hostent aHostByName, aQualifiedHostByName;
+ sal_Char pHostBuffer[ MAX_HOSTBUFFER_SIZE ];
+ sal_Char pQualifiedHostBuffer[ MAX_HOSTBUFFER_SIZE ];
+ int nErrorNo;
+
+ pHostBuffer[0] = '\0';
+ pQualifiedHostBuffer[0] = '\0';
+
+ /* get list of addresses */
+ pQualifiedHostByName = _osl_gethostbyname_r (
+ pFullQualifiedName,
+ &aQualifiedHostByName, pQualifiedHostBuffer,
+ sizeof(pQualifiedHostBuffer), &nErrorNo );
+ pHostByName = _osl_gethostbyname_r (
+ pHostName,
+ &aHostByName, pHostBuffer,
+ sizeof(pHostBuffer), &nErrorNo );
+
+ /* compare addresses */
+ bHostsAreEqual = sal_False;
+ if ( pQualifiedHostByName && pHostByName )
+ {
+ sal_Char **p, **q;
+ struct in_addr in;
+
+ /* lists are expected to be (very) short */
+ for ( p = pQualifiedHostByName->h_addr_list; *p != NULL; p++ )
+ {
+ for ( q = pHostByName->h_addr_list; *q != NULL; q++ )
+ {
+ /* in.s_addr may be in_addr_t or uint32_t or heaven knows */
+ if ( memcmp( *p, *q, sizeof(in.s_addr) ) == 0 )
+ {
+ bHostsAreEqual = sal_True;
+ break;
+ }
+ }
+ if ( bHostsAreEqual )
+ break;
+ }
+ }
+
+ /* very strange case, but have to believe it: reduce the
+ * full qualified name to the unqualified host name */
+ if ( !bHostsAreEqual )
+ {
+ OSL_TRACE("_osl_getFullQualifiedDomainName: "
+ "suspect FQDN: %s\n", pFullQualifiedName);
+
+ pFullQualifiedName[ nLengthOfHostName ] = '\0';
+ pFullQualifiedName = (sal_Char*)realloc ( pFullQualifiedName,
+ (nLengthOfHostName + 1) * sizeof( sal_Char ));
+ }
+ }
+
+ /* always return a hostname looked up as carefully as possible
+ * this string must be freed by the caller */
+ return pFullQualifiedName;
+}
+
+/*****************************************************************************/
+/* _osl_isFullQualifiedDomainName */
+/*****************************************************************************/
+static sal_Bool _osl_isFullQualifiedDomainName (const sal_Char *pHostName)
+{
+ /* a FQDN (aka 'hostname.domain.top_level_domain' )
+ * is a name which contains a dot '.' in it ( would
+ * match as well for 'hostname.' but is good enough
+ * for now )*/
+ return (sal_Bool)( strchr( pHostName, (int)'.' ) != NULL );
+}
+
+/*****************************************************************************/
+/* oslHostAddr */
+/*****************************************************************************/
+struct oslHostAddrImpl
+{
+ sal_Char *pHostName;
+ oslSocketAddr pSockAddr;
+};
+
+static oslHostAddr _osl_hostentToHostAddr (const struct hostent *he)
+{
+ oslHostAddr pAddr= NULL;
+ oslSocketAddr pSockAddr = 0;
+
+
+ if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL))
+ return ((oslHostAddr)NULL);
+
+ //YD 18/06/2006 win32 does this with unicode, see socket.cxx
+ sal_Char *cn;
+ cn= (sal_Char *)malloc(strlen (he->h_name) + 1);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+
+ strcpy(cn, he->h_name);
+
+#if 0 // YD 17/04/06 win32 doesn't it.
+ if (_osl_isFullQualifiedDomainName(he->h_name))
+ {
+ cn= (sal_Char *)malloc(strlen (he->h_name) + 1);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+
+ strcpy(cn, he->h_name);
+ }
+ else
+ {
+ cn =_osl_getFullQualifiedDomainName (he->h_name);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+ }
+#endif
+
+ pSockAddr = __osl_createSocketAddr();
+ OSL_ASSERT(pSockAddr);
+ if (pSockAddr == NULL)
+ {
+ free(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pSockAddr->m_sockaddr.sa_family= he->h_addrtype;
+ if (pSockAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ struct sockaddr_in *sin= (struct sockaddr_in *)&(pSockAddr->m_sockaddr);
+ memcpy (
+ &(sin->sin_addr.s_addr),
+ he->h_addr_list[0],
+ he->h_length);
+ }
+ else
+ {
+ /* unknown address family */
+ /* future extensions for new families might be implemented here */
+
+ OSL_TRACE("_osl_hostentToHostAddr: unknown address family.\n");
+ OSL_ASSERT(sal_False);
+
+ __osl_destroySocketAddr( pSockAddr );
+ free (cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
+ OSL_ASSERT(pAddr);
+ if (pAddr == NULL)
+ {
+ __osl_destroySocketAddr( pSockAddr );
+ free (cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr->pHostName= cn;
+ pAddr->pSockAddr= pSockAddr;
+
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddr (
+ rtl_uString *ustrHostname,
+ const oslSocketAddr Addr)
+{
+ oslHostAddr HostAddr;
+ rtl_String* strHostname=0;
+ sal_Char* pszHostName=0;
+
+ if ( ustrHostname != 0 )
+ {
+ rtl_uString2String( &strHostname,
+ rtl_uString_getStr(ustrHostname),
+ rtl_uString_getLength(ustrHostname),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszHostName = rtl_string_getStr(strHostname);
+ }
+
+ HostAddr = osl_psz_createHostAddr(pszHostName,Addr);
+
+ if ( strHostname != 0 )
+ {
+ rtl_string_release(strHostname);
+ }
+
+
+ return HostAddr;
+}
+
+oslHostAddr SAL_CALL osl_psz_createHostAddr (
+ const sal_Char *pszHostname,
+ const oslSocketAddr pAddr)
+{
+ oslHostAddr pHostAddr;
+ sal_Char *cn;
+
+ OSL_ASSERT(pszHostname && pAddr);
+ if ((pszHostname == NULL) || (pAddr == NULL))
+ return ((oslHostAddr)NULL);
+
+ cn = (sal_Char *)malloc(strlen (pszHostname) + 1);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+
+ strcpy (cn, pszHostname);
+
+ pHostAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
+ OSL_ASSERT(pHostAddr);
+ if (pAddr == NULL)
+ {
+ free (cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pHostAddr->pHostName= cn;
+ pHostAddr->pSockAddr= osl_copySocketAddr( pAddr );
+
+ return pHostAddr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByName */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *ustrHostname)
+{
+ oslHostAddr HostAddr;
+ rtl_String* strHostname=0;
+ sal_Char* pszHostName=0;
+
+ if ( ustrHostname != 0 )
+ {
+ rtl_uString2String( &strHostname,
+ rtl_uString_getStr(ustrHostname),
+ rtl_uString_getLength(ustrHostname),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszHostName=rtl_string_getStr(strHostname);
+ }
+
+ HostAddr = osl_psz_createHostAddrByName(pszHostName);
+
+ if ( strHostname != 0 )
+ {
+ rtl_string_release(strHostname);
+ }
+
+ return HostAddr;
+}
+
+oslHostAddr SAL_CALL osl_psz_createHostAddrByName (const sal_Char *pszHostname)
+{
+ struct hostent *he;
+ oslHostAddr addr;
+
+ static oslMutex mutex = NULL;
+
+ if (mutex == NULL)
+ mutex = osl_createMutex();
+
+ osl_acquireMutex(mutex);
+
+ he = gethostbyname((sal_Char *)pszHostname);
+ addr = _osl_hostentToHostAddr (he);
+
+ osl_releaseMutex(mutex);
+
+ return addr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByAddr (const oslSocketAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr == NULL)
+ return ((oslHostAddr)NULL);
+
+ if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ const struct sockaddr_in *sin= (const struct sockaddr_in *)&(pAddr->m_sockaddr);
+ struct hostent *he;
+
+ if (sin->sin_addr.s_addr == htonl(INADDR_ANY))
+ return ((oslHostAddr)NULL);
+
+ he= gethostbyaddr((sal_Char *)&(sin->sin_addr),
+ sizeof (sin->sin_addr),
+ sin->sin_family);
+ return _osl_hostentToHostAddr (he);
+ }
+
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_copyHostAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_copyHostAddr (const oslHostAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return osl_psz_createHostAddr (pAddr->pHostName, pAddr->pSockAddr);
+ else
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_getHostnameOfHostAddr (
+ const oslHostAddr Addr,
+ rtl_uString **ustrHostname)
+{
+ const sal_Char* pHostname=0;
+
+ pHostname = osl_psz_getHostnameOfHostAddr(Addr);
+
+ rtl_uString_newFromAscii (ustrHostname, pHostname);
+
+ return;
+}
+
+const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (const oslHostAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return pAddr->pHostName;
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_getSocketAddrOfHostAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr (const oslHostAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return ((oslSocketAddr)(pAddr->pSockAddr));
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_destroyHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_destroyHostAddr (oslHostAddr pAddr)
+{
+ if (pAddr)
+ {
+ if (pAddr->pHostName)
+ free (pAddr->pHostName);
+ if (pAddr->pSockAddr)
+ osl_destroySocketAddr (pAddr->pSockAddr);
+ free (pAddr);
+ }
+}
+
+/*****************************************************************************/
+/* osl_getLocalHostname */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getLocalHostname(rtl_uString **ustrLocalHostname)
+{
+ oslSocketResult Result;
+ sal_Char pszHostname[1024];
+
+ pszHostname[0] = '\0';
+
+ Result = osl_psz_getLocalHostname(pszHostname,sizeof(pszHostname));
+
+ rtl_uString_newFromAscii(ustrLocalHostname,pszHostname);
+
+ return Result;
+}
+
+oslSocketResult SAL_CALL osl_psz_getLocalHostname (
+ sal_Char *pBuffer, sal_uInt32 nBufLen)
+{
+ static sal_Char LocalHostname[256] = "";
+
+ if (strlen(LocalHostname) == 0)
+ {
+ const sal_Char *pStr;
+
+#ifdef SYSV
+ struct utsname uts;
+
+ if (uname(&uts) < 0)
+ return osl_Socket_Error;
+
+ if ((strlen(uts.nodename) + 1) > nBufLen)
+ return osl_Socket_Error;
+
+ strncpy(LocalHostname, uts.nodename, sizeof( LocalHostname ));
+#else /* BSD compatible */
+
+ if (gethostname(LocalHostname, sizeof(LocalHostname)-1) != 0)
+ return osl_Socket_Error;
+ LocalHostname[sizeof(LocalHostname)-1] = 0;
+#endif /* SYSV */
+
+ /* check if we have an FQDN */
+ if (strchr(LocalHostname, '.') == NULL)
+ {
+ oslHostAddr Addr;
+
+ /* no, determine it via dns */
+ Addr = osl_psz_createHostAddrByName(LocalHostname);
+
+ if (Addr && (pStr = osl_psz_getHostnameOfHostAddr(Addr)) != NULL)
+ {
+#if 0 /* OBSOLETE */
+ sal_Char* pChr;
+#endif /* OBSOLETE */
+ strcpy(LocalHostname, pStr);
+
+#if 0 /* OBSOLETE */
+ /* already done by _osl_getFullQualifiedDomainName() with
+ much better heuristics, so this may be contraproductive */
+
+ /* no FQDN, last try append domain name */
+ if ((pChr = strchr(LocalHostname, '.')) == NULL)
+ {
+ FILE *fp;
+
+ pChr = &LocalHostname[strlen(LocalHostname)];
+
+ if ( (fp = popen("domainname", "r")) != 0 )
+ {
+ int c;
+
+ *pChr++ = '.';
+
+ while ((c = getc(fp)) != EOF)
+ {
+ if (! isspace(c))
+ *pChr++ = (sal_Char)c;
+ }
+
+ *pChr = '\0';
+
+ fclose(fp);
+ }
+ else
+ LocalHostname[0] = '\0';
+ }
+#endif /* OBSOLETE */
+
+ }
+ if (Addr)
+ osl_destroyHostAddr(Addr);
+ }
+ }
+
+ if (strlen(LocalHostname) > 0)
+ {
+ strncpy(pBuffer, LocalHostname, nBufLen);
+ pBuffer[nBufLen - 1] = '\0';
+
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_resolveHostname */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString *ustrHostname)
+{
+ oslSocketAddr Addr;
+ rtl_String* strHostname=0;
+ sal_Char* pszHostName=0;
+
+ if ( ustrHostname != 0 )
+ {
+ rtl_uString2String( &strHostname,
+ rtl_uString_getStr(ustrHostname),
+ rtl_uString_getLength(ustrHostname),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszHostName = rtl_string_getStr(strHostname);
+ }
+
+
+ Addr = osl_psz_resolveHostname(pszHostName);
+
+ if ( strHostname != 0 )
+ {
+ rtl_string_release(strHostname);
+ }
+
+
+ return Addr;
+}
+
+
+oslSocketAddr SAL_CALL osl_psz_resolveHostname(const sal_Char* pszHostname)
+{
+ struct oslHostAddrImpl *pAddr = (oslHostAddr)osl_psz_createHostAddrByName(pszHostname);
+
+ if (pAddr)
+ {
+ oslSocketAddr SockAddr = osl_copySocketAddr(pAddr->pSockAddr);
+
+ osl_destroyHostAddr(pAddr);
+
+ return (SockAddr);
+ }
+
+ return ((oslSocketAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_getServicePort */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getServicePort(rtl_uString *ustrServicename, rtl_uString *ustrProtocol)
+{
+ sal_Int32 nPort;
+ rtl_String* strServicename=0;
+ rtl_String* strProtocol=0;
+ sal_Char* pszServiceName=0;
+ sal_Char* pszProtocol=0;
+
+ if ( ustrServicename != 0 )
+ {
+ rtl_uString2String( &strServicename,
+ rtl_uString_getStr(ustrServicename),
+ rtl_uString_getLength(ustrServicename),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszServiceName = rtl_string_getStr(strServicename);
+ }
+
+ if ( ustrProtocol != 0 )
+ {
+ rtl_uString2String( &strProtocol,
+ rtl_uString_getStr(ustrProtocol),
+ rtl_uString_getLength(ustrProtocol),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszProtocol = rtl_string_getStr(strProtocol);
+ }
+
+ nPort = osl_psz_getServicePort(pszServiceName,pszProtocol);
+
+ if ( strServicename != 0 )
+ {
+ rtl_string_release(strServicename);
+ }
+
+ if ( strProtocol != 0 )
+ {
+ rtl_string_release(strProtocol);
+ }
+
+
+ return nPort;
+}
+
+
+sal_Int32 SAL_CALL osl_psz_getServicePort(const sal_Char* pszServicename,
+ const sal_Char* pszProtocol)
+{
+ struct servent* ps;
+
+ ps= getservbyname(pszServicename, pszProtocol);
+
+ if (ps != 0)
+ return ntohs(ps->s_port);
+
+ return OSL_INVALID_PORT;
+}
+
+/*****************************************************************************/
+/* osl_destroySocketAddr */
+/*****************************************************************************/
+void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr)
+{
+ __osl_destroySocketAddr( pAddr );
+}
+
+/*****************************************************************************/
+/* osl_getFamilyOfSocketAddr */
+/*****************************************************************************/
+oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family);
+ else
+ return osl_Socket_FamilyInvalid;
+}
+
+/*****************************************************************************/
+/* osl_getInetPortOfSocketAddr */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ return ntohs(pSystemInetAddr->sin_port);
+ }
+ return OSL_INVALID_PORT;
+}
+
+/*****************************************************************************/
+/* osl_setInetPortOfSocketAddr */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setInetPortOfSocketAddr(oslSocketAddr pAddr, sal_Int32 Port)
+{
+ OSL_ASSERT(pAddr);
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+ if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ pSystemInetAddr->sin_port= htons((short)Port);
+ return sal_True;
+ }
+ }
+
+ /* this is not a inet-addr => can't set port */
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrHostname)
+{
+ oslSocketResult Result;
+ sal_Char pszHostname[1024];
+
+ pszHostname[0] = '\0';
+
+ Result = osl_psz_getHostnameOfSocketAddr(Addr,pszHostname,sizeof(pszHostname));
+
+ rtl_uString_newFromAscii(ustrHostname,pszHostname);
+
+ return Result;
+}
+
+
+oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr(oslSocketAddr pAddr,
+ sal_Char *pBuffer, sal_uInt32 BufferSize)
+{
+ oslHostAddr pHostAddr= (oslHostAddr )osl_createHostAddrByAddr(pAddr);
+
+ if (pHostAddr)
+ {
+ strncpy(pBuffer, pHostAddr->pHostName, BufferSize);
+
+ pBuffer[BufferSize - 1] = '\0';
+
+ osl_destroyHostAddr(pHostAddr);
+
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_getDottedInetAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrDottedInetAddr)
+{
+ oslSocketResult Result;
+ sal_Char pszDottedInetAddr[1024];
+
+ pszDottedInetAddr[0] = '\0';
+
+ Result = osl_psz_getDottedInetAddrOfSocketAddr(Addr,pszDottedInetAddr,sizeof(pszDottedInetAddr));
+
+ rtl_uString_newFromAscii(ustrDottedInetAddr,pszDottedInetAddr);
+
+ return Result;
+
+}
+
+oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr(oslSocketAddr pAddr,
+ sal_Char *pBuffer, sal_uInt32 BufferSize)
+{
+ OSL_ASSERT(pAddr);
+
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr = ( struct sockaddr_in * ) &(pAddr->m_sockaddr);
+
+ if (pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ strncpy(pBuffer, inet_ntoa(pSystemInetAddr->sin_addr), BufferSize);
+ pBuffer[BufferSize - 1] = '\0';
+
+ return osl_Socket_Ok;
+ }
+ }
+
+ return osl_Socket_Error;
+}
+
+#if 0 /* OBSOLETE */
+/*****************************************************************************/
+/* osl_getIpxNetNumber */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getIpxNetNumber(oslSocketAddr Addr,
+ oslSocketIpxNetNumber NetNumber)
+
+{
+ struct sockaddr_ipx* pAddr;
+
+ pAddr= (struct sockaddr_ipx*)Addr;
+
+ OSL_ASSERT(pAddr);
+
+ if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx)))
+ {
+ memcpy(NetNumber, pAddr->sa_netnum, sizeof(NetNumber));
+
+ return osl_Socket_Ok;
+ }
+ else
+ return osl_Socket_Error;
+}
+
+
+/*****************************************************************************/
+/* osl_getIpxNodeNumber */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getIpxNodeNumber(oslSocketAddr Addr,
+ oslSocketIpxNodeNumber NodeNumber)
+
+{
+ struct sockaddr_ipx* pAddr;
+
+ pAddr= (struct sockaddr_ipx*)Addr;
+
+ OSL_ASSERT(pAddr);
+
+ if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx)))
+ {
+ memcpy(NodeNumber, pAddr->sa_nodenum, sizeof(NodeNumber));
+
+ return osl_Socket_Ok;
+ }
+ else
+ return osl_Socket_Error;
+}
+
+
+/*****************************************************************************/
+/* osl_getIpxSocketNumber */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getIpxSocketNumber(oslSocketAddr Addr)
+{
+ struct sockaddr_ipx* pAddr= (struct sockaddr_ipx*)Addr;
+ OSL_ASSERT(pAddr);
+
+ if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx)))
+ return pAddr->sa_socket;
+ else
+ return OSL_INVALID_IPX_SOCKET_NO;
+}
+
+#endif /* OBSOLETE */
+
+/*****************************************************************************/
+/* osl_createSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_createSocket(oslAddrFamily Family,
+ oslSocketType Type,
+ oslProtocol Protocol)
+{
+ int Flags;
+ oslSocket pSocket;
+
+ /* alloc memory */
+ pSocket= __osl_createSocketImpl(OSL_INVALID_SOCKET);
+
+ /* create socket */
+ pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family),
+ TYPE_TO_NATIVE(Type),
+ PROTOCOL_TO_NATIVE(Protocol));
+
+ /* creation failed => free memory */
+ if(pSocket->m_Socket == OSL_INVALID_SOCKET)
+ {
+ OSL_TRACE("osl_createSocket failed. Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+
+ __osl_destroySocketImpl((pSocket));
+ pSocket= 0;
+ }
+ else
+ {
+ /* set close-on-exec flag */
+ if ((Flags = fcntl(pSocket->m_Socket, F_GETFD, 0)) != -1)
+ {
+ Flags |= FD_CLOEXEC;
+ if (fcntl(pSocket->m_Socket, F_SETFD, Flags) == -1)
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_createSocket failed changing socket flags. Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+ }
+ }
+ else
+ {
+ pSocket->m_nLastError=errno;
+ }
+
+
+ pSocket->m_CloseCallback = NULL;
+ pSocket->m_CallbackArg = NULL;
+ }
+
+ return pSocket;
+}
+
+void SAL_CALL osl_acquireSocket(oslSocket pSocket)
+{
+ osl_incrementInterlockedCount( &(pSocket->m_nRefCount ) );
+}
+
+void SAL_CALL osl_releaseSocket( oslSocket pSocket )
+{
+ if( pSocket && 0 == osl_decrementInterlockedCount( &(pSocket->m_nRefCount) ) )
+ {
+#if defined(LINUX)
+ if ( pSocket->m_bIsAccepting == sal_True )
+ {
+ OSL_ENSURE(0, "osl_destroySocket : attempt to destroy socket while accepting\n");
+ return;
+ }
+#endif /* LINUX */
+ osl_closeSocket( pSocket );
+ __osl_destroySocketImpl( pSocket );
+ }
+}
+
+
+
+/*****************************************************************************/
+/* osl_closeSocket */
+/*****************************************************************************/
+void SAL_CALL osl_closeSocket(oslSocket pSocket)
+{
+ int nRet;
+ int nFD;
+
+ /* socket already invalid */
+ if(pSocket==0)
+ return;
+
+ pSocket->m_nLastError=0;
+ nFD = pSocket->m_Socket;
+
+ pSocket->m_Socket = OSL_INVALID_SOCKET;
+
+#if defined(LINUX)
+ pSocket->m_bIsInShutdown = sal_True;
+
+ if ( pSocket->m_bIsAccepting == sal_True )
+ {
+ int nConnFD;
+ struct sockaddr aSockAddr;
+ socklen_t nSockLen = sizeof(aSockAddr);
+
+ nRet = getsockname(nFD, &aSockAddr, &nSockLen);
+#if OSL_DEBUG_LEVEL > 1
+ if ( nRet < 0 )
+ {
+ perror("getsockname");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+
+ if ( aSockAddr.sa_family == AF_INET )
+ {
+ struct sockaddr_in* pSockAddrIn = (struct sockaddr_in*) &aSockAddr;
+
+ if ( pSockAddrIn->sin_addr.s_addr == htonl(INADDR_ANY) )
+ {
+ pSockAddrIn->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
+
+ nConnFD = socket(AF_INET, SOCK_STREAM, 0);
+#if OSL_DEBUG_LEVEL > 1
+ if ( nConnFD < 0 )
+ {
+ perror("socket");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+
+ nRet = connect(nConnFD, &aSockAddr, sizeof(aSockAddr));
+#if OSL_DEBUG_LEVEL > 1
+ if ( nRet < 0 )
+ {
+ perror("connect");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+ close(nConnFD);
+ }
+ }
+#endif /* LINUX */
+
+ /* registrierten Callback ausfuehren */
+ if (pSocket->m_CloseCallback != NULL)
+ {
+ pSocket->m_CloseCallback(pSocket->m_CallbackArg);
+ }
+
+ nRet=close(nFD);
+ if ( nRet != 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("closeSocket close error '%s'\n",strerror(errno));
+ }
+
+ pSocket->m_Socket = OSL_INVALID_SOCKET;
+}
+
+/*****************************************************************************/
+/* osl_getLocalAddrOfSocket */
+/* Note that I rely on the fact that oslSocketAddr and struct sockaddr */
+/* are the same! I don't like it very much but see no other easy way to conceal */
+/* the struct sockaddr from the eyes of the user. */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket)
+{
+#if defined(LINUX) || defined(FREEBSD)
+ socklen_t AddrLen;
+#else
+ /* mfe: Solaris 'cc +w' means Addrlen should be signed! */
+ /* it's really defined as 'int*' in /usr/include/sys/socket.h! */
+ /* the man page says it expects a 'size_t' */
+ int AddrLen;
+#endif
+ struct sockaddr Addr;
+ oslSocketAddr pAddr;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return ((oslSocketAddr)NULL);
+
+ AddrLen= sizeof(struct sockaddr);
+
+ if (getsockname(pSocket->m_Socket, &Addr, PTR_SIZE_T(AddrLen)) == OSL_SOCKET_ERROR)
+ return ((oslSocketAddr)NULL);
+
+ pAddr = __osl_createSocketAddrFromSystem( &Addr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_getPeerAddrOfSocket */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
+{
+ sal_uInt32 AddrLen;
+ struct sockaddr Addr;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return 0;
+ }
+
+ pSocket->m_nLastError=0;
+ AddrLen= sizeof(struct sockaddr);
+
+ if(getpeername(pSocket->m_Socket, &Addr, (int*)PTR_SIZE_T(AddrLen)) == OSL_SOCKET_ERROR)
+ {
+ pSocket->m_nLastError=errno;
+ return 0;
+ }
+ return __osl_createSocketAddrFromSystem( &Addr );
+}
+
+/*****************************************************************************/
+/* osl_bindAddrToSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_bindAddrToSocket(oslSocket pSocket,
+ oslSocketAddr pAddr)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket && pAddr );
+ if ( pSocket == 0 || pAddr == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet = bind(pSocket->m_Socket, &(pAddr->m_sockaddr), sizeof(struct sockaddr));
+
+ if ( nRet == OSL_SOCKET_ERROR)
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+
+/*****************************************************************************/
+/* osl_listenOnSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_listenOnSocket(oslSocket pSocket,
+ sal_Int32 MaxPendingConnections)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet = listen(pSocket->m_Socket,
+ MaxPendingConnections == -1 ?
+ SOMAXCONN :
+ MaxPendingConnections);
+ if ( nRet == OSL_SOCKET_ERROR)
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+
+/*****************************************************************************/
+/* osl_connectSocketTo */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_connectSocketTo(oslSocket pSocket,
+ oslSocketAddr pAddr,
+ const TimeValue* pTimeout)
+{
+ fd_set WriteSet;
+ fd_set ExcptSet;
+ int ReadyHandles;
+ struct timeval tv;
+ oslSocketResult Result= osl_Socket_Ok;
+
+ OSL_PRECOND(pSocket, "osl_connectSocketTo(): need a valid socket!\n");
+
+ if ( pSocket == 0 )
+ {
+ return osl_Socket_Error;
+ }
+
+ pSocket->m_nLastError=0;
+
+ if (osl_isNonBlockingMode(pSocket))
+ {
+ if (connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
+ return osl_Socket_Ok;
+ else
+ if (errno == EWOULDBLOCK || errno == EINPROGRESS)
+ {
+ pSocket->m_nLastError=EINPROGRESS;
+ return osl_Socket_InProgress;
+ }
+
+
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("can't connect : '%s'",strerror(errno));
+ return osl_Socket_Error;
+ }
+
+ /* set socket temporarily to non-blocking */
+ OSL_VERIFY(osl_enableNonBlockingMode(pSocket, sal_True));
+
+ /* initiate connect */
+ if(connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
+ {
+ /* immediate connection */
+ osl_enableNonBlockingMode(pSocket, sal_False);
+
+ return osl_Socket_Ok;
+ }
+ else
+ {
+ /* really an error or just delayed? */
+ if (errno != EINPROGRESS)
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE(
+ "osl_connectSocketTo(): connect failed: errno: %d (%s)\n",
+ errno, strerror(errno));
+
+ osl_enableNonBlockingMode(pSocket, sal_False);
+ return osl_Socket_Error;
+ }
+ }
+
+
+ /* prepare select set for socket */
+ FD_ZERO(&WriteSet);
+ FD_ZERO(&ExcptSet);
+ FD_SET(pSocket->m_Socket, &WriteSet);
+ FD_SET(pSocket->m_Socket, &ExcptSet);
+
+ /* prepare timeout */
+ if (pTimeout)
+ {
+ /* divide milliseconds into seconds and microseconds */
+ tv.tv_sec= pTimeout->Seconds;
+ tv.tv_usec= pTimeout->Nanosec / 1000L;
+ }
+
+ /* select */
+ ReadyHandles= select(pSocket->m_Socket+1,
+ 0,
+ PTR_FD_SET(WriteSet),
+ PTR_FD_SET(ExcptSet),
+ (pTimeout) ? &tv : 0);
+
+ if (ReadyHandles > 0) /* connected */
+ {
+ if ( FD_ISSET(pSocket->m_Socket, &WriteSet ) )
+ {
+ int nErrorCode = 0;
+#ifdef SOLARIS
+/* mfe: Solaris 'cc +w' means 5th argument should be a 'int*'!
+ it's really defined as 'int*' in /usr/include/sys/socket.h!
+ the man page says it expects a 'size_t*'
+*/
+ int nErrorSize = sizeof( nErrorCode );
+#else
+ size_t nErrorSize = sizeof( nErrorCode );
+#endif
+
+ int nSockOpt;
+
+ nSockOpt = getsockopt ( pSocket->m_Socket, SOL_SOCKET, SO_ERROR,
+#ifdef SOLARIS
+/* mfe: Solaris 'cc +w' means 4th argument should be a 'char*'!
+ it's really defined as 'char*' in /usr/include/sys/socket.h!
+ the man page says it expects a 'void*'
+*/
+ (char*)
+#endif
+ &nErrorCode, (int*)&nErrorSize );
+ if ( (nSockOpt == 0) && (nErrorCode == 0))
+ Result = osl_Socket_Ok;
+ else
+ Result = osl_Socket_Error;
+ }
+ else
+ {
+ Result= osl_Socket_Error;
+ }
+ }
+ else if (ReadyHandles < 0) /* error */
+ {
+ if (errno == EBADF) /* most probably interrupted by close() */
+ {
+ /* do not access pSockImpl because it is about to be or */
+ /* already destroyed */
+ return osl_Socket_Interrupted;
+ }
+ else
+ {
+ pSocket->m_nLastError=errno;
+ Result= osl_Socket_Error;
+ }
+ }
+ else /* timeout */
+ {
+ pSocket->m_nLastError=errno;
+ Result= osl_Socket_TimedOut;
+ }
+
+ osl_enableNonBlockingMode(pSocket, sal_False);
+
+ return Result;
+}
+
+
+/*****************************************************************************/
+/* osl_acceptConnectionOnSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_acceptConnectionOnSocket(oslSocket pSocket,
+ oslSocketAddr* ppAddr)
+{
+ struct sockaddr Addr;
+ int Connection, Flags;
+ sal_uInt32 AddrLen = sizeof(struct sockaddr);
+ oslSocket pConnectionSockImpl;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return 0;
+ }
+
+ pSocket->m_nLastError=0;
+#if defined(LINUX)
+ pSocket->m_bIsAccepting = sal_True;
+#endif /* LINUX */
+
+ if( ppAddr && *ppAddr )
+ {
+ osl_destroySocketAddr( *ppAddr );
+ *ppAddr = 0;
+ }
+
+ /* prevent Linux EINTR behaviour */
+ do
+ {
+ Connection = accept(pSocket->m_Socket, &Addr, (int*)PTR_SIZE_T(AddrLen));
+ } while (Connection == -1 && errno == EINTR);
+
+
+ /* accept failed? */
+ if( Connection == OSL_SOCKET_ERROR )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_acceptConnectionOnSocket : accept error '%s'\n",strerror(errno));
+
+#if defined(LINUX)
+ pSocket->m_bIsAccepting = sal_False;
+#endif /* LINUX */
+ return 0;
+ }
+
+ OSL_ASSERT(AddrLen == sizeof(struct sockaddr));
+
+
+#if defined(LINUX)
+ if ( pSocket->m_bIsInShutdown == sal_True )
+ {
+ close(Connection);
+ OSL_TRACE("osl_acceptConnectionOnSocket : close while accept\n");
+ return 0;
+ }
+#endif /* LINUX */
+
+
+ if(ppAddr)
+ {
+ *ppAddr= __osl_createSocketAddrFromSystem(&Addr);
+ }
+
+ /* alloc memory */
+ pConnectionSockImpl= __osl_createSocketImpl(OSL_INVALID_SOCKET);
+
+ /* set close-on-exec flag */
+ if ((Flags = fcntl(Connection, F_GETFD, 0)) != -1)
+ {
+ Flags |= FD_CLOEXEC;
+ if (fcntl(Connection, F_SETFD, Flags) == -1)
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_acceptConnectionOnSocket failed changing socket flags. Errno: %d (%s)\n",
+ errno,
+ strerror(errno));
+ }
+
+ }
+
+ pConnectionSockImpl->m_Socket = Connection;
+ pConnectionSockImpl->m_nLastError = 0;
+ pConnectionSockImpl->m_CloseCallback = NULL;
+ pConnectionSockImpl->m_CallbackArg = NULL;
+#if defined(LINUX)
+ pConnectionSockImpl->m_bIsAccepting = sal_False;
+
+ pSocket->m_bIsAccepting = sal_False;
+#endif /* LINUX */
+ return pConnectionSockImpl;
+}
+
+/*****************************************************************************/
+/* osl_receiveSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveSocket(oslSocket pSocket,
+ void* pBuffer,
+ sal_uInt32 BytesToRead,
+ oslSocketMsgFlag Flag)
+{
+ int nRead;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_receiveSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ do
+ {
+ nRead = recv(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToRead,
+ MSG_FLAG_TO_NATIVE(Flag));
+ } while ( nRead < 0 && errno == EINTR );
+
+ if ( nRead < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,strerror(errno));
+ }
+ else if ( nRead == 0 )
+ {
+ OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
+ }
+
+ return nRead;
+}
+
+
+/*****************************************************************************/
+/* osl_receiveFromSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveFromSocket(oslSocket pSocket,
+ oslSocketAddr pSenderAddr,
+ void* pBuffer,
+ sal_uInt32 BufferSize,
+ oslSocketMsgFlag Flag)
+{
+ int nRead;
+ struct sockaddr *pSystemSockAddr = 0;
+ int AddrLen = 0;
+ if( pSenderAddr )
+ {
+ AddrLen = sizeof( struct sockaddr );
+ pSystemSockAddr = &(pSenderAddr->m_sockaddr);
+ }
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_receiveFromSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRead = recvfrom(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BufferSize,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ PTR_SIZE_T(AddrLen));
+
+ if ( nRead < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_receiveFromSocket failed : %i '%s'",nRead,strerror(errno));
+ }
+ else if ( nRead == 0 )
+ {
+ OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
+ }
+
+ return nRead;
+}
+
+
+/*****************************************************************************/
+/* osl_sendSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendSocket(oslSocket pSocket,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ int nWritten;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_sendSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ do
+ {
+ nWritten = send(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag));
+ } while ( nWritten < 0 && errno == EINTR );
+
+
+ if ( nWritten < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,strerror(errno));
+ }
+ else if ( nWritten == 0 )
+ {
+ OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,"EOL");
+ }
+
+ return nWritten;
+}
+
+/*****************************************************************************/
+/* osl_sendToSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendToSocket(oslSocket pSocket,
+ oslSocketAddr ReceiverAddr,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ int nWritten;
+
+ struct sockaddr *pSystemSockAddr = 0;
+ int AddrLen = 0;
+ if( ReceiverAddr )
+ {
+ pSystemSockAddr = &(ReceiverAddr->m_sockaddr);
+ AddrLen = sizeof( struct sockaddr );
+ }
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_sendToSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ /* ReceiverAddr might be 0 when used on a connected socket. */
+ /* Then sendto should behave like send. */
+
+ nWritten = sendto(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ AddrLen);
+
+ if ( nWritten < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,strerror(errno));
+ }
+ else if ( nWritten == 0 )
+ {
+ OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,"EOL");
+ }
+
+ return nWritten;
+}
+
+/*****************************************************************************/
+/* osl_readSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_readSocket (
+ oslSocket pSocket, void *pBuffer, sal_Int32 n )
+{
+ sal_uInt8 * Ptr = (sal_uInt8 *)pBuffer;
+ sal_uInt32 BytesRead= 0;
+ sal_uInt32 BytesToRead= n;
+
+ OSL_ASSERT( pSocket);
+
+ /* loop until all desired bytes were read or an error occured */
+ while (BytesToRead > 0)
+ {
+ sal_Int32 RetVal;
+ RetVal= osl_receiveSocket(pSocket,
+ Ptr,
+ BytesToRead,
+ osl_Socket_MsgNormal);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToRead -= RetVal;
+ BytesRead += RetVal;
+ Ptr += RetVal;
+ }
+
+ return BytesRead;
+}
+
+/*****************************************************************************/
+/* osl_writeSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_writeSocket(
+ oslSocket pSocket, const void *pBuffer, sal_Int32 n )
+{
+ /* loop until all desired bytes were send or an error occured */
+ sal_uInt32 BytesSend= 0;
+ sal_uInt32 BytesToSend= n;
+ sal_uInt8 *Ptr = ( sal_uInt8 * )pBuffer;
+
+ OSL_ASSERT( pSocket );
+
+ while (BytesToSend > 0)
+ {
+ sal_Int32 RetVal;
+
+ RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToSend -= RetVal;
+ BytesSend += RetVal;
+ Ptr += RetVal;
+
+ }
+ return BytesSend;
+}
+
+/*****************************************************************************/
+/* __osl_socket_poll */
+/*****************************************************************************/
+
+#ifdef HAVE_POLL_H /* poll() */
+
+sal_Bool __osl_socket_poll (
+ oslSocket pSocket,
+ const TimeValue* pTimeout,
+ short nEvent)
+{
+ struct pollfd fds;
+ int timeout;
+ int result;
+
+ OSL_ASSERT(pSocket);
+ pSocket->m_nLastError = 0;
+
+ fds.fd = pSocket->m_Socket;
+ fds.events = nEvent;
+ fds.revents = 0;
+
+ timeout = -1;
+ if (pTimeout)
+ {
+ /* Convert to [ms] */
+ timeout = pTimeout->Seconds * 1000;
+ timeout += pTimeout->Nanosec / (1000 * 1000);
+ }
+
+ result = poll (&fds, 1, timeout);
+ if (result < 0)
+ {
+ pSocket->m_nLastError = errno;
+ OSL_TRACE("__osl_socket_poll(): poll error: %d (%s)",
+ errno, strerror(errno));
+ return sal_False;
+ }
+ if (result == 0)
+ {
+ /* Timeout */
+ return sal_False;
+ }
+
+ return ((fds.revents & nEvent) == nEvent);
+}
+
+#else /* select() */
+
+sal_Bool __osl_socket_poll (
+ oslSocket pSocket,
+ const TimeValue* pTimeout,
+ short nEvent)
+{
+ fd_set fds;
+ struct timeval tv;
+ int result;
+
+ OSL_ASSERT(pSocket);
+ pSocket->m_nLastError = 0;
+
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ if (pTimeout)
+ {
+ /* Convert to 'timeval' */
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000;
+ }
+
+ result = select (
+ pSocket->m_Socket + 1,
+ (nEvent == POLLIN ) ? PTR_FD_SET(fds) : NULL,
+ (nEvent == POLLOUT) ? PTR_FD_SET(fds) : NULL,
+ (nEvent == POLLPRI) ? PTR_FD_SET(fds) : NULL,
+ (pTimeout) ? &tv : NULL);
+
+ if (result < 0)
+ {
+ pSocket->m_nLastError = errno;
+ OSL_TRACE("__osl_socket_poll(): select error: %d (%s)",
+ errno, strerror(errno));
+ return sal_False;
+ }
+ if (result == 0)
+ {
+ /* Timeout */
+ return sal_False;
+ }
+
+ return (FD_ISSET(pSocket->m_Socket, &fds) ? sal_True : sal_False);
+}
+
+#endif /* HAVE_POLL_H */
+
+/*****************************************************************************/
+/* osl_isReceiveReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isReceiveReady (
+ oslSocket pSocket, const TimeValue* pTimeout)
+{
+ OSL_ASSERT(pSocket);
+ if (pSocket == NULL)
+ {
+ /* ENOTSOCK */
+ return sal_False;
+ }
+
+ return __osl_socket_poll (pSocket, pTimeout, POLLIN);
+}
+
+/*****************************************************************************/
+/* osl_isSendReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isSendReady (
+ oslSocket pSocket, const TimeValue* pTimeout)
+{
+ OSL_ASSERT(pSocket);
+ if (pSocket == NULL)
+ {
+ /* ENOTSOCK */
+ return sal_False;
+ }
+
+ return __osl_socket_poll (pSocket, pTimeout, POLLOUT);
+}
+
+/*****************************************************************************/
+/* osl_isExceptionPending */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isExceptionPending (
+ oslSocket pSocket, const TimeValue* pTimeout)
+{
+ OSL_ASSERT(pSocket);
+ if (pSocket == NULL)
+ {
+ /* ENOTSOCK */
+ return sal_False;
+ }
+
+ return __osl_socket_poll (pSocket, pTimeout, POLLPRI);
+}
+
+/*****************************************************************************/
+/* osl_shutdownSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_shutdownSocket(oslSocket pSocket,
+ oslSocketDirection Direction)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet=shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction));
+ if (nRet != 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("shutdown error '%s'\n",strerror(errno));
+ }
+ return (nRet==0);
+}
+
+
+/*****************************************************************************/
+/* osl_getSocketOption */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getSocketOption(oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ if(getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ (int*)PTR_SIZE_T(BufferLen)) == -1)
+ {
+ pSocket->m_nLastError=errno;
+ return -1;
+ }
+
+ return BufferLen;
+}
+
+/*****************************************************************************/
+/* osl_setSocketOption */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setSocketOption(oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet = setsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ BufferLen);
+
+ if ( nRet < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_enableNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_enableNonBlockingMode(oslSocket pSocket,
+ sal_Bool On)
+{
+ int flags;
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
+
+ if (On)
+ flags |= O_NONBLOCK;
+ else
+ flags &= ~(O_NONBLOCK);
+
+ nRet = fcntl(pSocket->m_Socket, F_SETFL, flags);
+
+ if ( nRet < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_isNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket)
+{
+ int flags;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
+
+ if (flags == -1 || !(flags & O_NONBLOCK))
+ return sal_False;
+ else
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_getSocketType */
+/*****************************************************************************/
+oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket)
+{
+ int Type=0;
+ sal_uInt32 TypeSize= sizeof(Type);
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return osl_Socket_TypeInvalid;
+ }
+
+ pSocket->m_nLastError=0;
+
+ if(getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket),
+ OPTION_TO_NATIVE(osl_Socket_OptionType),
+ (sal_Char*)&Type,
+ (int*)PTR_SIZE_T(TypeSize)) == -1)
+ {
+ /* error */
+ pSocket->m_nLastError=errno;
+ return osl_Socket_TypeInvalid;
+ }
+
+ return TYPE_FROM_NATIVE(Type);
+
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketErrorDescription */
+/*****************************************************************************/
+void SAL_CALL osl_getLastSocketErrorDescription(oslSocket Socket, rtl_uString **ustrError)
+{
+ sal_Char pszError[1024];
+
+ pszError[0] = '\0';
+
+ osl_psz_getLastSocketErrorDescription(Socket,pszError,sizeof(pszError));
+
+ rtl_uString_newFromAscii(ustrError,pszError);
+
+ return;
+}
+
+
+void SAL_CALL osl_psz_getLastSocketErrorDescription(oslSocket pSocket, sal_Char* pBuffer, sal_uInt32 BufferSize)
+{
+ /* make shure pBuffer will be a zero-terminated string even when strncpy has to cut */
+ pBuffer[BufferSize-1]= '\0';
+
+ if ( pSocket == 0 )
+ {
+ strncpy(pBuffer, strerror(EINVAL), BufferSize-1);
+ return;
+ }
+
+ strncpy(pBuffer, strerror(pSocket->m_nLastError), BufferSize-1);
+ return;
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketError */
+/*****************************************************************************/
+oslSocketError SAL_CALL osl_getLastSocketError(oslSocket pSocket)
+{
+ if ( pSocket == 0 )
+ {
+ return ERROR_FROM_NATIVE(EINVAL);
+ }
+
+ return ERROR_FROM_NATIVE(pSocket->m_nLastError);
+}
+
+/*****************************************************************************/
+/* SocketSet */
+/*****************************************************************************/
+typedef struct _TSocketSetImpl
+{
+ int m_MaxHandle; /* for select(), the largest descriptor in the set */
+ fd_set m_Set; /* the set of descriptors */
+
+} TSocketSetImpl;
+
+/*****************************************************************************/
+/* osl_createSocketSet */
+/*****************************************************************************/
+oslSocketSet SAL_CALL osl_createSocketSet()
+{
+ TSocketSetImpl* pSet;
+
+ pSet= (TSocketSetImpl*)malloc(sizeof(TSocketSetImpl));
+
+ OSL_ASSERT(pSet);
+
+ if(pSet)
+ {
+ pSet->m_MaxHandle= 0;
+ FD_ZERO(&pSet->m_Set);
+ }
+
+ return (oslSocketSet)pSet;
+}
+
+/*****************************************************************************/
+/* osl_destroySocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_destroySocketSet(oslSocketSet Set)
+{
+ if(Set)
+ free(Set);
+}
+
+/*****************************************************************************/
+/* osl_clearSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_clearSocketSet(oslSocketSet Set)
+{
+ TSocketSetImpl* pSet;
+ OSL_ASSERT(Set);
+ if ( Set == 0 )
+ {
+ return;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+ pSet->m_MaxHandle= 0;
+
+ FD_ZERO(&pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_addToSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_addToSocketSet(oslSocketSet Set, oslSocket pSocket)
+{
+ TSocketSetImpl* pSet;
+
+ OSL_ASSERT(Set);
+ OSL_ASSERT(pSocket);
+
+ if ( Set == 0 || pSocket == 0)
+ {
+ return;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+
+ /* correct max handle */
+ if(pSocket->m_Socket > pSet->m_MaxHandle)
+ pSet->m_MaxHandle= pSocket->m_Socket;
+ FD_SET(pSocket->m_Socket, &pSet->m_Set);
+
+}
+
+/*****************************************************************************/
+/* osl_removeFromSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_removeFromSocketSet(oslSocketSet Set, oslSocket pSocket)
+{
+ TSocketSetImpl* pSet;
+
+ OSL_ASSERT(Set);
+ OSL_ASSERT(pSocket);
+
+ if ( Set == 0 || pSocket == 0)
+ {
+ return;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+
+ /* correct max handle */
+ if(pSocket->m_Socket == pSet->m_MaxHandle)
+ {
+ /* not optimal, since the next used descriptor might be */
+ /* much smaller than m_Socket-1, but it will do */
+ pSet->m_MaxHandle--;
+ if(pSet->m_MaxHandle < 0)
+ {
+ pSet->m_MaxHandle= 0; /* avoid underflow */
+ }
+ }
+
+ FD_CLR(pSocket->m_Socket, &pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_isInSocketSet */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isInSocketSet(oslSocketSet Set, oslSocket pSocket)
+{
+ TSocketSetImpl* pSet;
+
+ OSL_ASSERT(Set);
+ OSL_ASSERT(pSocket);
+ if ( Set == 0 || pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+
+ return (FD_ISSET(pSocket->m_Socket, &pSet->m_Set) != 0);
+}
+
+/*****************************************************************************/
+/* osl_demultiplexSocketEvents */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_demultiplexSocketEvents(oslSocketSet IncomingSet,
+ oslSocketSet OutgoingSet,
+ oslSocketSet OutOfBandSet,
+ const TimeValue* pTimeout)
+{
+ int MaxHandle= 0;
+ struct timeval tv;
+ TSocketSetImpl* pInSet;
+ TSocketSetImpl* pOutSet;
+ TSocketSetImpl* pOOBSet;
+
+ if (pTimeout)
+ {
+ /* non-blocking call */
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ /* map opaque data to impl-types */
+ pInSet= (TSocketSetImpl*)IncomingSet;
+ pOutSet= (TSocketSetImpl*)OutgoingSet;
+ pOOBSet= (TSocketSetImpl*)OutOfBandSet;
+
+ /* get max handle from all sets */
+ if (pInSet)
+ MaxHandle= pInSet->m_MaxHandle;
+
+ if (pOutSet && (pOutSet->m_MaxHandle > MaxHandle))
+ MaxHandle= pOutSet->m_MaxHandle;
+
+ if (pOOBSet && (pOOBSet->m_MaxHandle > MaxHandle))
+ MaxHandle= pOOBSet->m_MaxHandle;
+
+ return select(MaxHandle+1,
+ pInSet ? PTR_FD_SET(pInSet->m_Set) : 0,
+ pOutSet ? PTR_FD_SET(pOutSet->m_Set) : 0,
+ pOOBSet ? PTR_FD_SET(pOOBSet->m_Set) : 0,
+ pTimeout ? &tv : 0);
+}
+
diff --git a/sal/osl/os2/sockimpl.h b/sal/osl/os2/sockimpl.h
new file mode 100644
index 000000000000..38fc26bf0d22
--- /dev/null
+++ b/sal/osl/os2/sockimpl.h
@@ -0,0 +1,80 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_SOCKETIMPL_H_
+#define _OSL_SOCKETIMPL_H_
+
+#include <osl/pipe.h>
+#include <osl/socket.h>
+#include <osl/interlck.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* (*oslCloseCallback) (void*);
+
+struct oslSocketImpl {
+ int m_Socket;
+ int m_nLastError;
+ oslCloseCallback m_CloseCallback;
+ void* m_CallbackArg;
+ oslInterlockedCount m_nRefCount;
+#if defined(LINUX)
+ sal_Bool m_bIsAccepting;
+ sal_Bool m_bIsInShutdown;
+#endif
+};
+
+struct oslSocketAddrImpl
+{
+ sal_Int32 m_nRefCount;
+ struct sockaddr m_sockaddr;
+};
+
+/*
+struct oslPipeImpl {
+ int m_Socket;
+ sal_Char m_Name[PATH_MAX + 1];
+ oslInterlockedCount m_nRefCount;
+ sal_Bool m_bClosed;
+#if defined(LINUX)
+ sal_Bool m_bIsAccepting;
+ sal_Bool m_bIsInShutdown;
+#endif
+};
+*/
+
+oslSocket __osl_createSocketImpl(int Socket);
+void __osl_destroySocketImpl(oslSocket pImpl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sal/osl/os2/system.h b/sal/osl/os2/system.h
new file mode 100644
index 000000000000..ac7e410c5a34
--- /dev/null
+++ b/sal/osl/os2/system.h
@@ -0,0 +1,514 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __OSL_SYSTEM_H__
+#define __OSL_SYSTEM_H__
+
+#define PTHREAD_NONE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <signal.h>
+#include <utime.h>
+
+#include <pwd.h>
+
+#include <netdb.h>
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <sys/types.h>
+
+/* OS/2 API header */
+#define INCL_WINPROGRAMLIST
+#define INCL_WINSHELLDATA
+#define INCL_BASE
+#define INCL_DOSSIGNALS
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSMODULEMGR
+#define INCL_DOSERRORS
+#define INCL_DOSSESMGR
+#define INCL_DOSPROCESS
+#define INCL_DOSNMPIPES
+#define INCL_DOSMISC
+#include <os2.h>
+
+typedef ULONG HANDLE;
+#define _MAX_ENV 2048
+#define _MAX_CMD 2048
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int debug_printf(const char *f, ...);
+
+/* Make sockets of type AF_UNIX use underlying FS rights */
+#ifdef SOLARIS
+# define _XOPEN_SOURCE 500
+# include <sys/socket.h>
+# undef _XOPEN_SOURCE
+#else
+# include <sys/socket.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define max(a, b) ((a) < (b) ? (b) : (a))
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#ifndef abs
+#define abs(x) ((x) >= 0 ? (x) : -(x))
+#endif
+
+#ifdef SYSV
+# include <sys/utsname.h>
+#endif
+
+#ifdef LINUX
+# ifndef __USE_GNU
+# define __USE_GNU
+# endif
+
+#if GLIBC >= 2
+# include <shadow.h>
+# if ! (defined(SPARC) || defined(X86_64))
+# include <asm/sigcontext.h>
+# endif
+# include <pthread.h>
+# include <sys/file.h>
+# include <sys/ioctl.h>
+# include <sys/uio.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <dlfcn.h>
+# include <endian.h>
+# include <sys/time.h>
+# include <semaphore.h>
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif __BYTE_ORDER == __BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif __BYTE_ORDER == __PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# define PTR_SIZE_T(s) ((size_t *)&(s))
+# define IORESOURCE_TRANSFER_BSD
+# define IOCHANNEL_TRANSFER_BSD_RENO
+# define pthread_testcancel()
+# define NO_PTHREAD_PRIORITY
+# define PTHREAD_SIGACTION pthread_sigaction
+#else
+# include <shadow.h>
+# include <asm/sigcontext.h>
+# include <pthread.h>
+# include <sys/file.h>
+# include <sys/ioctl.h>
+# include <linux/net.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <linux/elfcore.h>
+# include <dlfcn.h>
+# include <endian.h>
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif __BYTE_ORDER == __BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif __BYTE_ORDER == __PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# define IORESOURCE_TRANSFER_BSD
+# define IOCHANNEL_TRANSFER_BSD_RENO
+# define pthread_testcancel()
+# define NO_PTHREAD_RTL
+# define NO_PTHREAD_PRIORITY
+# define PTHREAD_SIGACTION pthread_sigaction
+#endif
+#endif
+
+#ifdef NETBSD
+# define ETIME ETIMEDOUT
+# define _POSIX_THREAD_SYSCALL_SOFT 1
+# include <pthread.h>
+# include <netdb.h>
+# include <sys/sem.h>
+# include <sys/exec.h>
+# include <sys/filio.h>
+# include <sys/ioctl.h>
+# include <sys/time.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <dlfcn.h>
+# include <machine/endian.h>
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define _LITTLE_ENDIAN_OO
+# elif BYTE_ORDER == BIG_ENDIAN
+# define _BIG_ENDIAN_OO
+# elif BYTE_ORDER == PDP_ENDIAN
+# define _PDP_ENDIAN_OO
+# endif
+# define PTR_SIZE_T(s) ((size_t *)&(s))
+# define IORESOURCE_TRANSFER_BSD
+# define IOCHANNEL_TRANSFER_BSD_RENO
+# define pthread_testcancel()
+# define NO_PTHREAD_PRIORITY
+# define NO_PTHREAD_SEMAPHORES
+# define NO_PTHREAD_RTL
+# define PTHREAD_SIGACTION pthread_sigaction
+#endif
+
+#ifdef FREEBSD
+# define ETIME ETIMEDOUT
+# include <pthread.h>
+# include <sys/sem.h>
+# include <semaphore.h>
+# include <dlfcn.h>
+# include <sys/filio.h>
+# include <sys/ioctl.h>
+# include <sys/param.h>
+# include <sys/time.h>
+# include <sys/uio.h>
+# include <sys/exec.h>
+# include <vm/vm.h>
+# include <vm/vm_param.h>
+# include <vm/pmap.h>
+# include <vm/swap_pager.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# define IORESOURCE_TRANSFER_BSD
+# include <machine/endian.h>
+#if __FreeBSD_version < 500000
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif BYTE_ORDER == BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif BYTE_ORDER == PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+#endif
+# define NO_PTHREAD_RTL
+#endif
+
+#ifdef SCO
+# define AF_IPX -1
+# include <strings.h>
+# include <pthread.h>
+# include <shadow.h>
+# include <netdb.h>
+# include <sys/un.h>
+# include <sys/netinet/tcp.h>
+# include <sys/types.h>
+# include <sys/byteorder.h>
+# include <dlfcn.h>
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif BYTE_ORDER == BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif BYTE_ORDER == PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# define sched_yield() pthread_yield()
+# define pthread_testcancel()
+# define NO_PTHREAD_RTL
+# define NO_PTHREAD_PRIORITY
+extern int pthread_cancel(pthread_t);
+extern unsigned int nanosleep(unsigned int);
+# define SLEEP_TIMESPEC(timespec) (timespec .tv_sec > 0) ? sleep(timespec .tv_sec), nanosleep(timespec .tv_nsec) : nanosleep(timespec .tv_nsec)
+# define PATH_MAX _POSIX_PATH_MAX
+# define S_ISSOCK S_ISFIFO
+# define PTHREAD_SIGACTION pthread_sigaction
+# define STAT_PARENT stat
+#endif
+
+#ifdef AIX
+# define AF_IPX -1
+# include <strings.h>
+# include <pthread.h>
+# include <sys/time.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <sys/machine.h>
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif BYTE_ORDER == BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif BYTE_ORDER == PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# define sched_yield() pthread_yield()
+# define SLEEP_TIMESPEC(timespec) nsleep(&timespec, 0)
+# define LIBPATH "LIBPATH"
+# define PTR_SIZE_T(s) ((size_t *)&(s))
+# define NO_PTHREAD_SEMAPHORES
+# define NO_DL_FUNCTIONS
+#endif
+
+#ifdef HPUX
+# define AF_IPX -1
+# undef howmany
+# undef MAXINT
+# include <pthread.h>
+# include <sys/un.h>
+# include <sys/sched.h>
+# include <sys/xti.h>
+# include <sys/pstat.h>
+# include <shadow.h>
+# include <crypt.h>
+# include <machine/param.h>
+# define LIBPATH "SHLIB_PATH"
+# define PTR_SIZE_T(s) ((int *)&(s))
+# define PTR_FD_SET(s) ((int *)&(s))
+# define PTHREAD_VALUE(t) ((t).field2)
+# define PTHREAD_NONE_INIT { 0, -1 }
+# define PTHREAD_ATTR_DEFAULT pthread_attr_default
+# define PTHREAD_MUTEXATTR_DEFAULT pthread_mutexattr_default
+# define PTHREAD_CONDATTR_DEFAULT pthread_condattr_default
+# define pthread_detach(t) pthread_detach(&(t))
+# define NO_PTHREAD_PRIORITY
+# define NO_PTHREAD_SEMAPHORES
+# define NO_DL_FUNCTIONS
+# undef sigaction
+# define PTHREAD_SIGACTION cma_sigaction
+#endif
+
+#ifdef SOLARIS
+# include <shadow.h>
+# include <sys/procfs.h>
+# include <sys/un.h>
+# include <stropts.h>
+# include <pthread.h>
+# include <semaphore.h>
+# include <netinet/tcp.h>
+# include <sys/filio.h>
+# include <dlfcn.h>
+# include <sys/isa_defs.h>
+# define IORESOURCE_TRANSFER_SYSV
+# define IOCHANNEL_TRANSFER_BSD
+# define LIBPATH "LD_LIBRARY_PATH"
+# define PTR_SIZE_T(s) ((int *)&(s))
+#endif
+
+#ifdef MACOSX
+# define ETIME ETIMEDOUT
+# include <pthread.h>
+# include <sys/file.h>
+# include <sys/ioctl.h>
+# include <sys/uio.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <machine/endian.h>
+# include <sys/time.h>
+# include <sys/semaphore.h>
+/* fixme are premac and postmac still needed here? */
+# include <premac.h>
+# include <mach-o/dyld.h>
+# include <postmac.h>
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif BYTE_ORDER == BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif BYTE_ORDER == PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# define IOCHANNEL_TRANSFER_BSD_RENO
+# define NO_PTHREAD_RTL
+/* for NSGetArgc/Argv/Environ */
+# include <crt_externs.h>
+char *macxp_tempnam( const char *tmpdir, const char *prefix );
+#endif
+
+#ifdef OS2
+# include <netinet/tcp.h>
+#endif
+
+#if !defined(_WIN32) && !defined(_WIN16) && !defined(OS2) && \
+ !defined(LINUX) && !defined(NETBSD) && !defined(FREEBSD) && !defined(SCO) && \
+ !defined(AIX) && !defined(HPUX) && \
+ !defined(SOLARIS) && !defined(MAC) && \
+ !defined(MACOSX)
+# error "Target plattform not specified !"
+#endif
+
+#if defined(NETBSD)
+#if defined _LITTLE_ENDIAN_OO
+# define _OSL_BIGENDIAN
+#elif defined _BIG_ENDIAN_OO
+# define _OSL_LITENDIAN
+#else
+# error undetermined endianess
+#endif
+#else
+#if defined _LITTLE_ENDIAN
+# define _OSL_BIGENDIAN
+#elif defined _BIG_ENDIAN
+# define _OSL_LITENDIAN
+#else
+# error undetermined endianess
+#endif
+#endif
+
+#ifndef PTR_SIZE_T
+# define PTR_SIZE_T(s) (&(s))
+#endif
+
+#ifndef PTR_FD_SET
+# define PTR_FD_SET(s) (&(s))
+#endif
+
+#ifndef NORMALIZE_TIMESPEC
+# define NORMALIZE_TIMESPEC(timespec) \
+ timespec . tv_sec += timespec . tv_nsec / 1000000000; \
+ timespec . tv_nsec %= 1000000000;
+#endif
+
+#ifndef SET_TIMESPEC
+# define SET_TIMESPEC(timespec, sec, nsec) \
+ timespec . tv_sec = (sec); \
+ timespec . tv_nsec = (nsec); \
+ NORMALIZE_TIMESPEC(timespec);
+#endif
+
+#ifndef SLEEP_TIMESPEC
+# define SLEEP_TIMESPEC(timespec) nanosleep(&timespec, 0)
+#endif
+
+#ifndef INIT_GROUPS
+# define INIT_GROUPS(name, gid) ((setgid((gid)) == 0) && (initgroups((name), (gid)) == 0))
+#endif
+
+#ifndef PTHREAD_VALUE
+# define PTHREAD_VALUE(t) (t)
+#endif
+#ifndef PTHREAD_NONE
+extern pthread_t _pthread_none_;
+# define PTHREAD_NONE _pthread_none_
+# ifndef PTHREAD_NONE_INIT
+# define PTHREAD_NONE_INIT ((pthread_t)-1)
+# endif
+#endif
+
+#ifndef PTHREAD_ATTR_DEFAULT
+# define PTHREAD_ATTR_DEFAULT NULL
+#endif
+#ifndef PTHREAD_MUTEXATTR_DEFAULT
+# define PTHREAD_MUTEXATTR_DEFAULT NULL
+#endif
+#ifndef PTHREAD_CONDATTR_DEFAULT
+# define PTHREAD_CONDATTR_DEFAULT NULL
+#endif
+
+#ifndef PTHREAD_SIGACTION
+# define PTHREAD_SIGACTION sigaction
+#endif
+
+#ifndef STAT_PARENT
+# define STAT_PARENT lstat
+#endif
+
+/* socket options which might not be defined on all unx flavors */
+#ifndef SO_ACCEPTCONN
+# define SO_ACCEPTCONN 0
+#endif
+#ifndef SO_SNDLOWAT
+# define SO_SNDLOWAT 0
+#endif
+#ifndef SO_RCVLOWAT
+# define SO_RCVLOWAT 0
+#endif
+#ifndef SO_SNDTIMEO
+# define SO_SNDTIMEO 0
+#endif
+#ifndef SO_RCVTIMEO
+# define SO_RCVTIMEO 0
+#endif
+#ifndef SO_USELOOPBACK
+# define SO_USELOOPBACK 0
+#endif
+#ifndef MSG_MAXIOVLEN
+# define MSG_MAXIOVLEN 0
+#endif
+
+/* BEGIN HACK */
+/* dummy define and declarations for IPX should be replaced by */
+/* original ipx headers when these are available for this platform */
+
+#ifndef SA_FAMILY_DECL
+# define SA_FAMILY_DECL short sa_family
+#endif
+
+typedef struct sockaddr_ipx {
+ SA_FAMILY_DECL;
+ char sa_netnum[4];
+ char sa_nodenum[6];
+ unsigned short sa_socket;
+} SOCKADDR_IPX;
+
+#define NSPROTO_IPX 1000
+#define NSPROTO_SPX 1256
+#define NSPROTO_SPXII 1257
+
+/* END HACK */
+
+#ifdef NO_PTHREAD_SEMAPHORES
+
+typedef struct
+{
+ pthread_mutex_t mutex;
+ pthread_cond_t increased;
+ int value;
+} sem_t;
+extern int sem_init(sem_t* sem, int pshared, unsigned int value);
+extern int sem_destroy(sem_t* sem);
+extern int sem_wait(sem_t* sem);
+extern int sem_trywait(sem_t* sem);
+extern int sem_post(sem_t* sem);
+
+#endif
+
+#ifdef NO_PTHREAD_RTL
+#if !defined FREEBSD || (__FreeBSD_version < 500112)
+struct passwd *getpwent_r(struct passwd *pwd, char *buffer, int buflen);
+extern struct spwd *getspnam_r(const char *name, struct spwd *result,
+ char *buffer, int buflen);
+
+struct tm *localtime_r(const time_t *timep, struct tm *buffer);
+struct tm *gmtime_r(const time_t *timep, struct tm *buffer);
+#endif /* !defined FREEBSD || (__FreeBSD_version < 500112) */
+struct hostent *gethostbyname_r(const char *name, struct hostent *result,
+ char *buffer, int buflen, int *h_errnop);
+#endif
+
+#endif /* __OSL_SYSTEM_H__ */
+
diff --git a/sal/osl/os2/tempfile.c b/sal/osl/os2/tempfile.c
new file mode 100644
index 000000000000..672995563c88
--- /dev/null
+++ b/sal/osl/os2/tempfile.c
@@ -0,0 +1,359 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*****************************************************************/
+/* Includes */
+/*****************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "system.h"
+#include <osl/file.h>
+#include <osl/thread.h>
+#include <rtl/ustrbuf.h>
+#include <osl/diagnose.h>
+
+#ifndef _FILE_URL_H_
+#include "file_url.h"
+#endif
+
+/*****************************************************************/
+/* osl_getTempFirURL */
+/*****************************************************************/
+
+oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir )
+{
+ const char *pValue = getenv( "TEMP" );
+
+ if ( !pValue )
+ {
+ pValue = getenv( "TMP" );
+#if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD) || defined (MACOSX)
+ if ( !pValue )
+ pValue = P_tmpdir;
+#endif
+ }
+
+ if ( pValue )
+ {
+ oslFileError error;
+ rtl_uString *ustrTempPath = NULL;
+
+ rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(ustrTempPath != NULL);
+ error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
+ rtl_uString_release( ustrTempPath );
+
+ return error;
+ }
+ else
+ return osl_File_E_NOENT;
+}
+
+/******************************************************************
+ * Generates a random unique file name. We're using the scheme
+ * from the standard c-lib function mkstemp to generate a more
+ * or less random unique file name
+ *
+ * @param rand_name
+ * receives the random name
+ ******************************************************************/
+
+static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+static const int COUNT_OF_LETTERS = sizeof(LETTERS)/sizeof(LETTERS[0]) - 1;
+
+#define RAND_NAME_LENGTH 6
+
+static void osl_gen_random_name_impl_(rtl_uString** rand_name)
+{
+ static uint64_t value;
+
+ char buffer[RAND_NAME_LENGTH];
+ struct timeval tv;
+ uint64_t v;
+ int i;
+
+ gettimeofday(&tv, NULL);
+
+ value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
+
+ v = value;
+
+ for (i = 0; i < RAND_NAME_LENGTH; i++)
+ {
+ buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
+ v /= COUNT_OF_LETTERS;
+ }
+
+ rtl_string2UString(
+ rand_name,
+ buffer,
+ RAND_NAME_LENGTH,
+ RTL_TEXTENCODING_ASCII_US,
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(*rand_name != NULL);
+}
+
+/*****************************************************************
+ * Helper function
+ * Either use the directory provided or the result of
+ * osl_getTempDirUrl and return it as system path and file url
+ ****************************************************************/
+
+static oslFileError osl_setup_base_directory_impl_(
+ rtl_uString* pustrDirectoryURL,
+ rtl_uString** ppustr_base_dir)
+{
+ rtl_uString* dir_url = 0;
+ rtl_uString* dir = 0;
+ oslFileError error = osl_File_E_None;
+
+ if (pustrDirectoryURL)
+ rtl_uString_assign(&dir_url, pustrDirectoryURL);
+ else
+ error = osl_getTempDirURL(&dir_url);
+
+ if (osl_File_E_None == error)
+ {
+ error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE);
+ rtl_uString_release(dir_url);
+ }
+
+ if (osl_File_E_None == error)
+ {
+ rtl_uString_assign(ppustr_base_dir, dir);
+ rtl_uString_release(dir);
+ }
+
+ return error;
+}
+
+/*****************************************************************
+ * osl_setup_createTempFile_impl
+ * validate input parameter, setup variables
+ ****************************************************************/
+
+ static oslFileError osl_setup_createTempFile_impl_(
+ rtl_uString* pustrDirectoryURL,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL,
+ rtl_uString** ppustr_base_dir,
+ sal_Bool* b_delete_on_close)
+ {
+ oslFileError osl_error;
+
+ OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
+
+ if ((0 == pHandle) && (0 == ppustrTempFileURL))
+ {
+ osl_error = osl_File_E_INVAL;
+ }
+ else
+ {
+ osl_error = osl_setup_base_directory_impl_(
+ pustrDirectoryURL, ppustr_base_dir);
+
+ *b_delete_on_close = (0 == ppustrTempFileURL);
+ }
+
+ return osl_error;
+ }
+
+/*****************************************************************
+ * Create a unique file in the specified directory and return
+ * it's name
+ ****************************************************************/
+
+static oslFileError osl_create_temp_file_impl_(
+ const rtl_uString* pustr_base_directory,
+ oslFileHandle* file_handle,
+ rtl_uString** ppustr_temp_file_name)
+{
+ rtl_uString* rand_name = 0;
+ sal_uInt32 len_base_dir = 0;
+ rtl_uString* tmp_file_path = 0;
+ rtl_uString* tmp_file_url = 0;
+ sal_Int32 capacity = 0;
+ oslFileError osl_error = osl_File_E_None;
+ sal_Int32 offset_file_name;
+ const sal_Unicode* puchr;
+
+ OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
+ OSL_PRECOND(file_handle, "Invalid Parameter");
+ OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
+
+ len_base_dir = rtl_uString_getLength(pustr_base_directory);
+
+ rtl_uStringbuffer_newFromStr_WithLength(
+ &tmp_file_path,
+ rtl_uString_getStr((rtl_uString*)pustr_base_directory),
+ len_base_dir);
+
+ rtl_uStringbuffer_ensureCapacity(
+ &tmp_file_path,
+ &capacity,
+ (len_base_dir + 1 + RAND_NAME_LENGTH));
+
+ offset_file_name = len_base_dir;
+
+ puchr = rtl_uString_getStr(tmp_file_path);
+
+ /* ensure that the last character is a '\' */
+
+ if ((sal_Unicode)'\\' != puchr[len_base_dir - 1])
+ {
+ rtl_uStringbuffer_insert_ascii(
+ &tmp_file_path,
+ &capacity,
+ len_base_dir,
+ "\\",
+ 1);
+
+ offset_file_name++;
+ }
+
+ while(1) /* try until success */
+ {
+ osl_gen_random_name_impl_(&rand_name);
+
+ rtl_uStringbuffer_insert(
+ &tmp_file_path,
+ &capacity,
+ offset_file_name,
+ rtl_uString_getStr(rand_name),
+ rtl_uString_getLength(rand_name));
+
+ osl_error = osl_getFileURLFromSystemPath(
+ tmp_file_path, &tmp_file_url);
+
+ if (osl_File_E_None == osl_error)
+ {
+ /* RW permission for the user only! */
+ mode_t old_mode = umask(077);
+
+ osl_error = osl_openFile(
+ tmp_file_url,
+ file_handle,
+ osl_File_OpenFlag_Read |
+ osl_File_OpenFlag_Write |
+ osl_File_OpenFlag_Create);
+
+ umask(old_mode);
+ }
+
+ /* in case of error osl_File_E_EXIST we simply try again else we give up */
+
+ if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST))
+ {
+ if (rand_name)
+ rtl_uString_release(rand_name);
+
+ if (tmp_file_url)
+ rtl_uString_release(tmp_file_url);
+
+ break;
+ }
+ } /* while(1) */
+
+ if (osl_File_E_None == osl_error)
+ rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
+
+ if (tmp_file_path)
+ rtl_uString_release(tmp_file_path);
+
+ return osl_error;
+}
+
+/*****************************************************************
+ * osl_createTempFile
+ *****************************************************************/
+
+oslFileError SAL_CALL osl_createTempFile(
+ rtl_uString* pustrDirectoryURL,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL)
+{
+ rtl_uString* base_directory = 0;
+ rtl_uString* temp_file_name = 0;
+ oslFileHandle temp_file_handle;
+ sal_Bool b_delete_on_close;
+ oslFileError osl_error;
+
+ osl_error = osl_setup_createTempFile_impl_(
+ pustrDirectoryURL,
+ pHandle,
+ ppustrTempFileURL,
+ &base_directory,
+ &b_delete_on_close);
+
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+
+ osl_error = osl_create_temp_file_impl_(
+ base_directory, &temp_file_handle, &temp_file_name);
+
+ if (osl_File_E_None == osl_error)
+ {
+ rtl_uString* temp_file_url = 0;
+
+ /* assuming this works */
+ osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
+
+ if (b_delete_on_close)
+ {
+ osl_error = osl_removeFile(temp_file_url);
+
+ if (osl_File_E_None == osl_error)
+ *pHandle = temp_file_handle;
+ else
+ osl_closeFile(temp_file_handle);
+ }
+ else
+ {
+ if (pHandle)
+ *pHandle = temp_file_handle;
+ else
+ osl_closeFile(temp_file_handle);
+
+ rtl_uString_assign(ppustrTempFileURL, temp_file_url);
+ }
+
+ if (temp_file_url)
+ rtl_uString_release(temp_file_url);
+
+ if (temp_file_name)
+ rtl_uString_release(temp_file_name);
+ }
+
+ if (base_directory)
+ rtl_uString_release(base_directory);
+
+ return osl_error;
+}
diff --git a/sal/osl/os2/thread.c b/sal/osl/os2/thread.c
new file mode 100644
index 000000000000..313e67c0f925
--- /dev/null
+++ b/sal/osl/os2/thread.c
@@ -0,0 +1,772 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/time.h>
+#include <rtl/alloc.h>
+#include <rtl/tencinfo.h>
+
+/*
+ Thread-data structure hidden behind oslThread:
+*/
+typedef struct _osl_TThreadImpl
+{
+
+ TID m_ThreadId; /* identifier for this thread */
+ sal_Int32 m_Flags;
+ HEV m_hEvent;
+ sal_uInt32 m_Timeout;
+ oslWorkerFunction m_WorkerFunction;
+ void* m_pData;
+ sal_Bool m_StartSuspended;
+ HAB m_hab;
+ HMQ m_hmq;
+
+} osl_TThreadImpl;
+
+#define THREADIMPL_FLAGS_TERMINATE 0x0001
+#define THREADIMPL_FLAGS_SLEEP 0x0002
+
+
+// static mutex to control access to private members of oslMutexImpl
+static HMTX MutexLock = NULL;
+
+/*****************************************************************************/
+
+HAB osl_getPMinternal_HAB(oslThread hThread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)hThread;
+
+ if(pThreadImpl == NULL) /* valid ptr? */
+ {
+ return NULL;
+ }
+ else
+ {
+ return pThreadImpl->m_hab;
+ }
+}
+
+HMQ osl_getPMinternal_HMQ(oslThread hThread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)hThread;
+
+ if(pThreadImpl == NULL) /* valid ptr? */
+ {
+ return NULL;
+ }
+ else
+ {
+ return pThreadImpl->m_hmq;
+ }
+}
+
+
+/*****************************************************************************/
+/* oslWorkerWrapperFunction */
+/*****************************************************************************/
+static void oslWorkerWrapperFunction(void* pData)
+{
+ BOOL rc;
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)pData;
+
+#if OSL_DEBUG_LEVEL>0
+printf("oslWorkerWrapperFunction pThreadImpl %x, pThreadImpl->m_ThreadId %d\n", pThreadImpl, pThreadImpl->m_ThreadId);
+#endif
+ /* Inizialize PM for this thread */
+ pThreadImpl->m_hab = WinInitialize( 0 );
+#if OSL_DEBUG_LEVEL>0
+printf("pThreadImpl->m_ThreadId %d, pThreadImpl->m_hab %x\n", pThreadImpl->m_ThreadId,pThreadImpl->m_hab);
+#endif
+ pThreadImpl->m_hmq = WinCreateMsgQueue( pThreadImpl->m_hab, 0 );
+#if OSL_DEBUG_LEVEL>0
+printf("pThreadImpl->m_ThreadId %d, pThreadImpl->m_hmq %x\n", pThreadImpl->m_ThreadId,pThreadImpl->m_hmq);
+#endif
+
+ /* call worker-function with data */
+ pThreadImpl->m_WorkerFunction( pThreadImpl->m_pData );
+
+ /* Free all PM-resources for this thread */
+#if OSL_DEBUG_LEVEL>0
+printf("pThreadImpl->m_ThreadId %d, about to destroy queue\n", pThreadImpl->m_ThreadId);
+#endif
+ rc = WinDestroyMsgQueue( pThreadImpl->m_hmq );
+#if OSL_DEBUG_LEVEL>0
+printf("pThreadImpl->m_ThreadId %d, WinDestroyMsgQueue rc=%d (should be 1)\n", pThreadImpl->m_ThreadId, rc);
+printf("pThreadImpl->m_ThreadId %d, about to terminate hab\n", pThreadImpl->m_ThreadId);
+#endif
+ rc = WinTerminate( pThreadImpl->m_hab );
+#if OSL_DEBUG_LEVEL>0
+printf("pThreadImpl->m_ThreadId %d, WinTerminate rc=%d (should be 1)\n", pThreadImpl->m_ThreadId, rc);
+#endif
+}
+
+
+/*****************************************************************************/
+/* oslCreateThread */
+/*****************************************************************************/
+static oslThread oslCreateThread(oslWorkerFunction pWorker,
+ void* pThreadData,
+ sal_Bool nFlags)
+{
+ osl_TThreadImpl* pThreadImpl;
+
+ /* alloc mem. for our internal data structure */
+ pThreadImpl = (osl_TThreadImpl*)malloc(sizeof(osl_TThreadImpl));
+
+ OSL_ASSERT(pThreadImpl);
+
+ pThreadImpl->m_WorkerFunction= pWorker;
+ pThreadImpl->m_pData= pThreadData;
+
+ pThreadImpl->m_Flags = 0;
+ pThreadImpl->m_hEvent = 0;
+ pThreadImpl->m_Timeout = 0;
+ pThreadImpl->m_StartSuspended = nFlags;
+ pThreadImpl->m_hab = 0;
+ pThreadImpl->m_hmq = 0;
+
+ if ( nFlags == sal_True )
+ {
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+ }
+
+ pThreadImpl->m_ThreadId = (TID) _beginthread( oslWorkerWrapperFunction, /* worker-function */
+ NULL, /* unused parameter */
+ 1024*1024, /* max. Stacksize */
+ pThreadImpl );
+ if ( nFlags == sal_True )
+ {
+ if( pThreadImpl->m_ThreadId != -1 )
+ DosSuspendThread( pThreadImpl->m_ThreadId );
+ DosReleaseMutexSem( MutexLock);
+ }
+#if OSL_DEBUG_LEVEL>0
+printf("oslCreateThread pThreadImpl %x, pThreadImpl->m_ThreadId %d\n", pThreadImpl, pThreadImpl->m_ThreadId);
+#endif
+ if(pThreadImpl->m_ThreadId == -1)
+ {
+ /* create failed */
+ if (pThreadImpl->m_hEvent != 0)
+ DosCloseEventSem(pThreadImpl->m_hEvent);
+
+ free(pThreadImpl);
+ return 0;
+ }
+
+ pThreadImpl->m_hEvent= 0;
+
+ return pThreadImpl;
+
+}
+
+/*****************************************************************************/
+/* osl_createThread */
+/*****************************************************************************/
+oslThread SAL_CALL osl_createThread(oslWorkerFunction pWorker,
+ void* pThreadData)
+{
+ return oslCreateThread(pWorker,pThreadData,sal_False);
+}
+
+/*****************************************************************************/
+/* osl_createSuspendedThread */
+/*****************************************************************************/
+oslThread SAL_CALL osl_createSuspendedThread(oslWorkerFunction pWorker,
+ void* pThreadData)
+{
+ return oslCreateThread(pWorker,pThreadData,sal_True);
+}
+
+/*****************************************************************************/
+/* osl_getThreadIdentifier */
+/*****************************************************************************/
+oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ if (pThreadImpl != NULL)
+ return ((oslThreadIdentifier)pThreadImpl->m_ThreadId);
+ else
+ {
+ PTIB pptib = NULL;
+ PPIB pppib = NULL;
+
+ DosGetInfoBlocks( &pptib, &pppib );
+ return ((oslThreadIdentifier) pptib->tib_ptib2->tib2_ultid );
+ }
+}
+
+/*****************************************************************************/
+/* osl_destroyThread */
+/*****************************************************************************/
+void SAL_CALL osl_destroyThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ if(Thread == 0) /* valid ptr? */
+ {
+ /* thread already destroyed or not created */
+ return;
+ }
+
+ if(pThreadImpl->m_ThreadId != -1) /* valid handle ? */
+ {
+ /* cancel thread */
+ DosKillThread( pThreadImpl->m_ThreadId );
+ }
+}
+
+/*****************************************************************************/
+/* osl_freeThreadHandle */
+/*****************************************************************************/
+void SAL_CALL osl_freeThreadHandle(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ if(Thread == 0) /* valid ptr? */
+ {
+ /* thread already destroyed or not created */
+ return;
+ }
+
+ if (pThreadImpl->m_hEvent != 0)
+ DosCloseEventSem(pThreadImpl->m_hEvent);
+
+ /* free memory */
+ free(Thread);
+}
+
+/*****************************************************************************/
+/* osl_resumeThread */
+/*****************************************************************************/
+void SAL_CALL osl_resumeThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ OSL_ASSERT(pThreadImpl); /* valid ptr? */
+
+ DosResumeThread( pThreadImpl->m_ThreadId );
+}
+
+/*****************************************************************************/
+/* osl_suspendThread */
+/*****************************************************************************/
+void SAL_CALL osl_suspendThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ OSL_ASSERT(pThreadImpl); /* valid ptr? */
+
+ DosSuspendThread( pThreadImpl->m_ThreadId );
+}
+
+/*****************************************************************************/
+/* osl_setThreadPriority */
+/*****************************************************************************/
+void SAL_CALL osl_setThreadPriority(oslThread Thread,
+ oslThreadPriority Priority)
+{
+ ULONG nOs2PriorityClass;
+ ULONG nOs2PriorityDelta;
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ OSL_ASSERT(pThreadImpl); /* valid ptr? */
+
+ switch(Priority) {
+
+ case osl_Thread_PriorityHighest:
+
+ nOs2PriorityClass = PRTYC_REGULAR;
+ nOs2PriorityDelta = PRTYD_MAXIMUM;
+ break;
+
+ case osl_Thread_PriorityAboveNormal:
+
+ nOs2PriorityClass = PRTYC_REGULAR;
+ nOs2PriorityDelta = 16;
+ break;
+
+ case osl_Thread_PriorityNormal:
+
+ nOs2PriorityClass = PRTYC_REGULAR;
+ nOs2PriorityDelta = 0;
+ break;
+
+ case osl_Thread_PriorityBelowNormal:
+
+ nOs2PriorityClass = PRTYC_REGULAR;
+ nOs2PriorityDelta = -16;
+ break;
+
+ case osl_Thread_PriorityLowest:
+
+ nOs2PriorityClass = PRTYC_REGULAR;
+ nOs2PriorityDelta = PRTYD_MINIMUM;
+ break;
+
+ case osl_Thread_PriorityUnknown:
+ OSL_ASSERT(FALSE); /* only fools try this...*/
+
+ /* let release-version behave friendly */
+ return;
+
+ default:
+ OSL_ASSERT(FALSE); /* enum expanded, but forgotten here...*/
+
+ /* let release-version behave friendly */
+ return;
+ }
+
+ DosSetPriority( PRTYS_THREAD,
+ nOs2PriorityClass, nOs2PriorityDelta,
+ pThreadImpl->m_ThreadId );
+
+}
+
+/*****************************************************************************/
+/* osl_getThreadPriority */
+/*****************************************************************************/
+
+#define BYTE1FROMULONG(ul) ((UCHAR) (ul))
+#define BYTE2FROMULONG(ul) ((UCHAR) ((ULONG) ul >> 8))
+
+oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread)
+{
+ ULONG nOs2PriorityClass;
+ ULONG nOs2PriorityDelta;
+
+ oslThreadPriority Priority;
+
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments ?*/
+ if(pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
+ {
+ return osl_Thread_PriorityUnknown;
+ }
+
+ /* get current priorities */
+ {
+ PTIB pptib = NULL;
+ PPIB pppib = NULL;
+
+ DosGetInfoBlocks( &pptib, &pppib );
+ nOs2PriorityClass = BYTE1FROMULONG( pptib->tib_ptib2->tib2_ulpri );
+ nOs2PriorityDelta = BYTE2FROMULONG( pptib->tib_ptib2->tib2_ulpri );
+ }
+
+ /* map OS2 priority to enum */
+ switch(nOs2PriorityClass)
+ {
+ case PRTYC_TIMECRITICAL:
+ Priority= osl_Thread_PriorityHighest;
+ break;
+
+ case PRTYC_REGULAR:
+
+ if( nOs2PriorityDelta == 0 )
+ {
+ Priority= osl_Thread_PriorityNormal;
+ break;
+ }
+
+ if( nOs2PriorityDelta < -16 )
+ {
+ Priority= osl_Thread_PriorityLowest;
+ break;
+ }
+
+ if( nOs2PriorityDelta < 0 )
+ {
+ Priority= osl_Thread_PriorityBelowNormal;
+ break;
+ }
+
+ if( nOs2PriorityDelta > 0 )
+ {
+ Priority= osl_Thread_PriorityAboveNormal;
+ break;
+ }
+
+ Priority= osl_Thread_PriorityHighest;
+ break;
+
+ case PRTYC_IDLETIME:
+ Priority= osl_Thread_PriorityLowest;
+ break;
+
+ default:
+ OSL_ASSERT(FALSE); /* OS/2 API changed, incorporate new prio-level! */
+
+ /* release-version behaves friendly */
+ Priority= osl_Thread_PriorityUnknown;
+ }
+
+ return Priority;
+}
+
+/*****************************************************************************/
+/* osl_isThreadRunning */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+ APIRET rc;
+
+ /* invalid arguments ?*/
+ if(pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
+ {
+ return sal_False;
+ }
+
+ if( osl_getThreadIdentifier( 0 ) == osl_getThreadIdentifier( Thread ) )
+ return sal_True;
+
+ rc = DosWaitThread( &pThreadImpl->m_ThreadId, DCWW_NOWAIT );
+
+ return( rc != ERROR_INVALID_THREADID );
+}
+
+/*****************************************************************************/
+/* osl_joinWithThread */
+/*****************************************************************************/
+void SAL_CALL osl_joinWithThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments?*/
+ if(pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
+ {
+ /* assume thread is not running */
+ return;
+ }
+
+ DosWaitThread( &pThreadImpl->m_ThreadId, DCWW_WAIT );
+}
+
+/*****************************************************************************/
+/* osl_waitThread */
+/*****************************************************************************/
+void SAL_CALL osl_waitThread(const TimeValue* pDelay)
+{
+ int millisecs;
+
+ OSL_ASSERT(pDelay);
+
+ millisecs = pDelay->Seconds * 1000 + pDelay->Nanosec / 1000000;
+
+ DosSleep(millisecs);
+}
+
+/*****************************************************************************/
+/* osl_terminateThread */
+/*****************************************************************************/
+void SAL_CALL osl_terminateThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments?*/
+ if (pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
+ {
+ /* assume thread is not running */
+ return;
+ }
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+ pThreadImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE;
+ DosReleaseMutexSem( MutexLock);
+}
+
+
+/*****************************************************************************/
+/* osl_scheduleThread */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ osl_yieldThread();
+
+ /* invalid arguments?*/
+ if (pThreadImpl==0 || pThreadImpl->m_ThreadId==-1)
+ {
+ /* assume thread is not running */
+ return sal_False;
+ }
+
+ if (pThreadImpl->m_Flags & THREADIMPL_FLAGS_SLEEP)
+ {
+ OSL_ASSERT (pThreadImpl->m_hEvent != 0);
+
+ DosWaitEventSem(pThreadImpl->m_hEvent, pThreadImpl->m_Timeout);
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+
+ pThreadImpl->m_Timeout = 0;
+
+ pThreadImpl->m_Flags &= ~THREADIMPL_FLAGS_SLEEP;
+
+ DosReleaseMutexSem( MutexLock);
+ }
+
+ return ((pThreadImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) == 0);
+}
+
+/*****************************************************************************/
+/* osl_yieldThread */
+/*****************************************************************************/
+void SAL_CALL osl_yieldThread()
+{
+ DosSleep(0);
+}
+
+typedef struct _TLS
+{
+ PULONG pulPtr;
+ oslThreadKeyCallbackFunction pfnCallback;
+ struct _TLS *pNext, *pPrev;
+} TLS, *PTLS;
+
+static PTLS g_pThreadKeyList = NULL;
+
+static void AddKeyToList( PTLS pTls )
+{
+ if ( pTls )
+ {
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+
+ pTls->pNext = g_pThreadKeyList;
+ pTls->pPrev = 0;
+
+ if ( g_pThreadKeyList )
+ g_pThreadKeyList->pPrev = pTls;
+
+ g_pThreadKeyList = pTls;
+
+ DosReleaseMutexSem( MutexLock);
+ }
+}
+
+static void RemoveKeyFromList( PTLS pTls )
+{
+ if ( pTls )
+ {
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+ if ( pTls->pPrev )
+ pTls->pPrev->pNext = pTls->pNext;
+ else
+ {
+ OSL_ASSERT( pTls == g_pThreadKeyList );
+ g_pThreadKeyList = pTls->pNext;
+ }
+
+ if ( pTls->pNext )
+ pTls->pNext->pPrev = pTls->pPrev;
+ DosReleaseMutexSem( MutexLock);
+ }
+}
+
+void SAL_CALL _osl_callThreadKeyCallbackOnThreadDetach(void)
+{
+ PTLS pTls;
+
+ DosRequestMutexSem( MutexLock, SEM_INDEFINITE_WAIT );
+ pTls = g_pThreadKeyList;
+ while ( pTls )
+ {
+ if ( pTls->pfnCallback )
+ {
+ void *pValue = (void*)*pTls->pulPtr;
+
+ if ( pValue )
+ pTls->pfnCallback( pValue );
+ }
+
+ pTls = pTls->pNext;
+ }
+ DosReleaseMutexSem( MutexLock);
+}
+
+/*****************************************************************************/
+/* osl_createThreadKey */
+/*****************************************************************************/
+oslThreadKey SAL_CALL osl_createThreadKey(oslThreadKeyCallbackFunction pCallback)
+{
+ PTLS pTls = (PTLS)rtl_allocateMemory( sizeof(TLS) );
+
+ if ( pTls )
+ {
+ pTls->pfnCallback = pCallback;
+ if (DosAllocThreadLocalMemory(1, &pTls->pulPtr) != NO_ERROR)
+ {
+ rtl_freeMemory( pTls );
+ pTls = 0;
+ }
+ else
+ {
+ *pTls->pulPtr = 0;
+ AddKeyToList( pTls );
+ }
+ }
+
+ return ((oslThreadKey)pTls);
+}
+
+/*****************************************************************************/
+/* osl_destroyThreadKey */
+/*****************************************************************************/
+void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
+{
+ if (Key != 0)
+ {
+ PTLS pTls = (PTLS)Key;
+
+ RemoveKeyFromList( pTls );
+ DosFreeThreadLocalMemory(pTls->pulPtr);
+ rtl_freeMemory( pTls );
+ }
+}
+
+/*****************************************************************************/
+/* osl_getThreadKeyData */
+/*****************************************************************************/
+void * SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
+{
+ if (Key != 0)
+ {
+ PTLS pTls = (PTLS)Key;
+
+ return ((void *) *pTls->pulPtr);
+ }
+
+ return (NULL);
+}
+
+/*****************************************************************************/
+/* osl_setThreadKeyData */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
+{
+ if (Key != 0)
+ {
+ PTLS pTls = (PTLS)Key;
+ void* pOldData = NULL;
+ BOOL fSuccess = TRUE; //YD cannot fail
+
+ if ( pTls->pfnCallback )
+ pOldData = (void*)*pTls->pulPtr;
+
+ *pTls->pulPtr = (ULONG)pData;
+
+ if ( fSuccess && pTls->pfnCallback && pOldData )
+ pTls->pfnCallback( pOldData );
+
+ return (sal_Bool)(fSuccess != FALSE);
+ }
+
+ return (sal_False);
+}
+
+
+
+/*****************************************************************************/
+/* osl_getThreadTextEncoding */
+/*****************************************************************************/
+
+ULONG g_dwTLSTextEncodingIndex = (ULONG)-1;
+
+sal_uInt32 SAL_CALL _GetACP( void)
+{
+ APIRET rc;
+ ULONG aulCpList[8] = {0};
+ ULONG ulListSize;
+
+ rc = DosQueryCp( sizeof( aulCpList), aulCpList, &ulListSize);
+ if (rc)
+ return 437; // in case of error, return codepage EN_US
+ // current codepage is first of list, others are the prepared codepages.
+ return aulCpList[0];
+}
+
+rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding(void)
+{
+ rtl_TextEncoding _encoding;
+
+ if ( (ULONG)-1 == g_dwTLSTextEncodingIndex ) {
+ rtl_TextEncoding defaultEncoding;
+ const char * pszEncoding;
+
+ /* create thread specific data key */
+ g_dwTLSTextEncodingIndex = osl_createThreadKey( NULL);
+
+ /* determine default text encoding */
+ pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING");
+ if (pszEncoding)
+ defaultEncoding = atoi(pszEncoding);
+ else
+ defaultEncoding = rtl_getTextEncodingFromWindowsCodePage( _GetACP());
+
+ //OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW);
+ //g_thread.m_textencoding.m_default = defaultEncoding;
+ osl_setThreadKeyData( g_dwTLSTextEncodingIndex, (void*)defaultEncoding);
+ }
+
+ _encoding = (rtl_TextEncoding)osl_getThreadKeyData( g_dwTLSTextEncodingIndex );
+ if (0 == _encoding) {
+ const char * pszEncoding;
+ /* determine default text encoding */
+ pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING");
+ if (pszEncoding)
+ _encoding = atoi(pszEncoding);
+ else
+ _encoding = rtl_getTextEncodingFromWindowsCodePage( _GetACP());
+ /* save for future reference */
+ osl_setThreadKeyData( g_dwTLSTextEncodingIndex, (void*)_encoding);
+ }
+
+ return _encoding;
+}
+
+/*****************************************************************************/
+/* osl_getThreadTextEncoding */
+/*****************************************************************************/
+rtl_TextEncoding SAL_CALL osl_setThreadTextEncoding( rtl_TextEncoding Encoding )
+{
+ rtl_TextEncoding oldEncoding = osl_getThreadTextEncoding();
+
+ osl_setThreadKeyData( g_dwTLSTextEncodingIndex, (void*)Encoding);
+
+ return oldEncoding;
+}
+
+
+
diff --git a/sal/osl/os2/time.c b/sal/osl/os2/time.c
new file mode 100644
index 000000000000..c1a98a6b87a9
--- /dev/null
+++ b/sal/osl/os2/time.c
@@ -0,0 +1,269 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/time.h>
+
+/* FIXME: detection should be done in configure script */
+#if defined(MACOSX) || defined(FREEBSD) || defined(NETBSD) || defined(LINUX)
+#define STRUCT_TM_HAS_GMTOFF 1
+
+#elif defined(SOLARIS)
+#define HAS_ALTZONE 1
+#endif
+
+/*--------------------------------------------------
+ * osl_getSystemTime
+ *-------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getSystemTime(TimeValue* TimeValue)
+{
+ struct timeval tp;
+
+ /* FIXME: use higher resolution */
+ gettimeofday(&tp, NULL);
+
+ TimeValue->Seconds = tp.tv_sec;
+ TimeValue->Nanosec = tp.tv_usec * 1000;
+
+ return (sal_True);
+}
+
+
+/*--------------------------------------------------
+ * osl_getDateTimeFromTimeValue
+ *-------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getDateTimeFromTimeValue( TimeValue* pTimeVal, oslDateTime* pDateTime )
+{
+ struct tm *pSystemTime;
+ struct tm tmBuf;
+ time_t atime;
+
+ atime = (time_t)pTimeVal->Seconds;
+
+ /* Convert time from type time_t to struct tm */
+ pSystemTime = gmtime_r( &atime, &tmBuf );
+
+
+ /* Convert struct tm to struct oslDateTime */
+ if ( pSystemTime != NULL )
+ {
+ pDateTime->NanoSeconds = pTimeVal->Nanosec;
+ pDateTime->Seconds = pSystemTime->tm_sec;
+ pDateTime->Minutes = pSystemTime->tm_min;
+ pDateTime->Hours = pSystemTime->tm_hour;
+ pDateTime->Day = pSystemTime->tm_mday;
+ pDateTime->DayOfWeek = pSystemTime->tm_wday;
+ pDateTime->Month = pSystemTime->tm_mon + 1;
+ pDateTime->Year = pSystemTime->tm_year + 1900;
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+/*--------------------------------------------------
+ * osl_getTimeValueFromDateTime
+ *--------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getTimeValueFromDateTime( oslDateTime* pDateTime, TimeValue* pTimeVal )
+{
+ struct tm aTime;
+ time_t nSeconds;
+
+ /* Convert struct oslDateTime to struct tm */
+ aTime.tm_sec = pDateTime->Seconds;
+ aTime.tm_min = pDateTime->Minutes;
+ aTime.tm_hour = pDateTime->Hours;
+ aTime.tm_mday = pDateTime->Day;
+ aTime.tm_wday = pDateTime->DayOfWeek;
+
+ if ( pDateTime->Month > 0 )
+ aTime.tm_mon = pDateTime->Month - 1;
+ else
+ return sal_False;
+
+ if ( pDateTime->Year >= 1900 )
+ aTime.tm_year = pDateTime->Year - 1900;
+ else
+ return sal_False;
+
+ aTime.tm_isdst = -1;
+ aTime.tm_wday = 0;
+ aTime.tm_yday = 0;
+
+ /* Convert time to calendar value */
+ nSeconds = mktime( &aTime );
+
+ /*
+ * mktime expects the struct tm to be in local timezone, so we have to adjust
+ * the returned value to be timezone neutral.
+ */
+
+ if ( nSeconds != (time_t) -1 )
+ {
+ time_t bias;
+
+ /* timezone corrections */
+ tzset();
+
+#if defined(STRUCT_TM_HAS_GMTOFF)
+ /* members of struct tm are corrected by mktime */
+ bias = 0 - aTime.tm_gmtoff;
+
+#elif defined(HAS_ALTZONE)
+ /* check if daylight saving time is in effect */
+ bias = aTime.tm_isdst > 0 ? altzone : timezone;
+#else
+ /* exspect daylight saving time to be one hour */
+ bias = aTime.tm_isdst > 0 ? timezone - 3600 : timezone;
+#endif
+
+ pTimeVal->Seconds = nSeconds;
+ pTimeVal->Nanosec = pDateTime->NanoSeconds;
+
+ if ( nSeconds > bias )
+ pTimeVal->Seconds -= bias;
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+
+/*--------------------------------------------------
+ * osl_getLocalTimeFromSystemTime
+ *--------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getLocalTimeFromSystemTime( TimeValue* pSystemTimeVal, TimeValue* pLocalTimeVal )
+{
+ struct tm *pLocalTime;
+ struct tm tmBuf;
+ time_t bias;
+ time_t atime;
+
+ atime = (time_t) pSystemTimeVal->Seconds;
+ pLocalTime = localtime_r( &atime, &tmBuf );
+
+#if defined(STRUCT_TM_HAS_GMTOFF)
+ /* members of struct tm are corrected by mktime */
+ bias = 0 - pLocalTime->tm_gmtoff;
+
+#elif defined(HAS_ALTZONE)
+ /* check if daylight saving time is in effect */
+ bias = pLocalTime->tm_isdst > 0 ? altzone : timezone;
+#else
+ /* exspect daylight saving time to be one hour */
+ bias = pLocalTime->tm_isdst > 0 ? timezone - 3600 : timezone;
+#endif
+
+ if ( (sal_Int64) pSystemTimeVal->Seconds > bias )
+ {
+ pLocalTimeVal->Seconds = pSystemTimeVal->Seconds - bias;
+ pLocalTimeVal->Nanosec = pSystemTimeVal->Nanosec;
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+/*--------------------------------------------------
+ * osl_getSystemTimeFromLocalTime
+ *--------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getSystemTimeFromLocalTime( TimeValue* pLocalTimeVal, TimeValue* pSystemTimeVal )
+{
+ struct tm *pLocalTime;
+ struct tm tmBuf;
+ time_t bias;
+ time_t atime;
+
+ atime = (time_t) pLocalTimeVal->Seconds;
+
+ /* Convert atime, which is a local time, to it's GMT equivalent. Then, get
+ * the timezone offset for the local time for the GMT equivalent time. Note
+ * that we cannot directly use local time to determine the timezone offset
+ * because GMT is the only reliable time that we can determine timezone
+ * offset from.
+ */
+
+ atime = mktime( gmtime_r( &atime, &tmBuf ) );
+ pLocalTime = localtime_r( &atime, &tmBuf );
+
+#if defined(STRUCT_TM_HAS_GMTOFF)
+ /* members of struct tm are corrected by mktime */
+ bias = 0 - pLocalTime->tm_gmtoff;
+
+#elif defined(HAS_ALTZONE)
+ /* check if daylight saving time is in effect */
+ bias = pLocalTime->tm_isdst > 0 ? altzone : timezone;
+#else
+ /* exspect daylight saving time to be one hour */
+ bias = pLocalTime->tm_isdst > 0 ? timezone - 3600 : timezone;
+#endif
+
+ if ( (sal_Int64) pLocalTimeVal->Seconds + bias > 0 )
+ {
+ pSystemTimeVal->Seconds = pLocalTimeVal->Seconds + bias;
+ pSystemTimeVal->Nanosec = pLocalTimeVal->Nanosec;
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+
+
+static struct timeval startTime;
+static sal_Bool bGlobalTimer = sal_False;
+
+sal_uInt32 SAL_CALL osl_getGlobalTimer()
+{
+ struct timeval currentTime;
+ sal_uInt32 nSeconds;
+
+ // FIXME: not thread safe !!
+ if ( bGlobalTimer == sal_False )
+ {
+ gettimeofday( &startTime, NULL );
+ bGlobalTimer=sal_True;
+ }
+
+ gettimeofday( &currentTime, NULL );
+
+ nSeconds = (sal_uInt32)( currentTime.tv_sec - startTime.tv_sec );
+
+ return ( nSeconds * 1000 ) + (long) (( currentTime.tv_usec - startTime.tv_usec) / 1000 );
+}
diff --git a/sal/osl/os2/util.c b/sal/osl/os2/util.c
new file mode 100644
index 000000000000..cfe3eb76c622
--- /dev/null
+++ b/sal/osl/os2/util.c
@@ -0,0 +1,37 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "osl/util.h"
+
+
+
+extern sal_Bool osl_getEthernetAddress( sal_uInt8 * pTargetAddress )
+{
+ return sal_False;
+}
+
+
diff --git a/sal/osl/os2/uunxapi.cxx b/sal/osl/os2/uunxapi.cxx
new file mode 100644
index 000000000000..e86ad31264e0
--- /dev/null
+++ b/sal/osl/os2/uunxapi.cxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #ifndef _LIMITS_H
+ #include <limits.h>
+ #endif
+
+ #ifndef _RTL_USTRING_HXX_
+ #include <rtl/ustring.hxx>
+ #endif
+
+ #ifndef _OSL_THREAD_H_
+ #include <osl/thread.h>
+ #endif
+
+ #ifndef _OSL_UUNXAPI_HXX_
+ #include "uunxapi.hxx"
+ #endif
+
+ //###########################
+ //access_u
+ int access_u(const rtl_uString* pustrPath, int mode)
+ {
+ return access(OUStringToOString(pustrPath).getStr(), mode);
+ }
+
+ //#########################
+ //realpath_u
+ sal_Bool realpath_u(const rtl_uString* pustrFileName, rtl_uString** ppustrResolvedName)
+ {
+ rtl::OString fn = rtl::OUStringToOString(
+ rtl::OUString(const_cast<rtl_uString*>(pustrFileName)),
+ osl_getThreadTextEncoding());
+
+ char rp[PATH_MAX];
+ bool bRet = realpath(fn.getStr(), rp);
+
+ if (bRet)
+ {
+ rtl::OUString resolved = rtl::OStringToOUString(
+ rtl::OString(static_cast<sal_Char*>(rp)),
+ osl_getThreadTextEncoding());
+
+ rtl_uString_assign(ppustrResolvedName, resolved.pData);
+ }
+ return bRet;
+ }
+
+ //#########################
+ //lstat_u
+ int lstat_u(const rtl_uString* pustrPath, struct stat* buf)
+ {
+ return lstat(OUStringToOString(pustrPath).getStr(), buf);
+ }
+
+ //#########################
+ // @see mkdir
+ int mkdir_u(const rtl_uString* path, mode_t mode)
+ {
+ return mkdir(OUStringToOString(path).getStr(), mode);
+ }
+
diff --git a/sal/osl/os2/uunxapi.h b/sal/osl/os2/uunxapi.h
new file mode 100644
index 000000000000..9eddc5fe4753
--- /dev/null
+++ b/sal/osl/os2/uunxapi.h
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #ifndef _OSL_UUNXAPI_H_
+ #define _OSL_UUNXAPI_H_
+
+ #ifndef _UNISTD_H
+ #include <unistd.h>
+ #endif
+
+ #ifndef _STDLIB_H
+ #include <stdlib.h>
+ #endif
+
+ #ifndef _TYPES_H
+ #include <sys/types.h>
+ #endif
+
+ #ifndef _STAT_H
+ #include <sys/stat.h>
+ #endif
+
+ #ifndef _RTL_USTRING_H_
+ #include <rtl/ustring.h>
+ #endif
+
+
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+
+ /* @see access */
+ int access_u(const rtl_uString* pustrPath, int mode);
+
+ /***********************************
+ @descr
+ The return value differs from the
+ realpath function
+
+ @returns sal_True on success else
+ sal_False
+
+ @see realpath
+ **********************************/
+ sal_Bool realpath_u(
+ const rtl_uString* pustrFileName,
+ rtl_uString** ppustrResolvedName);
+
+ /* @see lstat */
+ int lstat_u(const rtl_uString* pustrPath, struct stat* buf);
+
+ /* @see mkdir */
+ int mkdir_u(const rtl_uString* path, mode_t mode);
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+
+ #endif /* _OSL_UUNXAPI_H_ */
+
diff --git a/sal/osl/os2/uunxapi.hxx b/sal/osl/os2/uunxapi.hxx
new file mode 100644
index 000000000000..ab7e5cce890d
--- /dev/null
+++ b/sal/osl/os2/uunxapi.hxx
@@ -0,0 +1,106 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #ifndef _OSL_UUNXAPI_HXX_
+ #define _OSL_UUNXAPI_HXX_
+
+ #ifndef _OSL_UUNXAPI_H_
+ #include "uunxapi.h"
+ #endif
+
+ #ifndef _RTL_USTRING_HXX_
+ #include <rtl/ustring.hxx>
+ #endif
+
+ //###########################
+ inline rtl::OString OUStringToOString(const rtl_uString* s)
+ {
+ return rtl::OUStringToOString(
+ rtl::OUString(const_cast<rtl_uString*>(s)),
+ osl_getThreadTextEncoding());
+ }
+
+ namespace osl
+ {
+
+ /***********************************
+ osl::access
+
+ @see access
+ **********************************/
+
+ inline int access(const rtl::OUString& ustrPath, int mode)
+ {
+ return access_u(ustrPath.pData, mode);
+ }
+
+ /***********************************
+ osl::realpath
+
+ @descr
+ The return value differs from the
+ realpath function
+
+ @returns sal_True on success else
+ sal_False
+
+ @see realpath
+ **********************************/
+
+ inline sal_Bool realpath(
+ const rtl::OUString& ustrFileName,
+ rtl::OUString& ustrResolvedName)
+ {
+ return realpath_u(ustrFileName.pData, &ustrResolvedName.pData);
+ }
+
+
+ /***********************************
+ osl::lstat
+
+ @see lstat
+ **********************************/
+
+ inline int lstat(const rtl::OUString& ustrPath, struct stat& buf)
+ {
+ return lstat_u(ustrPath.pData, &buf);
+ }
+
+ /***********************************
+ osl::mkdir
+ @see mkdir
+ **********************************/
+ inline int mkdir(const rtl::OUString& aPath, mode_t aMode)
+ {
+ return mkdir_u(aPath.pData, aMode);
+ }
+
+ } // end namespace osl
+
+
+ #endif /* _OSL_UUNXAPI_HXX_ */
+
diff --git a/sal/osl/unx/asm/interlck_sparc.s b/sal/osl/unx/asm/interlck_sparc.s
new file mode 100644
index 000000000000..a33e3539398e
--- /dev/null
+++ b/sal/osl/unx/asm/interlck_sparc.s
@@ -0,0 +1,267 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+/*
+ * Implements osl_[increment|decrement]InterlockedCount in two ways:
+ * sparcv8 architecture: use the "swap" instruction
+ * sparcv9/sparcv8plus architecture: use the "cas" instruction
+ *
+ * 32 bit mode with v8 and v8plus support:
+ * Initialize once with osl_InterlockedCountSetV9(int bv9) if you want to
+ * use the "cas" instruction, which is faster (no spinlock needed)
+ * Default is to use the "swap" instruction, which works on all supported
+ * SPARC cpu's
+ *
+ * osl_InterlockedCountSetV9(int bv9)
+ * bv9 = 0 use sparcv8 "swap" (spinlock)
+ * bv9 = 1 use sparcv9/sparcv8plus "cas" (no spinlock)
+ *
+ * 32 bit mode without v8 support (implies v8plus) or 64 bit mode:
+ * No need (nor the possibilty) to call osl_InterlockedCountSetV9(),
+ * sparcv9 mode is implied. Assemble with -xarch=v8plus (32 bit) or
+ * -xarch=v9 (64 bit).
+ *
+ */
+
+#if !defined(__sparcv8plus) && !defined(__sparcv9) && !defined(__sparc_v9__)
+
+.section ".data"
+.align 4
+osl_incrementInterLockCountFuncPtr:
+.word osl_incrementInterlockedCountV8
+.type osl_incrementInterLockCountFuncPtr,#object
+.size osl_incrementInterLockCountFuncPtr,4
+
+.align 4
+osl_decrementInterLockCountFuncPtr:
+.word osl_decrementInterlockedCountV8
+.type osl_decrementInterLockCountFuncPtr,#object
+.size osl_decrementInterLockCountFuncPtr,4
+
+.section ".text"
+
+#if defined(NETBSD) || defined(LINUX)
+/* add the address of the calling "call" instruction (stored in %o7) to
+ * %o5 which contains _GLOBAL_OFFSET_TABLE_
+ */
+.Laddoseven:
+ retl
+ add %o7, %o5, %o5
+#endif
+
+ .global osl_incrementInterlockedCount
+ .align 4
+
+osl_incrementInterlockedCount:
+
+#if defined(NETBSD) || defined(LINUX)
+ mov %o7, %g1
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
+ call .Laddoseven
+ add %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
+ mov %g1, %o7
+#endif
+ set osl_incrementInterLockCountFuncPtr, %o1
+#if defined(NETBSD)
+ ld [%o1 + %o5], %o1
+#endif
+ ld [%o1], %o1
+ jmp %o1
+ nop ! delay slot
+ .type osl_incrementInterlockedCount,#function
+ .size osl_incrementInterlockedCount,.-osl_incrementInterlockedCount
+
+.section ".text"
+ .global osl_decrementInterlockedCount
+ .align 4
+
+osl_decrementInterlockedCount:
+
+#if defined(NETBSD) || defined(LINUX)
+ mov %o7, %g1
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
+ call .Laddoseven
+ add %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
+ mov %g1, %o7
+#endif
+ set osl_decrementInterLockCountFuncPtr, %o1
+#if defined(NETBSD) || defined(LINUX)
+ ld [%o1 + %o5], %o1
+#endif
+ ld [%o1], %o1
+ jmp %o1
+ nop ! delay slot
+ .type osl_decrementInterlockedCount,#function
+ .size osl_decrementInterlockedCount,.-osl_decrementInterlockedCount
+
+.section ".text"
+ .global osl_InterlockedCountSetV9
+ .align 4
+
+osl_InterlockedCountSetV9:
+
+#if defined(NETBSD) || defined(LINUX)
+ mov %o7, %g1
+ sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o5
+ call .Laddoseven
+ add %o5, %lo(_GLOBAL_OFFSET_TABLE_+4), %o5
+ mov %g1, %o7
+#endif
+ set osl_incrementInterLockCountFuncPtr, %o1
+ set osl_decrementInterLockCountFuncPtr, %o2
+ cmp %o0, %g0
+ bnz 1f
+ nop ! delay slot
+ set osl_incrementInterlockedCountV8, %o0
+ set osl_decrementInterlockedCountV8, %o3
+#if defined(NETBSD) || defined(LINUX)
+ ld [%o0 + %o5], %o0
+ ld [%o1 + %o5], %o1
+ ld [%o2 + %o5], %o2
+ ld [%o3 + %o5], %o3
+#endif
+ st %o3,[%o2]
+ retl
+ st %o0,[%o1]
+1: set osl_incrementInterlockedCountV9, %o0
+ set osl_decrementInterlockedCountV9, %o3
+#if defined(NETBSD) || defined(LINUX)
+ ld [%o0 + %o5], %o0
+ ld [%o1 + %o5], %o1
+ ld [%o2 + %o5], %o2
+ ld [%o3 + %o5], %o3
+#endif
+ st %o3,[%o2]
+ retl
+ st %o0,[%o1]
+
+ .type osl_InterlockedCountSetV9,#function
+ .size osl_InterlockedCountSetV9,.-osl_InterlockedCountSetV9
+
+
+.section ".text"
+ .local osl_incrementInterlockedCountV8
+ .align 4
+
+! Implements osl_[increment|decrement]InterlockedCount with sparcv8 "swap" instruction.
+! Uses -4096 as lock value for spinlock to allow for small negative counts.
+
+osl_incrementInterlockedCountV8:
+
+1: ld [%o0], %o1
+ cmp %o1, -4096 ! test spinlock
+ be 1b
+ mov -4096, %o1 ! delay slot
+ swap [%o0], %o1
+ cmp %o1, -4096
+ be 1b
+ inc %o1 ! delay slot, if we got spinlock, increment count
+ st %o1, [%o0]
+ retl
+ mov %o1, %o0 ! delay slot
+
+ .type osl_incrementInterlockedCountV8,#function
+ .size osl_incrementInterlockedCountV8,.-osl_incrementInterlockedCountV8
+
+
+.section ".text"
+ .local osl_decrementInterlockedCountV8
+ .align 4
+
+osl_decrementInterlockedCountV8:
+
+1: ld [%o0], %o1
+ cmp %o1, -4096 ! test spinlock
+ be 1b
+ mov -4096, %o1 ! delay slot
+ swap [%o0], %o1
+ cmp %o1, -4096
+ be 1b
+ dec %o1 ! delay slot, if we got spinlock, decrement count
+ st %o1, [%o0] ! delay slot
+ retl
+ mov %o1, %o0 ! delay slot
+
+ .type osl_decrementInterlockedCountV8,#function
+ .size osl_decrementInterlockedCountV8,.-osl_decrementInterlockedCountV8
+
+#endif /* !__sparcv8plus && !__sparcv9 && !_sparcv9__ */
+
+.section ".text"
+#if defined(__sparcv8plus) || defined(__sparcv9) || defined(__sparc_v9__)
+#define osl_incrementInterlockedCountV9 osl_incrementInterlockedCount
+ .global osl_incrementInterlockedCountV9
+#else
+ .local osl_incrementInterlockedCountV9
+#endif
+ .align 8
+
+! Implements osl_[increment|decrement]InterlockedCount with sparcv9(sparcv8plus) "cas"
+! instruction.
+
+osl_incrementInterlockedCountV9:
+
+1: ld [%o0], %o1
+ add %o1, 1, %o2
+! allow linux to build for v8
+ .word 0xD5E21009
+! cas [%o0], %o1, %o2
+ cmp %o1, %o2
+ bne 1b
+ nop ! delay slot
+ retl
+ add %o2, 1, %o0 ! delay slot
+
+ .type osl_incrementInterlockedCountV9,#function
+ .size osl_incrementInterlockedCountV9,.-osl_incrementInterlockedCountV9
+
+
+.section ".text"
+#if defined(__sparcv8plus) || defined(__sparcv9) || defined(__sparc_v9__)
+#define osl_decrementInterlockedCountV9 osl_decrementInterlockedCount
+ .global osl_decrementInterlockedCountV9
+#else
+ .local osl_decrementInterlockedCountV9
+#endif
+ .align 8
+
+osl_decrementInterlockedCountV9:
+
+1: ld [%o0], %o1
+ sub %o1, 1, %o2
+! allow linux to build for v8
+ .word 0xD5E21009
+! cas [%o0], %o1, %o2
+ cmp %o1, %o2
+ bne 1b
+ nop ! delay slot
+ retl
+ sub %o2, 1, %o0 ! delay slot
+
+ .type osl_decrementInterlockedCountV9,#function
+ .size osl_decrementInterlockedCountV9,.-osl_decrementInterlockedCountV9
diff --git a/sal/osl/unx/asm/interlck_x86.s b/sal/osl/unx/asm/interlck_x86.s
new file mode 100644
index 000000000000..c1f99008d406
--- /dev/null
+++ b/sal/osl/unx/asm/interlck_x86.s
@@ -0,0 +1,92 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+.section .text,"ax"
+ .globl osl_incrementInterlockedCount
+
+osl_incrementInterlockedCount:
+
+ push %ebp
+ mov %esp,%ebp
+ push %ebx
+ call 1f
+1:
+ pop %ebx
+ add $_GLOBAL_OFFSET_TABLE_+0x1,%ebx
+ mov 8(%ebp),%ecx
+ mov $1,%eax
+ mov osl_isSingleCPU@GOT(%ebx),%edx
+ cmp $0,(%edx)
+ je 2f
+ xadd %eax,(%ecx)
+ jmp 3f
+2:
+ lock
+ xadd %eax,(%ecx)
+3:
+ inc %eax
+ pop %ebx
+ mov %ebp,%esp
+ pop %ebp
+ ret
+
+ .type osl_incrementInterlockedCount,@function
+ .size osl_incrementInterlockedCount,.-osl_incrementInterlockedCount
+
+.section .text,"ax"
+ .globl osl_decrementInterlockedCount
+
+osl_decrementInterlockedCount:
+
+ push %ebp
+ mov %esp,%ebp
+ push %ebx
+ call 1f
+1:
+ pop %ebx
+ add $_GLOBAL_OFFSET_TABLE_+0x1,%ebx
+ mov 8(%ebp),%ecx
+ orl $-1,%eax
+ mov osl_isSingleCPU@GOT(%ebx),%edx
+ cmp $0,(%edx)
+ je 2f
+ xadd %eax,(%ecx)
+ jmp 3f
+2:
+ lock
+ xadd %eax,(%ecx)
+3:
+ dec %eax
+ pop %ebx
+ mov %ebp,%esp
+ pop %ebp
+ ret
+
+ .type osl_decrementInterlockedCount,@function
+ .size osl_decrementInterlockedCount,.-osl_decrementInterlockedCount
+
diff --git a/sal/osl/unx/backtrace.c b/sal/osl/unx/backtrace.c
new file mode 100755
index 000000000000..00156b80f1d6
--- /dev/null
+++ b/sal/osl/unx/backtrace.c
@@ -0,0 +1,359 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#ifdef SOLARIS
+
+#include <dlfcn.h>
+#include <pthread.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <sys/frame.h>
+#include "backtrace.h"
+
+#if defined(SPARC)
+
+#if defined IS_LP64
+
+#define FRAME_PTR_OFFSET 1
+#define FRAME_OFFSET 0
+#define STACK_BIAS 0x7ff
+
+#else
+
+#define FRAME_PTR_OFFSET 1
+#define FRAME_OFFSET 0
+#define STACK_BIAS 0
+
+#endif
+
+#elif defined( INTEL )
+
+#define FRAME_PTR_OFFSET 3
+#define FRAME_OFFSET 0
+#define STACK_BIAS 0
+
+#else
+
+#error Unknown Solaris target platform.
+
+#endif /* defined SPARC or INTEL */
+
+
+int backtrace( void **buffer, int max_frames )
+{
+ jmp_buf ctx;
+ long fpval;
+ struct frame *fp;
+ int i;
+
+ /* flush register windows */
+#ifdef SPARC
+ asm("ta 3");
+#endif
+
+ /* get stack- and framepointer */
+ setjmp(ctx);
+
+ fpval = ((long*)(ctx))[FRAME_PTR_OFFSET];
+ fp = (struct frame*)((char*)(fpval) + STACK_BIAS);
+
+ for (i = 0; (i < FRAME_OFFSET) && (fp != 0); i++)
+ fp = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
+
+ /* iterate through backtrace */
+ for (i = 0; (fp != 0) && (fp->fr_savpc != 0) && (i < max_frames); i++)
+ {
+ /* saved (prev) frame */
+ struct frame * prev = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
+
+ /* store frame */
+ *(buffer++) = (void*)(fp->fr_savpc);
+
+ /* prev frame (w/ stack growing top down) */
+ fp = (prev > fp) ? prev : 0;
+ }
+
+ /* return number of frames stored */
+ return i;
+}
+
+void backtrace_symbols_fd( void **buffer, int size, int fd )
+{
+ FILE *fp = fdopen( fd, "w" );
+
+ if ( fp )
+ {
+ void **pFramePtr;
+
+ for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
+ {
+ Dl_info dli;
+ ptrdiff_t offset;
+
+ if ( 0 != dladdr( *pFramePtr, &dli ) )
+ {
+ if ( dli.dli_fname && dli.dli_fbase )
+ {
+ offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
+ fprintf( fp, "%s+0x%x", dli.dli_fname, offset );
+ }
+ if ( dli.dli_sname && dli.dli_saddr )
+ {
+ offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
+ fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset );
+ }
+ }
+ fprintf( fp, "[0x%x]\n", *pFramePtr );
+ }
+
+ fflush( fp );
+ fclose( fp );
+ }
+}
+
+#endif /* defined SOLARIS */
+
+
+#if defined FREEBSD || defined NETBSD
+#include <dlfcn.h>
+#include <pthread.h>
+#include <setjmp.h>
+#include <stddef.h>
+#include <stdio.h>
+#include "backtrace.h"
+
+#define FRAME_PTR_OFFSET 1
+#define FRAME_OFFSET 0
+
+int backtrace( void **buffer, int max_frames )
+{
+ struct frame *fp;
+ jmp_buf ctx;
+ int i;
+ /* get stack- and framepointer */
+ setjmp(ctx);
+ fp = (struct frame*)(((size_t*)(ctx))[FRAME_PTR_OFFSET]);
+ for ( i=0; (i<FRAME_OFFSET) && (fp!=0); i++)
+ fp = fp->fr_savfp;
+ /* iterate through backtrace */
+ for (i=0; fp && fp->fr_savpc && i<max_frames; i++)
+ {
+ /* store frame */
+ *(buffer++) = (void *)fp->fr_savpc;
+ /* next frame */
+ fp=fp->fr_savfp;
+ }
+ return i;
+}
+
+void backtrace_symbols_fd( void **buffer, int size, int fd )
+{
+ FILE *fp = fdopen( fd, "w" );
+
+ if ( fp )
+ {
+ void **pFramePtr;
+ for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
+ {
+ Dl_info dli;
+ ptrdiff_t offset;
+
+ if ( 0 != dladdr( *pFramePtr, &dli ) )
+ {
+ if ( dli.dli_fname && dli.dli_fbase )
+ {
+ offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
+ fprintf( fp, "%s+0x%x", dli.dli_fname, offset );
+ }
+ if ( dli.dli_sname && dli.dli_saddr )
+ {
+ offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
+ fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset );
+ }
+ }
+ fprintf( fp, "[0x%x]\n", *pFramePtr );
+ }
+ fflush( fp );
+ fclose( fp );
+ }
+}
+#endif /* defined FREEBSD */
+
+#ifdef LINUX
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <dlfcn.h>
+#include <pthread.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include "backtrace.h"
+
+#if defined(SPARC)
+
+#define FRAME_PTR_OFFSET 1
+#define FRAME_OFFSET 0
+
+#else
+
+#error Unknown Linux target platform.
+
+#endif /* defined SPARC or INTEL */
+
+typedef int ptrdiff_t;
+
+int backtrace( void **buffer, int max_frames )
+{
+ struct frame *fp;
+ jmp_buf ctx;
+ int i;
+
+ /* flush register windows */
+#ifdef SPARC
+ asm("ta 3");
+#endif
+ /* get stack- and framepointer */
+ setjmp(ctx);
+ fp = (struct frame*)(((size_t*)(ctx))[FRAME_PTR_OFFSET]);
+ for ( i=0; (i<FRAME_OFFSET) && (fp!=0); i++)
+ fp = fp->fr_savfp;
+
+ /* iterate through backtrace */
+ for (i=0; fp && fp->fr_savpc && i<max_frames; i++)
+ {
+ /* store frame */
+ *(buffer++) = (void *)fp->fr_savpc;
+ /* next frame */
+ fp=fp->fr_savfp;
+ }
+ return i;
+}
+
+void backtrace_symbols_fd( void **buffer, int size, int fd )
+{
+ FILE *fp = fdopen( fd, "w" );
+
+ if ( fp )
+ {
+ void **pFramePtr;
+
+ for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
+ {
+ Dl_info dli;
+ ptrdiff_t offset;
+
+ if ( 0 != dladdr( *pFramePtr, &dli ) )
+ {
+ if ( dli.dli_fname && dli.dli_fbase )
+ {
+ offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
+ fprintf( fp, "%s+0x%x", dli.dli_fname, offset );
+ }
+ if ( dli.dli_sname && dli.dli_saddr )
+ {
+ offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
+ fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset );
+ }
+ }
+ fprintf( fp, "[0x%x]\n", *pFramePtr );
+ }
+
+ fflush( fp );
+ fclose( fp );
+ }
+}
+
+#endif /* defined LINUX */
+
+#if defined( MACOSX )
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include "backtrace.h"
+
+typedef unsigned ptrdiff_t;
+
+/* glib backtrace is only available on MacOsX 10.5 or higher
+ so we do it on our own */
+
+int backtrace( void **buffer, int max_frames )
+{
+ void **frame = (void **)__builtin_frame_address(0);
+ void **bp = ( void **)(*frame);
+ void *ip = frame[1];
+ int i;
+
+ for ( i = 0; bp && ip && i < max_frames; i++ )
+ {
+ *(buffer++) = ip;
+
+ ip = bp[1];
+ bp = (void**)(bp[0]);
+ }
+
+ return i;
+}
+
+
+void backtrace_symbols_fd( void **buffer, int size, int fd )
+{
+ FILE *fp = fdopen( fd, "w" );
+
+ if ( fp )
+ {
+ void **pFramePtr;
+
+ for ( pFramePtr = buffer; size > 0 && pFramePtr && *pFramePtr; pFramePtr++, size-- )
+ {
+ Dl_info dli;
+ ptrdiff_t offset;
+
+ if ( 0 != dladdr( *pFramePtr, &dli ) )
+ {
+ if ( dli.dli_fname && dli.dli_fbase )
+ {
+ offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_fbase;
+ fprintf( fp, "%s+0x%x", dli.dli_fname, offset );
+ }
+ if ( dli.dli_sname && dli.dli_saddr )
+ {
+ offset = (ptrdiff_t)*pFramePtr - (ptrdiff_t)dli.dli_saddr;
+ fprintf( fp, "(%s+0x%x)", dli.dli_sname, offset );
+ }
+ }
+ fprintf( fp, "[0x%x]\n", (unsigned int)*pFramePtr );
+ }
+
+ fflush( fp );
+ fclose( fp );
+ }
+}
+
+#endif /* defined MACOSX */
diff --git a/sal/osl/unx/backtrace.h b/sal/osl/unx/backtrace.h
new file mode 100755
index 000000000000..1ca2ae84c4a0
--- /dev/null
+++ b/sal/osl/unx/backtrace.h
@@ -0,0 +1,99 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#if defined (SOLARIS) || (FREEBSD)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* backtrace function with same behaviour as defined in GNU libc */
+
+int backtrace( void **buffer, int max_frames );
+
+void backtrace_symbols_fd( void **buffer, int size, int fd );
+
+/* no frame.h on FreeBSD */
+#if defined FREEBSD
+struct frame {
+ long arg0[8];
+ long arg1[6];
+ struct frame *fr_savfp;
+ long fr_savpc;
+};
+#endif
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* defined SOLARIS || FREEBSD */
+
+#if defined (LINUX) && defined (SPARC)
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* backtrace function with same behaviour as defined in GNU libc */
+
+int backtrace( void **buffer, int max_frames );
+
+void backtrace_symbols_fd( void **buffer, int size, int fd );
+
+/* no frame.h on linux sparc */
+struct frame {
+ long arg0[8];
+ long arg1[6];
+ struct frame *fr_savfp;
+ long fr_savpc;
+};
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* defined LINUX && SPARC */
+
+#if defined (MACOSX)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* backtrace function with same behaviour as defined in GNU libc */
+
+int backtrace( void **buffer, int max_frames );
+
+void backtrace_symbols_fd( void **buffer, int size, int fd );
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* defined MACOSX */
diff --git a/sal/osl/unx/conditn.c b/sal/osl/unx/conditn.c
new file mode 100644
index 000000000000..ea701d221e55
--- /dev/null
+++ b/sal/osl/unx/conditn.c
@@ -0,0 +1,350 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+#include <sal/types.h>
+
+#include <osl/conditn.h>
+#include <osl/diagnose.h>
+#include <osl/time.h>
+
+
+typedef struct _oslConditionImpl
+{
+ pthread_cond_t m_Condition;
+ pthread_mutex_t m_Lock;
+ sal_Bool m_State;
+} oslConditionImpl;
+
+
+/*****************************************************************************/
+/* osl_createCondition */
+/*****************************************************************************/
+oslCondition SAL_CALL osl_createCondition()
+{
+ oslConditionImpl* pCond;
+ int nRet=0;
+
+ pCond = (oslConditionImpl*) malloc(sizeof(oslConditionImpl));
+
+ OSL_ASSERT(pCond);
+
+ if ( pCond == 0 )
+ {
+ return 0;
+ }
+
+ pCond->m_State = sal_False;
+
+ /* init condition variable with default attr. (PTHREAD_PROCESS_PRIVAT) */
+ nRet = pthread_cond_init(&pCond->m_Condition, PTHREAD_CONDATTR_DEFAULT);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_createCondition : condition init failed. Errno: %d; '%s'\n",
+ nRet, strerror(nRet));
+
+ free(pCond);
+ return 0;
+ }
+
+ nRet = pthread_mutex_init(&pCond->m_Lock, PTHREAD_MUTEXATTR_DEFAULT);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_createCondition : mutex init failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+
+ nRet = pthread_cond_destroy(&pCond->m_Condition);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_createCondition : destroy condition failed. Errno: %d; '%s'\n",
+ nRet, strerror(nRet));
+ }
+
+ free(pCond);
+ pCond = 0;
+ }
+
+ return (oslCondition)pCond;
+}
+
+/*****************************************************************************/
+/* osl_destroyCondition */
+/*****************************************************************************/
+void SAL_CALL osl_destroyCondition(oslCondition Condition)
+{
+ oslConditionImpl* pCond;
+ int nRet = 0;
+
+ if ( Condition )
+ {
+ pCond = (oslConditionImpl*)Condition;
+
+ nRet = pthread_cond_destroy(&pCond->m_Condition);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_destroyCondition : destroy condition failed. Errno: %d; '%s'\n",
+ nRet, strerror(nRet));
+ }
+ nRet = pthread_mutex_destroy(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_destroyCondition : destroy mutex failed. Errno: %d; '%s'\n",
+ nRet, strerror(nRet));
+ }
+
+ free(Condition);
+ }
+
+ return;
+}
+
+/*****************************************************************************/
+/* osl_setCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setCondition(oslCondition Condition)
+{
+ oslConditionImpl* pCond;
+ int nRet=0;
+
+ OSL_ASSERT(Condition);
+ pCond = (oslConditionImpl*)Condition;
+
+ if ( pCond == 0 )
+ {
+ return sal_False;
+ }
+
+ nRet = pthread_mutex_lock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_setCondition : mutex lock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ return sal_False;
+ }
+
+ pCond->m_State = sal_True;
+ nRet = pthread_cond_broadcast(&pCond->m_Condition);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_setCondition : condition broadcast failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ return sal_False;
+ }
+
+ nRet = pthread_mutex_unlock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_setCondition : mutex unlock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ return sal_False;
+ }
+
+ return sal_True;
+
+}
+
+/*****************************************************************************/
+/* osl_resetCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_resetCondition(oslCondition Condition)
+{
+ oslConditionImpl* pCond;
+ int nRet=0;
+
+ OSL_ASSERT(Condition);
+
+ pCond = (oslConditionImpl*)Condition;
+
+ if ( pCond == 0 )
+ {
+ return sal_False;
+ }
+
+ nRet = pthread_mutex_lock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_resetCondition : mutex lock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ return sal_False;
+ }
+
+ pCond->m_State = sal_False;
+
+ nRet = pthread_mutex_unlock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_resetCondition : mutex unlock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_waitCondition */
+/*****************************************************************************/
+oslConditionResult SAL_CALL osl_waitCondition(oslCondition Condition, const TimeValue* pTimeout)
+{
+ oslConditionImpl* pCond;
+ int nRet=0;
+ oslConditionResult Result = osl_cond_result_ok;
+
+ OSL_ASSERT(Condition);
+ pCond = (oslConditionImpl*)Condition;
+
+ if ( pCond == 0 )
+ {
+ return osl_cond_result_error;
+ }
+
+ nRet = pthread_mutex_lock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_waitCondition : mutex lock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ return osl_cond_result_error;
+ }
+
+ if ( pTimeout )
+ {
+ if ( ! pCond->m_State )
+ {
+ int ret;
+ struct timeval tp;
+ struct timespec to;
+
+ gettimeofday(&tp, NULL);
+
+ SET_TIMESPEC( to, tp.tv_sec + pTimeout->Seconds,
+ tp.tv_usec * 1000 + pTimeout->Nanosec );
+
+ /* spurious wake up prevention */
+ do
+ {
+ ret = pthread_cond_timedwait(&pCond->m_Condition, &pCond->m_Lock, &to);
+ if ( ret != 0 )
+ {
+ if ( ret == ETIME || ret == ETIMEDOUT )
+ {
+ Result = osl_cond_result_timeout;
+ nRet = pthread_mutex_unlock(&pCond->m_Lock);
+ if (nRet != 0)
+ {
+ OSL_TRACE("osl_waitCondition : mutex unlock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ }
+
+ return Result;
+ }
+ else if ( ret != EINTR )
+ {
+ Result = osl_cond_result_error;
+ nRet = pthread_mutex_unlock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_waitCondition : mutex unlock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ }
+ return Result;
+ }
+/* OSL_TRACE("EINTR\n");*/
+ }
+ }
+ while ( !pCond->m_State );
+ }
+ }
+ else
+ {
+ while ( !pCond->m_State )
+ {
+ nRet = pthread_cond_wait(&pCond->m_Condition, &pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_waitCondition : condition wait failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ Result = osl_cond_result_error;
+ nRet = pthread_mutex_unlock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_waitCondition : mutex unlock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ }
+
+ return Result;
+ }
+ }
+ }
+
+ nRet = pthread_mutex_unlock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_waitCondition : mutex unlock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ }
+
+ return Result;
+}
+
+/*****************************************************************************/
+/* osl_checkCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_checkCondition(oslCondition Condition)
+{
+ sal_Bool State;
+ oslConditionImpl* pCond;
+ int nRet=0;
+
+ OSL_ASSERT(Condition);
+ pCond = (oslConditionImpl*)Condition;
+
+ if ( pCond == 0 )
+ {
+ return sal_False;
+ }
+
+ nRet = pthread_mutex_lock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_checkCondition : mutex unlock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ }
+
+ State = pCond->m_State;
+
+ nRet = pthread_mutex_unlock(&pCond->m_Lock);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_checkCondition : mutex unlock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ }
+
+ return State;
+}
+
+
diff --git a/sal/osl/unx/diagnose.c b/sal/osl/unx/diagnose.c
new file mode 100644
index 000000000000..bb8cbca406bd
--- /dev/null
+++ b/sal/osl/unx/diagnose.c
@@ -0,0 +1,332 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "osl/diagnose.h"
+#include "system.h"
+
+
+#ifndef HAVE_DLFCN_H
+
+#if defined(LINUX) || defined(SOLARIS)
+#define HAVE_DLFCN_H
+#endif /* LINUX || SOLARIS */
+
+#endif /* HAVE_DLFCN_H */
+
+
+#ifdef HAVE_DLFCN_H
+
+#ifndef INCLUDED_DLFCN_H
+#include <dlfcn.h>
+#define INCLUDED_DLFCN_H
+#endif
+
+#endif /* HAVE_DLFCN_H */
+#include "osl/thread.h"
+
+#ifndef INCLUDED_PTHREAD_H
+#include <pthread.h>
+#define INCLUDED_PTHREAD_H
+#endif
+
+#ifndef INCLUDED_STDDEF_H
+#include <stddef.h>
+#define INCLUDED_STDDEF_H
+#endif
+
+/************************************************************************/
+/* Internal data structures and functions */
+/************************************************************************/
+
+static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+typedef pfunc_osl_printDebugMessage oslDebugMessageFunc;
+static oslDebugMessageFunc volatile g_pDebugMessageFunc = 0;
+
+typedef pfunc_osl_printDetailedDebugMessage oslDetailedDebugMessageFunc;
+static oslDetailedDebugMessageFunc volatile g_pDetailedDebugMessageFunc = 0;
+
+static void osl_diagnose_backtrace_Impl (
+ oslDebugMessageFunc f);
+
+#define OSL_DIAGNOSE_OUTPUTMESSAGE(f, s) \
+((f != 0) ? (*(f))((s)) : (void)fprintf(stderr, "%s", (s)))
+
+#if defined (LINUX) || defined (SOLARIS)
+/************************************************************************/
+/* osl_diagnose_frame_Impl */
+/************************************************************************/
+static void osl_diagnose_frame_Impl (
+ oslDebugMessageFunc f,
+ int depth,
+ void * pc)
+{
+ const char *fname = 0, *sname = 0;
+ void *fbase = 0, *saddr = 0;
+ ptrdiff_t offset;
+ char szMessage[1024];
+
+#ifdef INCLUDED_DLFCN_H
+ Dl_info dli;
+ if (dladdr (pc, &dli) != 0)
+ {
+ fname = dli.dli_fname;
+ fbase = dli.dli_fbase;
+ sname = dli.dli_sname;
+ saddr = dli.dli_saddr;
+ }
+#endif /* INCLUDED_DLFCN_H */
+
+ if (saddr)
+ offset = (ptrdiff_t)(pc) - (ptrdiff_t)(saddr);
+ else if (fbase)
+ offset = (ptrdiff_t)(pc) - (ptrdiff_t)(fbase);
+ else
+ offset = (ptrdiff_t)(pc);
+
+ snprintf (szMessage, sizeof(szMessage),
+ "Backtrace: [%d] %s: %s+0x%" SAL_PRI_PTRDIFFT "x\n",
+ depth,
+ fname ? fname : "<unknown>",
+ sname ? sname : "???",
+ offset);
+
+ OSL_DIAGNOSE_OUTPUTMESSAGE(f, szMessage);
+}
+#endif
+
+/************************************************************************/
+/* osl_diagnose_backtrace_Impl */
+/************************************************************************/
+#if defined(LINUX)
+
+#include <execinfo.h>
+
+#define FRAME_COUNT 64
+#define FRAME_OFFSET 1
+
+static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
+{
+ void * ppFrames[FRAME_COUNT];
+ int i, n;
+
+ n = backtrace (ppFrames, FRAME_COUNT);
+ for (i = FRAME_OFFSET; i < n; i++)
+ {
+ osl_diagnose_frame_Impl (f, (i - FRAME_OFFSET), ppFrames[i]);
+ }
+}
+
+#elif defined(SOLARIS)
+
+#include <pthread.h>
+#include <setjmp.h>
+#include <sys/frame.h>
+
+#if defined(SPARC)
+
+#if defined IS_LP64
+
+#define FRAME_PTR_OFFSET 1
+#define FRAME_OFFSET 0
+#define STACK_BIAS 0x7ff
+
+#else
+
+#define FRAME_PTR_OFFSET 1
+#define FRAME_OFFSET 0
+#define STACK_BIAS 0
+
+#endif
+
+#elif defined(INTEL)
+
+#define FRAME_PTR_OFFSET 3
+#define FRAME_OFFSET 0
+#define STACK_BIAS 0
+
+#endif /* (SPARC || INTEL) */
+
+static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
+{
+ jmp_buf ctx;
+ long fpval;
+ struct frame * fp;
+ int i;
+
+#if defined(SPARC)
+ asm("ta 3");
+#endif /* SPARC */
+ setjmp (ctx);
+
+ fpval = ((long*)(ctx))[FRAME_PTR_OFFSET];
+ fp = (struct frame*)((char*)(fpval) + STACK_BIAS);
+
+ for (i = 0; (i < FRAME_OFFSET) && (fp != 0); i++)
+ fp = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
+
+ for (i = 0; (fp != 0) && (fp->fr_savpc != 0); i++)
+ {
+ struct frame * prev = (struct frame*)((char*)(fp->fr_savfp) + STACK_BIAS);
+ osl_diagnose_frame_Impl (f, i, (void*)(fp->fr_savpc));
+ fp = (prev > fp) ? prev : 0;
+ }
+}
+
+#else /* (LINUX || SOLARIS) */
+
+static void osl_diagnose_backtrace_Impl (oslDebugMessageFunc f)
+{
+ /* not yet implemented */
+}
+
+#endif /* (LINUX || SOLARIS) */
+
+/************************************************************************/
+/* osl_assertFailedLine */
+/************************************************************************/
+sal_Bool SAL_CALL osl_assertFailedLine (
+ const sal_Char* pszFileName,
+ sal_Int32 nLine,
+ const sal_Char* pszMessage)
+{
+ oslDebugMessageFunc f = g_pDebugMessageFunc;
+ char szMessage[1024];
+
+ /* If there's a callback for detailed messages, use it */
+ if ( g_pDetailedDebugMessageFunc != NULL )
+ {
+ g_pDetailedDebugMessageFunc( pszFileName, nLine, pszMessage );
+ return sal_False;
+ }
+
+ /* if SAL assertions are disabled in general, stop here */
+ if ( getenv("DISABLE_SAL_DBGBOX") )
+ return sal_False;
+
+ /* format message into buffer */
+ if (pszMessage != 0)
+ {
+ snprintf(szMessage, sizeof(szMessage),
+ "Error: File %s, Line %" SAL_PRIdINT32 ": %s\n",
+ pszFileName, nLine, pszMessage);
+ }
+ else
+ {
+ snprintf(szMessage, sizeof(szMessage),
+ "Error: File %s, Line %" SAL_PRIdINT32 "\n",
+ pszFileName, nLine);
+ }
+
+ /* acquire lock to serialize output message(s) */
+ pthread_mutex_lock(&g_mutex);
+
+ /* output message buffer */
+ OSL_DIAGNOSE_OUTPUTMESSAGE(f, szMessage);
+
+ /* output backtrace */
+ osl_diagnose_backtrace_Impl(f);
+
+ /* release lock and leave, w/o calling osl_breakDebug() */
+ pthread_mutex_unlock(&g_mutex);
+ return sal_False;
+}
+
+/************************************************************************/
+/* osl_breakDebug */
+/************************************************************************/
+void SAL_CALL osl_breakDebug()
+{
+ exit(0);
+}
+
+/************************************************************************/
+/* osl_reportError */
+/************************************************************************/
+sal_Int32 SAL_CALL osl_reportError (
+ sal_uInt32 nType,
+ const sal_Char* pszMessage)
+{
+ (void) nType; /* unused */
+ fputs(pszMessage, stderr);
+ return 0;
+}
+
+/************************************************************************/
+/* osl_setDebugMessageFunc */
+/************************************************************************/
+oslDebugMessageFunc SAL_CALL osl_setDebugMessageFunc (
+ oslDebugMessageFunc pNewFunc)
+{
+ oslDebugMessageFunc pOldFunc = g_pDebugMessageFunc;
+ g_pDebugMessageFunc = pNewFunc;
+ return pOldFunc;
+}
+
+/************************************************************************/
+/* osl_setDetailedDebugMessageFunc */
+/************************************************************************/
+pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc (
+ pfunc_osl_printDetailedDebugMessage pNewFunc)
+{
+ oslDetailedDebugMessageFunc pOldFunc = g_pDetailedDebugMessageFunc;
+ g_pDetailedDebugMessageFunc = pNewFunc;
+ return pOldFunc;
+}
+
+/************************************************************************/
+/* osl_trace */
+/************************************************************************/
+/* comment this define to stop output thread identifier*/
+#define OSL_TRACE_THREAD 1
+void SAL_CALL osl_trace (
+ const sal_Char* lpszFormat, ...)
+{
+ va_list args;
+
+#if defined(OSL_PROFILING)
+ fprintf(stderr, "Time: %06lu : ", osl_getGlobalTimer() );
+#else
+#if defined(OSL_TRACE_THREAD)
+ fprintf(
+ stderr, "Thread: %6lu :",
+ SAL_INT_CAST(unsigned long, osl_getThreadIdentifier(NULL)));
+#else
+ fprintf(stderr, "Trace Message: ");
+#endif
+#endif
+
+ va_start(args, lpszFormat);
+ vfprintf(stderr, lpszFormat, args);
+ va_end(args);
+
+ fprintf(stderr,"\n");
+ fflush(stderr);
+}
+
+/************************************************************************/
+
diff --git a/sal/osl/unx/file.cxx b/sal/osl/unx/file.cxx
new file mode 100644
index 000000000000..cc0c041bc328
--- /dev/null
+++ b/sal/osl/unx/file.cxx
@@ -0,0 +1,1397 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "osl/file.hxx"
+
+#include "osl/diagnose.h"
+#include "rtl/alloc.h"
+
+#include "system.h"
+#include "file_error_transl.h"
+#include "file_url.h"
+
+#include <algorithm>
+#include <limits>
+
+#include <string.h>
+#include <pthread.h>
+#include <sys/mman.h>
+
+#if defined(MACOSX)
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#define HAVE_O_EXLOCK
+
+// add MACOSX Time Value
+#define TimeValue CFTimeValue
+#include <CoreFoundation/CoreFoundation.h>
+#undef TimeValue
+
+#endif /* MACOSX */
+
+#ifdef DEBUG_OSL_FILE
+# define OSL_FILE_TRACE 0 ? (void)(0) : osl_trace
+# define PERROR( a, b ) perror( a ); fprintf( stderr, b )
+#else
+# define OSL_FILE_TRACE 1 ? (void)(0) : osl_trace
+# define PERROR( a, b )
+#endif
+
+/*******************************************************************
+ *
+ * FileHandle_Impl interface
+ *
+ ******************************************************************/
+struct FileHandle_Impl
+{
+ pthread_mutex_t m_mutex;
+ rtl_String * m_strFilePath; /* holds native file path */
+ int m_fd;
+
+ /** State
+ */
+ enum StateBits
+ {
+ STATE_SEEKABLE = 1, /* default */
+ STATE_READABLE = 2, /* default */
+ STATE_WRITEABLE = 4, /* open() sets, write() requires, else osl_File_E_BADF */
+ STATE_MODIFIED = 8 /* write() sets, flush() resets */
+ };
+ int m_state;
+
+ sal_uInt64 m_size; /* file size */
+ off_t m_offset; /* physical offset from begin of file */
+ off_t m_fileptr; /* logical offset from begin of file */
+
+ off_t m_bufptr; /* buffer offset from begin of file */
+ size_t m_buflen; /* buffer filled [0, m_bufsiz - 1] */
+
+ size_t m_bufsiz;
+ sal_uInt8 * m_buffer;
+
+ explicit FileHandle_Impl (int fd, char const * path = "<anon>");
+ ~FileHandle_Impl();
+
+ static void* operator new (size_t n);
+ static void operator delete (void * p, size_t);
+
+ static size_t getpagesize();
+
+ sal_uInt64 getPos() const;
+ oslFileError setPos (sal_uInt64 uPos);
+
+ sal_uInt64 getSize() const;
+ oslFileError setSize (sal_uInt64 uSize);
+
+ oslFileError readAt (
+ off_t nOffset,
+ void * pBuffer,
+ size_t nBytesRequested,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeAt (
+ off_t nOffset,
+ void const * pBuffer,
+ size_t nBytesToWrite,
+ sal_uInt64 * pBytesWritten);
+
+ oslFileError readFileAt (
+ off_t nOffset,
+ void * pBuffer,
+ size_t nBytesRequested,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeFileAt (
+ off_t nOffset,
+ void const * pBuffer,
+ size_t nBytesToWrite,
+ sal_uInt64 * pBytesWritten);
+
+ oslFileError readLineAt (
+ off_t nOffset,
+ sal_Sequence ** ppSequence,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeSequence_Impl (
+ sal_Sequence ** ppSequence,
+ size_t * pnOffset,
+ const void * pBuffer,
+ size_t nBytes);
+
+ oslFileError syncFile();
+
+ /** Buffer cache / allocator.
+ */
+ class Allocator
+ {
+ rtl_cache_type * m_cache;
+ size_t m_bufsiz;
+
+ Allocator (Allocator const &);
+ Allocator & operator= (Allocator const &);
+
+ public:
+ static Allocator & get();
+
+ void allocate (sal_uInt8 ** ppBuffer, size_t * pnSize);
+ void deallocate (sal_uInt8 * pBuffer);
+
+ protected:
+ Allocator();
+ ~Allocator();
+ };
+
+ /** Guard.
+ */
+ class Guard
+ {
+ pthread_mutex_t * m_mutex;
+
+ public:
+ explicit Guard(pthread_mutex_t * pMutex);
+ ~Guard();
+ };
+};
+
+/*******************************************************************
+ *
+ * FileHandle_Impl implementation
+ *
+ ******************************************************************/
+
+FileHandle_Impl::Allocator &
+FileHandle_Impl::Allocator::get()
+{
+ static Allocator g_aBufferAllocator;
+ return g_aBufferAllocator;
+}
+
+FileHandle_Impl::Allocator::Allocator()
+ : m_cache (0),
+ m_bufsiz (0)
+{
+ size_t const pagesize = FileHandle_Impl::getpagesize();
+ if (size_t(-1) != pagesize)
+ {
+ m_cache = rtl_cache_create (
+ "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0);
+ if (0 != m_cache)
+ m_bufsiz = pagesize;
+ }
+}
+FileHandle_Impl::Allocator::~Allocator()
+{
+ rtl_cache_destroy (m_cache), m_cache = 0;
+}
+
+void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, size_t * pnSize)
+{
+ OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation");
+ *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz;
+}
+void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
+{
+ if (0 != pBuffer)
+ rtl_cache_free (m_cache, pBuffer);
+}
+
+FileHandle_Impl::Guard::Guard(pthread_mutex_t * pMutex)
+ : m_mutex (pMutex)
+{
+ OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer.");
+ (void) pthread_mutex_lock (m_mutex); // ignoring EINVAL ...
+}
+FileHandle_Impl::Guard::~Guard()
+{
+ OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer.");
+ (void) pthread_mutex_unlock (m_mutex);
+}
+
+FileHandle_Impl::FileHandle_Impl (int fd, char const * path)
+ : m_strFilePath (0),
+ m_fd (fd),
+ m_state (STATE_SEEKABLE | STATE_READABLE),
+ m_size (0),
+ m_offset (0),
+ m_fileptr (0),
+ m_bufptr (-1),
+ m_buflen (0),
+ m_bufsiz (0),
+ m_buffer (0)
+{
+ (void) pthread_mutex_init(&m_mutex, 0);
+ rtl_string_newFromStr (&m_strFilePath, path);
+ Allocator::get().allocate (&m_buffer, &m_bufsiz);
+ if (0 != m_buffer)
+ memset (m_buffer, 0, m_bufsiz);
+}
+FileHandle_Impl::~FileHandle_Impl()
+{
+ Allocator::get().deallocate (m_buffer), m_buffer = 0;
+ rtl_string_release (m_strFilePath), m_strFilePath = 0;
+ (void) pthread_mutex_destroy(&m_mutex); // ignoring EBUSY ...
+}
+
+void* FileHandle_Impl::operator new (size_t n)
+{
+ return rtl_allocateMemory(n);
+}
+void FileHandle_Impl::operator delete (void * p, size_t)
+{
+ rtl_freeMemory(p);
+}
+
+size_t FileHandle_Impl::getpagesize()
+{
+#if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX)
+ return sal::static_int_cast< size_t >(::getpagesize());
+#else /* POSIX */
+ return sal::static_int_cast< size_t >(::sysconf(_SC_PAGESIZE));
+#endif /* xBSD || POSIX */
+}
+
+sal_uInt64 FileHandle_Impl::getPos() const
+{
+ return sal::static_int_cast< sal_uInt64 >(m_fileptr);
+}
+
+oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos)
+{
+ OSL_FILE_TRACE("FileHandle_Impl::setPos(%d, %lld) => %lld", m_fd, getPos(), uPos);
+ m_fileptr = sal::static_int_cast< off_t >(uPos);
+ return osl_File_E_None;
+}
+
+sal_uInt64 FileHandle_Impl::getSize() const
+{
+ off_t const bufend = std::max((off_t)(0), m_bufptr) + m_buflen;
+ return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend));
+}
+
+oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize)
+{
+ off_t const nSize = sal::static_int_cast< off_t >(uSize);
+ if (-1 == ftruncate (m_fd, nSize))
+ {
+ /* Failure. Save original result. Try fallback algorithm */
+ oslFileError result = oslTranslateFileError (OSL_FET_ERROR, errno);
+
+ /* Check against current size. Fail upon 'shrink' */
+ if (uSize <= getSize())
+ {
+ /* Failure upon 'shrink'. Return original result */
+ return (result);
+ }
+
+ /* Save current position */
+ off_t const nCurPos = (off_t)lseek (m_fd, (off_t)0, SEEK_CUR);
+ if (nCurPos == (off_t)(-1))
+ return (result);
+
+ /* Try 'expand' via 'lseek()' and 'write()' */
+ if (-1 == lseek (m_fd, (off_t)(nSize - 1), SEEK_SET))
+ return (result);
+
+ if (-1 == write (m_fd, (char*)"", (size_t)1))
+ {
+ /* Failure. Restore saved position */
+ (void) lseek (m_fd, (off_t)(nCurPos), SEEK_SET);
+ return (result);
+ }
+
+ /* Success. Restore saved position */
+ if (-1 == lseek (m_fd, (off_t)nCurPos, SEEK_SET))
+ return (result);
+ }
+
+ OSL_FILE_TRACE("osl_setFileSize(%d, %lld) => %ld", m_fd, getSize(), nSize);
+ m_size = sal::static_int_cast< sal_uInt64 >(nSize);
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::readAt (
+ off_t nOffset,
+ void * pBuffer,
+ size_t nBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::readAt(): not seekable");
+ if (!(m_state & STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ OSL_PRECOND((m_state & STATE_READABLE), "FileHandle_Impl::readAt(): not readable");
+ if (!(m_state & STATE_READABLE))
+ return osl_File_E_BADF;
+
+#if defined(LINUX) || defined(SOLARIS)
+
+ ssize_t nBytes = ::pread (m_fd, pBuffer, nBytesRequested, nOffset);
+ if ((-1 == nBytes) && (EOVERFLOW == errno))
+ {
+ /* Some 'pread()'s fail with EOVERFLOW when reading at (or past)
+ * end-of-file, different from 'lseek() + read()' behaviour.
+ * Returning '0 bytes read' and 'osl_File_E_None' instead.
+ */
+ nBytes = 0;
+ }
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+
+#else /* !(LINUX || SOLARIS) */
+
+ if (nOffset != m_offset)
+ {
+ if (-1 == ::lseek (m_fd, nOffset, SEEK_SET))
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ m_offset = nOffset;
+ }
+
+ ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ m_offset += nBytes;
+
+#endif /* !(LINUX || SOLARIS) */
+
+ OSL_FILE_TRACE("FileHandle_Impl::readAt(%d, %lld, %ld)", m_fd, nOffset, nBytes);
+ *pBytesRead = nBytes;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::writeAt (
+ off_t nOffset,
+ void const * pBuffer,
+ size_t nBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ OSL_PRECOND((m_state & STATE_SEEKABLE), "FileHandle_Impl::writeAt(): not seekable");
+ if (!(m_state & STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ OSL_PRECOND((m_state & STATE_WRITEABLE), "FileHandle_Impl::writeAt(): not writeable");
+ if (!(m_state & STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+#if defined(LINUX) || defined(SOLARIS)
+
+ ssize_t nBytes = ::pwrite (m_fd, pBuffer, nBytesToWrite, nOffset);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+
+#else /* !(LINUX || SOLARIS) */
+
+ if (nOffset != m_offset)
+ {
+ if (-1 == ::lseek (m_fd, nOffset, SEEK_SET))
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ m_offset = nOffset;
+ }
+
+ ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ m_offset += nBytes;
+
+#endif /* !(LINUX || SOLARIS) */
+
+ OSL_FILE_TRACE("FileHandle_Impl::writeAt(%d, %lld, %ld)", m_fd, nOffset, nBytes);
+ m_size = std::max (m_size, sal::static_int_cast< sal_uInt64 >(nOffset + nBytes));
+
+ *pBytesWritten = nBytes;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::readFileAt (
+ off_t nOffset,
+ void * pBuffer,
+ size_t nBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ if (0 == (m_state & STATE_SEEKABLE))
+ {
+ // not seekable (pipe)
+ ssize_t nBytes = ::read (m_fd, pBuffer, nBytesRequested);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ *pBytesRead = nBytes;
+ return osl_File_E_None;
+ }
+ else if (0 == m_buffer)
+ {
+ // not buffered
+ return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
+ }
+ else
+ {
+ sal_uInt8 * buffer = static_cast<sal_uInt8*>(pBuffer);
+ for (*pBytesRead = 0; nBytesRequested > 0; )
+ {
+ off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ size_t const bufpos = (nOffset % m_bufsiz);
+
+ if (bufptr != m_bufptr)
+ {
+ // flush current buffer
+ oslFileError result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = -1, m_buflen = 0;
+
+ if (nBytesRequested >= m_bufsiz)
+ {
+ // buffer too small, read through from file
+ sal_uInt64 uDone = 0;
+ result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+
+ nBytesRequested -= uDone, *pBytesRead += uDone;
+ return osl_File_E_None;
+ }
+
+ // update buffer (pointer)
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = uDone;
+ }
+ if (bufpos >= m_buflen)
+ {
+ // end of file
+ return osl_File_E_None;
+ }
+
+ size_t const bytes = std::min (m_buflen - bufpos, nBytesRequested);
+ OSL_FILE_TRACE("FileHandle_Impl::readFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes);
+
+ memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes);
+ nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes;
+ }
+ return osl_File_E_None;
+ }
+}
+
+oslFileError FileHandle_Impl::writeFileAt (
+ off_t nOffset,
+ void const * pBuffer,
+ size_t nBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ if (0 == (m_state & STATE_SEEKABLE))
+ {
+ // not seekable (pipe)
+ ssize_t nBytes = ::write (m_fd, pBuffer, nBytesToWrite);
+ if (-1 == nBytes)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+ *pBytesWritten = nBytes;
+ return osl_File_E_None;
+ }
+ else if (0 == m_buffer)
+ {
+ // not buffered
+ return writeAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
+ }
+ else
+ {
+ sal_uInt8 const * buffer = static_cast<sal_uInt8 const *>(pBuffer);
+ for (*pBytesWritten = 0; nBytesToWrite > 0; )
+ {
+ off_t const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ size_t const bufpos = (nOffset % m_bufsiz);
+ if (bufptr != m_bufptr)
+ {
+ // flush current buffer
+ oslFileError result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = -1, m_buflen = 0;
+
+ if (nBytesToWrite >= m_bufsiz)
+ {
+ // buffer to small, write through to file
+ sal_uInt64 uDone = 0;
+ result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ if (uDone != nBytesToWrite)
+ return osl_File_E_IO;
+
+ nBytesToWrite -= uDone, *pBytesWritten += uDone;
+ return osl_File_E_None;
+ }
+
+ // update buffer (pointer)
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = uDone;
+ }
+
+ size_t const bytes = std::min (m_bufsiz - bufpos, nBytesToWrite);
+ OSL_FILE_TRACE("FileHandle_Impl::writeFileAt(%d, %lld, %ld)", m_fd, nOffset, bytes);
+
+ memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes);
+ nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes;
+
+ m_buflen = std::max(m_buflen, bufpos + bytes);
+ m_state |= STATE_MODIFIED;
+ }
+ return osl_File_E_None;
+ }
+}
+
+oslFileError FileHandle_Impl::readLineAt (
+ off_t nOffset,
+ sal_Sequence ** ppSequence,
+ sal_uInt64 * pBytesRead)
+{
+ oslFileError result = osl_File_E_None;
+
+ off_t bufptr = nOffset / m_bufsiz * m_bufsiz;
+ if (bufptr != m_bufptr)
+ {
+ /* flush current buffer */
+ result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+
+ /* update buffer (pointer) */
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+
+ m_bufptr = bufptr, m_buflen = uDone;
+ }
+
+ static int const LINE_STATE_BEGIN = 0;
+ static int const LINE_STATE_CR = 1;
+ static int const LINE_STATE_LF = 2;
+
+ size_t bufpos = nOffset - m_bufptr, curpos = bufpos, dstpos = 0;
+ int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN;
+
+ for ( ; state != LINE_STATE_LF; )
+ {
+ if (curpos >= m_buflen)
+ {
+ /* buffer examined */
+ if (0 < (curpos - bufpos))
+ {
+ /* flush buffer to sequence */
+ result = writeSequence_Impl (
+ ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos);
+ if (result != osl_File_E_None)
+ return (result);
+ *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
+ }
+
+ bufptr = nOffset / m_bufsiz * m_bufsiz;
+ if (bufptr != m_bufptr)
+ {
+ /* update buffer (pointer) */
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = uDone;
+ }
+
+ bufpos = nOffset - m_bufptr, curpos = bufpos;
+ if (bufpos >= m_buflen)
+ break;
+ }
+ switch (state)
+ {
+ case LINE_STATE_CR:
+ state = LINE_STATE_LF;
+ switch (m_buffer[curpos])
+ {
+ case 0x0A: /* CRLF */
+ /* eat current char */
+ curpos++;
+ break;
+ default: /* single CR */
+ /* keep current char */
+ break;
+ }
+ break;
+ default:
+ /* determine next state */
+ switch (m_buffer[curpos])
+ {
+ case 0x0A: /* single LF */
+ state = LINE_STATE_LF;
+ break;
+ case 0x0D: /* CR */
+ state = LINE_STATE_CR;
+ break;
+ default: /* advance to next char */
+ curpos++;
+ break;
+ }
+ if (state != LINE_STATE_BEGIN)
+ {
+ /* store (and eat) the newline char */
+ m_buffer[curpos] = 0x0A, curpos++;
+
+ /* flush buffer to sequence */
+ result = writeSequence_Impl (
+ ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1);
+ if (result != osl_File_E_None)
+ return (result);
+ *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
+ }
+ break;
+ }
+ }
+
+ result = writeSequence_Impl (ppSequence, &dstpos, 0, 0);
+ if (result != osl_File_E_None)
+ return (result);
+ if (0 < dstpos)
+ return osl_File_E_None;
+ if (bufpos >= m_buflen)
+ return osl_File_E_AGAIN;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::writeSequence_Impl (
+ sal_Sequence ** ppSequence,
+ size_t * pnOffset,
+ const void * pBuffer,
+ size_t nBytes)
+{
+ sal_Int32 nElements = *pnOffset + nBytes;
+ if (!*ppSequence)
+ {
+ /* construct sequence */
+ rtl_byte_sequence_constructNoDefault(ppSequence, nElements);
+ }
+ else if (nElements != (*ppSequence)->nElements)
+ {
+ /* resize sequence */
+ rtl_byte_sequence_realloc(ppSequence, nElements);
+ }
+ if (*ppSequence != 0)
+ {
+ /* fill sequence */
+ memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes;
+ }
+ return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM;
+}
+
+oslFileError FileHandle_Impl::syncFile()
+{
+ oslFileError result = osl_File_E_None;
+ if (m_state & STATE_MODIFIED)
+ {
+ sal_uInt64 uDone = 0;
+ result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ if (uDone != m_buflen)
+ return osl_File_E_IO;
+ m_state &= ~STATE_MODIFIED;
+ }
+ return (result);
+}
+
+/****************************************************************************
+ * osl_createFileHandleFromFD
+ ***************************************************************************/
+extern "C" oslFileHandle osl_createFileHandleFromFD( int fd )
+{
+ if (-1 == fd)
+ return 0; // EINVAL
+
+ struct stat aFileStat;
+ if (-1 == fstat (fd, &aFileStat))
+ return 0; // EBADF
+
+ FileHandle_Impl * pImpl = new FileHandle_Impl (fd);
+ if (0 == pImpl)
+ return 0; // ENOMEM
+
+ // assume writeable
+ pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE;
+ if (!S_ISREG(aFileStat.st_mode))
+ {
+ /* not a regular file, mark not seekable */
+ pImpl->m_state &= ~FileHandle_Impl::STATE_SEEKABLE;
+ }
+ else
+ {
+ /* regular file, init current size */
+ pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size);
+ }
+
+ OSL_FILE_TRACE("osl_createFileHandleFromFD(%d, writeable) => %s",
+ pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath));
+ return (oslFileHandle)(pImpl);
+}
+
+/*******************************************************************
+ * osl_file_adjustLockFlags
+ ******************************************************************/
+static int osl_file_adjustLockFlags (const char * path, int flags)
+{
+#ifdef MACOSX
+ /*
+ * The AFP implementation of MacOS X 10.4 treats O_EXLOCK in a way
+ * that makes it impossible for OOo to create a backup copy of the
+ * file it keeps opened. OTOH O_SHLOCK for AFP behaves as desired by
+ * the OOo file handling, so we need to check the path of the file
+ * for the filesystem name.
+ */
+ struct statfs s;
+ if( 0 <= statfs( path, &s ) )
+ {
+ if( 0 == strncmp("afpfs", s.f_fstypename, 5) )
+ {
+ flags &= ~O_EXLOCK;
+ flags |= O_SHLOCK;
+ }
+ else
+ {
+ /* Needed flags to allow opening a webdav file */
+ flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK);
+ }
+ }
+#endif /* MACOSX */
+
+ (void) path;
+ return flags;
+}
+
+/****************************************************************************
+ * osl_file_queryLocking
+ ***************************************************************************/
+struct Locking_Impl
+{
+ int m_enabled;
+ Locking_Impl() : m_enabled(0)
+ {
+#ifndef HAVE_O_EXLOCK
+ m_enabled = ((getenv("SAL_ENABLE_FILE_LOCKING") != 0) || (getenv("STAR_ENABLE_FILE_LOCKING") != 0));
+#endif /* HAVE_O_EXLOCK */
+ }
+};
+static int osl_file_queryLocking (sal_uInt32 uFlags)
+{
+ if (!(uFlags & osl_File_OpenFlag_NoLock))
+ {
+ if ((uFlags & osl_File_OpenFlag_Write) || (uFlags & osl_File_OpenFlag_Create))
+ {
+ static Locking_Impl g_locking;
+ return (g_locking.m_enabled != 0);
+ }
+ }
+ return 0;
+}
+
+/****************************************************************************
+ * osl_openFile
+ ***************************************************************************/
+#ifdef HAVE_O_EXLOCK
+#define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK )
+#define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR | O_EXLOCK | O_NONBLOCK )
+#else
+#define OPEN_WRITE_FLAGS ( O_RDWR )
+#define OPEN_CREATE_FLAGS ( O_CREAT | O_EXCL | O_RDWR )
+#endif
+
+oslFileError
+SAL_CALL osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags )
+{
+ oslFileError eRet;
+
+ if ((ustrFileURL == 0) || (ustrFileURL->length == 0) || (pHandle == 0))
+ return osl_File_E_INVAL;
+
+ /* convert file URL to system path */
+ char buffer[PATH_MAX];
+ eRet = FileURLToPath (buffer, sizeof(buffer), ustrFileURL);
+ if (eRet != osl_File_E_None)
+ return eRet;
+#ifdef MACOSX
+ if (macxp_resolveAlias (buffer, sizeof(buffer)) != 0)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+#endif /* MACOSX */
+
+ /* set mode and flags */
+ int mode = S_IRUSR | S_IRGRP | S_IROTH;
+ int flags = O_RDONLY;
+ if (uFlags & osl_File_OpenFlag_Write)
+ {
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ flags = OPEN_WRITE_FLAGS;
+ }
+ if (uFlags & osl_File_OpenFlag_Create)
+ {
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ flags = OPEN_CREATE_FLAGS;
+ }
+ if (uFlags & osl_File_OpenFlag_NoLock)
+ {
+#ifdef HAVE_O_EXLOCK
+ flags &= ~(O_EXLOCK | O_SHLOCK | O_NONBLOCK);
+#endif /* HAVE_O_EXLOCK */
+ }
+ else
+ {
+ flags = osl_file_adjustLockFlags (buffer, flags);
+ }
+
+ /* open the file */
+ int fd = open( buffer, flags, mode );
+ if (-1 == fd)
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+
+ /* reset O_NONBLOCK flag */
+ if (flags & O_NONBLOCK)
+ {
+ int f = fcntl (fd, F_GETFL, 0);
+ if (-1 == f)
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ if (-1 == fcntl (fd, F_SETFL, (f & ~O_NONBLOCK)))
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ }
+
+ /* get file status (mode, size) */
+ struct stat aFileStat;
+ if (-1 == fstat (fd, &aFileStat))
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ if (!S_ISREG(aFileStat.st_mode))
+ {
+ /* we only open regular files here */
+ (void) close(fd);
+ return osl_File_E_INVAL;
+ }
+
+ if (osl_file_queryLocking (uFlags))
+ {
+#ifdef MACOSX
+ if (-1 == flock (fd, LOCK_EX | LOCK_NB))
+ {
+ /* Mac OSX returns ENOTSUP for webdav drives. We should try read lock */
+ if ((errno != ENOTSUP) || ((-1 == flock (fd, LOCK_SH | LOCK_NB)) && (errno != ENOTSUP)))
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ }
+#else /* F_SETLK */
+ {
+ struct flock aflock;
+
+ aflock.l_type = F_WRLCK;
+ aflock.l_whence = SEEK_SET;
+ aflock.l_start = 0;
+ aflock.l_len = 0;
+
+ if (-1 == fcntl (fd, F_SETLK, &aflock))
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, errno);
+ (void) close(fd);
+ return eRet;
+ }
+ }
+#endif /* F_SETLK */
+ }
+
+ /* allocate memory for impl structure */
+ FileHandle_Impl * pImpl = new FileHandle_Impl (fd, buffer);
+ if (!pImpl)
+ {
+ eRet = oslTranslateFileError (OSL_FET_ERROR, ENOMEM);
+ (void) close(fd);
+ return eRet;
+ }
+ if (flags & O_RDWR)
+ pImpl->m_state |= FileHandle_Impl::STATE_WRITEABLE;
+ pImpl->m_size = sal::static_int_cast< sal_uInt64 >(aFileStat.st_size);
+
+ OSL_TRACE("osl_openFile(%d, %s) => %s", pImpl->m_fd,
+ flags & O_RDWR ? "writeable":"readonly",
+ rtl_string_getStr(pImpl->m_strFilePath));
+
+ *pHandle = (oslFileHandle)(pImpl);
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_closeFile */
+/****************************************************************************/
+oslFileError
+SAL_CALL osl_closeFile( oslFileHandle Handle )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((pImpl == 0) || (pImpl->m_fd < 0))
+ return osl_File_E_INVAL;
+
+ (void) pthread_mutex_lock (&(pImpl->m_mutex));
+
+ /* close(2) implicitly (and unconditionally) unlocks */
+ OSL_TRACE("osl_closeFile(%d) => %s", pImpl->m_fd, rtl_string_getStr(pImpl->m_strFilePath));
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ {
+ /* close, ignoring double failure */
+ (void) close (pImpl->m_fd);
+ }
+ else if (-1 == close (pImpl->m_fd))
+ {
+ /* translate error code */
+ result = oslTranslateFileError (OSL_FET_ERROR, errno);
+ }
+
+ (void) pthread_mutex_unlock (&(pImpl->m_mutex));
+ delete pImpl;
+ return (result);
+}
+
+/************************************************
+ * osl_syncFile
+ ***********************************************/
+oslFileError
+SAL_CALL osl_syncFile(oslFileHandle Handle)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+
+ OSL_TRACE("osl_syncFile(%d)", pImpl->m_fd);
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ if (-1 == fsync (pImpl->m_fd))
+ return oslTranslateFileError (OSL_FET_ERROR, errno);
+
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_mapFile
+********************************************/
+oslFileError
+SAL_CALL osl_mapFile (
+ oslFileHandle Handle,
+ void** ppAddr,
+ sal_uInt64 uLength,
+ sal_uInt64 uOffset,
+ sal_uInt32 uFlags
+)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppAddr))
+ return osl_File_E_INVAL;
+ *ppAddr = 0;
+
+ static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max();
+ if (g_limit_size_t < uLength)
+ return osl_File_E_OVERFLOW;
+ size_t const nLength = sal::static_int_cast< size_t >(uLength);
+
+ static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uOffset)
+ return osl_File_E_OVERFLOW;
+ off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
+
+ void* p = mmap(NULL, nLength, PROT_READ, MAP_SHARED, pImpl->m_fd, nOffset);
+ if (MAP_FAILED == p)
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+ *ppAddr = p;
+
+ if (uFlags & osl_File_MapFlag_RandomAccess)
+ {
+ // Determine memory pagesize.
+ size_t const nPageSize = FileHandle_Impl::getpagesize();
+ if (size_t(-1) != nPageSize)
+ {
+ /*
+ * Pagein, touching first byte of every memory page.
+ * Note: volatile disables optimizing the loop away.
+ */
+ sal_uInt8 * pData (reinterpret_cast<sal_uInt8*>(*ppAddr));
+ size_t nSize (nLength);
+
+ volatile sal_uInt8 c = 0;
+ while (nSize > nPageSize)
+ {
+ c ^= pData[0];
+ pData += nPageSize;
+ nSize -= nPageSize;
+ }
+ if (nSize > 0)
+ {
+ c^= pData[0];
+ pData += nSize;
+ nSize -= nSize;
+ }
+ }
+ }
+ if (uFlags & osl_File_MapFlag_WillNeed)
+ {
+ // On Linux, madvise(..., MADV_WILLNEED) appears to have the undesirable
+ // effect of not returning until the data has actually been paged in, so
+ // that its net effect would typically be to slow down the process
+ // (which could start processing at the beginning of the data while the
+ // OS simultaneously pages in the rest); on other platforms, it remains
+ // to be evaluated whether madvise or equivalent is available and
+ // actually useful:
+#if defined MACOSX
+ int e = posix_madvise(p, nLength, POSIX_MADV_WILLNEED);
+ if (e != 0)
+ {
+ OSL_TRACE(
+ "posix_madvise(..., POSIX_MADV_WILLNEED) failed with %d", e);
+ }
+#elif defined SOLARIS
+ if (madvise(static_cast< caddr_t >(p), nLength, MADV_WILLNEED) != 0)
+ {
+ OSL_TRACE("madvise(..., MADV_WILLNEED) failed with %d", errno);
+ }
+#endif
+ }
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_unmapFile
+********************************************/
+oslFileError
+SAL_CALL osl_unmapFile (void* pAddr, sal_uInt64 uLength)
+{
+ if (0 == pAddr)
+ return osl_File_E_INVAL;
+
+ static sal_uInt64 const g_limit_size_t = std::numeric_limits< size_t >::max();
+ if (g_limit_size_t < uLength)
+ return osl_File_E_OVERFLOW;
+ size_t const nLength = sal::static_int_cast< size_t >(uLength);
+
+ if (-1 == munmap(static_cast<char*>(pAddr), nLength))
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_readLine
+********************************************/
+oslFileError
+SAL_CALL osl_readLine (
+ oslFileHandle Handle,
+ sal_Sequence ** ppSequence)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == ppSequence))
+ return osl_File_E_INVAL;
+ sal_uInt64 uBytesRead = 0;
+
+ // read at current fileptr; fileptr += uBytesRead;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->readLineAt (
+ pImpl->m_fileptr, ppSequence, &uBytesRead);
+ if (result == osl_File_E_None)
+ pImpl->m_fileptr += uBytesRead;
+ return (result);
+}
+
+/*******************************************
+ osl_readFile
+********************************************/
+oslFileError
+SAL_CALL osl_readFile (
+ oslFileHandle Handle,
+ void * pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead))
+ return osl_File_E_INVAL;
+
+ static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
+ if (g_limit_ssize_t < uBytesRequested)
+ return osl_File_E_OVERFLOW;
+ size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested);
+
+ // read at current fileptr; fileptr += *pBytesRead;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->readFileAt (
+ pImpl->m_fileptr, pBuffer, nBytesRequested, pBytesRead);
+ if (result == osl_File_E_None)
+ pImpl->m_fileptr += *pBytesRead;
+ return (result);
+}
+
+/*******************************************
+ osl_writeFile
+********************************************/
+oslFileError
+SAL_CALL osl_writeFile (
+ oslFileHandle Handle,
+ const void * pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
+ if (g_limit_ssize_t < uBytesToWrite)
+ return osl_File_E_OVERFLOW;
+ size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite);
+
+ // write at current fileptr; fileptr += *pBytesWritten;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->writeFileAt (
+ pImpl->m_fileptr, pBuffer, nBytesToWrite, pBytesWritten);
+ if (result == osl_File_E_None)
+ pImpl->m_fileptr += *pBytesWritten;
+ return (result);
+}
+
+/*******************************************
+ osl_readFileAt
+********************************************/
+oslFileError
+SAL_CALL osl_readFileAt (
+ oslFileHandle Handle,
+ sal_uInt64 uOffset,
+ void* pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64* pBytesRead)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesRead))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uOffset)
+ return osl_File_E_OVERFLOW;
+ off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
+
+ static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
+ if (g_limit_ssize_t < uBytesRequested)
+ return osl_File_E_OVERFLOW;
+ size_t const nBytesRequested = sal::static_int_cast< size_t >(uBytesRequested);
+
+ // read at specified fileptr
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ return pImpl->readFileAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
+}
+
+/*******************************************
+ osl_writeFileAt
+********************************************/
+oslFileError
+SAL_CALL osl_writeFileAt (
+ oslFileHandle Handle,
+ sal_uInt64 uOffset,
+ const void* pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64* pBytesWritten)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pBuffer) || (0 == pBytesWritten))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uOffset)
+ return osl_File_E_OVERFLOW;
+ off_t const nOffset = sal::static_int_cast< off_t >(uOffset);
+
+ static sal_uInt64 const g_limit_ssize_t = std::numeric_limits< ssize_t >::max();
+ if (g_limit_ssize_t < uBytesToWrite)
+ return osl_File_E_OVERFLOW;
+ size_t const nBytesToWrite = sal::static_int_cast< size_t >(uBytesToWrite);
+
+ // write at specified fileptr
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ return pImpl->writeFileAt (nOffset, pBuffer, nBytesToWrite, pBytesWritten);
+}
+
+/****************************************************************************/
+/* osl_isEndOfFile */
+/****************************************************************************/
+oslFileError
+SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pIsEOF))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pIsEOF = (pImpl->getPos() == pImpl->getSize());
+ return osl_File_E_None;
+}
+
+/************************************************
+ * osl_getFilePos
+ ***********************************************/
+oslFileError
+SAL_CALL osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pPos))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pPos = pImpl->getPos();
+ return osl_File_E_None;
+}
+
+/*******************************************
+ osl_setFilePos
+********************************************/
+oslFileError
+SAL_CALL osl_setFilePos (oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset)
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd))
+ return osl_File_E_INVAL;
+
+ static sal_Int64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uOffset)
+ return osl_File_E_OVERFLOW;
+ off_t nPos = 0, nOffset = sal::static_int_cast< off_t >(uOffset);
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ switch(uHow)
+ {
+ case osl_Pos_Absolut:
+ if (0 > nOffset)
+ return osl_File_E_INVAL;
+ break;
+
+ case osl_Pos_Current:
+ nPos = sal::static_int_cast< off_t >(pImpl->getPos());
+ if ((0 > nOffset) && (-1*nOffset > nPos))
+ return osl_File_E_INVAL;
+ if (g_limit_off_t < nPos + nOffset)
+ return osl_File_E_OVERFLOW;
+ break;
+
+ case osl_Pos_End:
+ nPos = sal::static_int_cast< off_t >(pImpl->getSize());
+ if ((0 > nOffset) && (-1*nOffset > nPos))
+ return osl_File_E_INVAL;
+ if (g_limit_off_t < nPos + nOffset)
+ return osl_File_E_OVERFLOW;
+ break;
+
+ default:
+ return osl_File_E_INVAL;
+ }
+
+ return pImpl->setPos (nPos + nOffset);
+}
+
+/****************************************************************************
+ * osl_getFileSize
+ ****************************************************************************/
+oslFileError
+SAL_CALL osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd) || (0 == pSize))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pSize = pImpl->getSize();
+ return osl_File_E_None;
+}
+
+/************************************************
+ * osl_setFileSize
+ ***********************************************/
+oslFileError
+SAL_CALL osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize )
+{
+ FileHandle_Impl* pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || (-1 == pImpl->m_fd))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ static sal_uInt64 const g_limit_off_t = std::numeric_limits< off_t >::max();
+ if (g_limit_off_t < uSize)
+ return osl_File_E_OVERFLOW;
+
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ pImpl->m_bufptr = -1, pImpl->m_buflen = 0;
+
+ return pImpl->setSize (uSize);
+}
diff --git a/sal/osl/unx/file_error_transl.cxx b/sal/osl/unx/file_error_transl.cxx
new file mode 100644
index 000000000000..3de829afc391
--- /dev/null
+++ b/sal/osl/unx/file_error_transl.cxx
@@ -0,0 +1,255 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+ #ifndef _ERRNO_H
+ #include <errno.h>
+ #endif
+
+ #ifndef _FILE_ERROR_TRANSL_H_
+ #include "file_error_transl.h"
+ #endif
+
+ #ifndef _OSL_DIAGNOSE_H_
+ #include <osl/diagnose.h>
+ #endif
+
+
+/********************************************
+ * oslTranslateFileError
+ *******************************************/
+
+oslFileError oslTranslateFileError(sal_Bool bIsError, int Errno)
+{
+ oslFileError osl_error = osl_File_E_invalidError;
+
+ OSL_ENSURE((bIsError && (0 != Errno)) || (!bIsError && (0 == Errno)), "oslTranslateFileError strange input combination!");
+
+ /* Have a look at file_error_transl.h for
+ the reason that we do this here */
+ if (bIsError && (0 == Errno))
+ return osl_error;
+
+ switch(Errno)
+ {
+ case 0:
+ osl_error = osl_File_E_None;
+ break;
+
+ case EPERM:
+ osl_error = osl_File_E_PERM;
+ break;
+
+ case ENOENT:
+ osl_error = osl_File_E_NOENT;
+ break;
+
+ case ESRCH:
+ osl_error = osl_File_E_SRCH;
+ break;
+
+ case EINTR:
+ osl_error = osl_File_E_INTR;
+ break;
+
+ case EIO:
+ osl_error = osl_File_E_IO;
+ break;
+
+ case ENXIO:
+ osl_error = osl_File_E_IO;
+ break;
+
+ case E2BIG:
+ osl_error = osl_File_E_2BIG;
+ break;
+
+ case ENOEXEC:
+ osl_error = osl_File_E_NOEXEC;
+ break;
+
+ case EBADF:
+ osl_error = osl_File_E_BADF;
+ break;
+
+ case ECHILD:
+ osl_error = osl_File_E_CHILD;
+ break;
+
+ case EAGAIN:
+ osl_error = osl_File_E_AGAIN;
+ break;
+
+ case ENOMEM:
+ osl_error = osl_File_E_NOMEM;
+ break;
+
+ case EACCES:
+ osl_error = osl_File_E_ACCES;
+ break;
+
+ case EFAULT:
+ osl_error = osl_File_E_FAULT;
+ break;
+
+ case EBUSY:
+ osl_error = osl_File_E_BUSY;
+ break;
+
+ case EEXIST:
+ osl_error = osl_File_E_EXIST;
+ break;
+
+ case EXDEV:
+ osl_error = osl_File_E_XDEV;
+ break;
+
+ case ENODEV:
+ osl_error = osl_File_E_NODEV;
+ break;
+
+ case ENOTDIR:
+ osl_error = osl_File_E_NOTDIR;
+ break;
+
+ case EISDIR:
+ osl_error = osl_File_E_ISDIR;
+ break;
+
+ case EINVAL:
+ osl_error = osl_File_E_INVAL;
+ break;
+
+ case ENFILE:
+ osl_error = osl_File_E_NFILE;
+ break;
+
+ case EMFILE:
+ osl_error = osl_File_E_MFILE;
+ break;
+
+ case ENOTTY:
+ osl_error = osl_File_E_NOTTY;
+ break;
+
+ case EFBIG:
+ osl_error = osl_File_E_FBIG;
+ break;
+
+ case ENOSPC:
+ osl_error = osl_File_E_NOSPC;
+ break;
+
+ case ESPIPE:
+ osl_error = osl_File_E_SPIPE;
+ break;
+
+ case EROFS:
+ osl_error = osl_File_E_ROFS;
+ break;
+
+ case EMLINK:
+ osl_error = osl_File_E_MLINK;
+ break;
+
+ case EPIPE:
+ osl_error = osl_File_E_PIPE;
+ break;
+
+ case EDOM:
+ osl_error = osl_File_E_DOM;
+ break;
+
+ case ERANGE:
+ osl_error = osl_File_E_RANGE;
+ break;
+
+ case EDEADLK:
+ osl_error = osl_File_E_DEADLK;
+ break;
+
+ case ENAMETOOLONG:
+ osl_error = osl_File_E_NAMETOOLONG;
+ break;
+
+ case ENOLCK:
+ osl_error = osl_File_E_NOLCK;
+ break;
+
+ case ENOSYS:
+ osl_error = osl_File_E_NOSYS;
+ break;
+
+ case ENOTEMPTY:
+ osl_error = osl_File_E_NOTEMPTY;
+ break;
+
+ case ELOOP:
+ osl_error = osl_File_E_LOOP;
+ break;
+
+#if !(defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+ case EILSEQ:
+ osl_error = osl_File_E_ILSEQ;
+ break;
+#endif /* MACOSX */
+
+#if !(defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+ case ENOLINK:
+ osl_error = osl_File_E_NOLINK;
+ break;
+#endif /* MACOSX */
+
+#if !(defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+ case EMULTIHOP:
+ osl_error = osl_File_E_MULTIHOP;
+ break;
+#endif /* MACOSX */
+
+ case EUSERS:
+ osl_error = osl_File_E_USERS;
+ break;
+
+ case EOVERFLOW:
+ osl_error = osl_File_E_OVERFLOW;
+ break;
+
+ case ETIMEDOUT:
+ osl_error = osl_File_E_TIMEDOUT;
+ break;
+
+ default:
+ /* FIXME translateFileError: is this alright? Or add a new one: osl_File_E_Unknown? */
+ osl_error = osl_File_E_invalidError;
+ break;
+ }
+
+ return osl_error;
+}
+
diff --git a/sal/osl/unx/file_error_transl.h b/sal/osl/unx/file_error_transl.h
new file mode 100644
index 000000000000..59d7b1d9faec
--- /dev/null
+++ b/sal/osl/unx/file_error_transl.h
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _FILE_ERROR_TRANSL_H_
+#define _FILE_ERROR_TRANSL_H_
+
+#include <osl/file.h>
+#include <sal/types.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*********************************************
+ oslTranslateFileError
+ Translate errno's to osl file errors
+
+ @param bIsError [in] specifies if nErrno
+ should be interpreted as error,
+ some libc functions signaling an error
+ but errno is nevertheless 0 in this
+ case the function should at least
+ return osl_File_E_Unknown but in no
+ case osl_File_E_None!
+
+ @param nErrno [in] the errno if errno is 0
+ and bIsError is true the function
+ returns osl_File_E_Unknown
+
+ @returns the osl error code appropriate to
+ the errno
+
+ *********************************************/
+
+#define OSL_FET_SUCCESS sal_False
+#define OSL_FET_ERROR sal_True
+
+oslFileError oslTranslateFileError(sal_Bool bIsError, int Errno);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sal/osl/unx/file_impl.hxx b/sal/osl/unx/file_impl.hxx
new file mode 100644
index 000000000000..5dee69f29b2e
--- /dev/null
+++ b/sal/osl/unx/file_impl.hxx
@@ -0,0 +1,54 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_FILE_IMPL_HXX
+#define INCLUDED_FILE_IMPL_HXX
+
+#include "osl/file.h"
+#include <stddef.h>
+
+struct DirectoryItem_Impl
+{
+ sal_Int32 m_RefCount;
+
+ rtl_uString * m_ustrFilePath; /* holds native file name */
+ unsigned char m_DType;
+
+ explicit DirectoryItem_Impl(
+ rtl_uString * ustrFilePath, unsigned char DType = 0);
+ ~DirectoryItem_Impl();
+
+ static void * operator new(size_t n);
+ static void operator delete (void * p, size_t);
+
+ void acquire(); /* @see osl_acquireDirectoryItem() */
+ void release(); /* @see osl_releaseDirectoryItem() */
+
+ oslFileType getFileType() const;
+};
+
+#endif /* INCLUDED_FILE_IMPL_HXX */
diff --git a/sal/osl/unx/file_misc.cxx b/sal/osl/unx/file_misc.cxx
new file mode 100644
index 000000000000..331b91cb1626
--- /dev/null
+++ b/sal/osl/unx/file_misc.cxx
@@ -0,0 +1,1101 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "osl/file.hxx"
+
+#include "osl/diagnose.h"
+#include "osl/thread.h"
+#include <osl/signal.h>
+#include "rtl/alloc.h"
+
+#include "system.h"
+#include "file_impl.hxx"
+#include "file_error_transl.h"
+#include "file_path_helper.hxx"
+#include "file_url.h"
+#include "uunxapi.hxx"
+
+#include <sys/types.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <algorithm>
+
+/************************************************************************
+ * ToDo
+ *
+ * - Fix: check for corresponding struct sizes in exported functions
+ * - check size/use of oslDirectory
+ * - check size/use of oslDirectoryItem
+ ***********************************************************************/
+/******************************************************************************
+ *
+ * Data Type Definition
+ *
+ ******************************************************************************/
+
+typedef struct
+{
+ rtl_uString* ustrPath; /* holds native directory path */
+ DIR* pDirStruct;
+} oslDirectoryImpl;
+
+#if 0
+/* FIXME: reintroducing this may save some extra bytes per Item */
+typedef struct
+{
+ rtl_uString* ustrFileName; /* holds native file name */
+ rtl_uString* ustrDirPath; /* holds native dir path */
+ sal_uInt32 RefCount;
+} oslDirectoryItemImpl;
+#endif
+
+DirectoryItem_Impl::DirectoryItem_Impl(
+ rtl_uString * ustrFilePath, unsigned char DType)
+ : m_RefCount (1),
+ m_ustrFilePath (ustrFilePath),
+ m_DType (DType)
+{
+ if (m_ustrFilePath != 0)
+ rtl_uString_acquire(m_ustrFilePath);
+}
+DirectoryItem_Impl::~DirectoryItem_Impl()
+{
+ if (m_ustrFilePath != 0)
+ rtl_uString_release(m_ustrFilePath);
+}
+
+void * DirectoryItem_Impl::operator new(size_t n)
+{
+ return rtl_allocateMemory(n);
+}
+void DirectoryItem_Impl::operator delete(void * p, size_t)
+{
+ rtl_freeMemory(p);
+}
+
+void DirectoryItem_Impl::acquire()
+{
+ ++m_RefCount;
+}
+void DirectoryItem_Impl::release()
+{
+ if (0 == --m_RefCount)
+ delete this;
+}
+
+oslFileType DirectoryItem_Impl::getFileType() const
+{
+ switch (m_DType)
+ {
+#ifdef _DIRENT_HAVE_D_TYPE
+ case DT_LNK:
+ return osl_File_Type_Link;
+ case DT_DIR:
+ return osl_File_Type_Directory;
+ case DT_REG:
+ return osl_File_Type_Regular;
+ case DT_FIFO:
+ return osl_File_Type_Fifo;
+ case DT_SOCK:
+ return osl_File_Type_Socket;
+ case DT_CHR:
+ case DT_BLK:
+ return osl_File_Type_Special;
+#endif /* _DIRENT_HAVE_D_TYPE */
+ default:
+ break;
+ }
+ return osl_File_Type_Unknown;
+}
+
+/******************************************************************************
+ *
+ * C-String Function Declarations
+ *
+ *****************************************************************************/
+
+static oslFileError osl_psz_createDirectory(const sal_Char* pszPath);
+static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath);
+
+/*******************************************************************
+ * osl_openDirectory
+ ******************************************************************/
+
+oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory)
+{
+ rtl_uString* ustrSystemPath = NULL;
+ oslFileError eRet;
+
+ char path[PATH_MAX];
+
+ if ((0 == ustrDirectoryURL) || (0 == ustrDirectoryURL->length) || (0 == pDirectory))
+ return osl_File_E_INVAL;
+
+ /* convert file URL to system path */
+ eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False);
+
+ if( osl_File_E_None != eRet )
+ return eRet;
+
+ osl_systemPathRemoveSeparator(ustrSystemPath);
+
+ /* convert unicode path to text */
+ if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length )
+#ifdef MACOSX
+ && macxp_resolveAlias( path, PATH_MAX ) == 0
+#endif /* MACOSX */
+ )
+ {
+ /* open directory */
+ DIR *pdir = opendir( path );
+
+ if( pdir )
+ {
+ /* create and initialize impl structure */
+ oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
+
+ if( pDirImpl )
+ {
+ pDirImpl->pDirStruct = pdir;
+ pDirImpl->ustrPath = ustrSystemPath;
+
+ *pDirectory = (oslDirectory) pDirImpl;
+ return osl_File_E_None;
+ }
+ else
+ {
+ errno = ENOMEM;
+ closedir( pdir );
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_FILE
+ perror ("osl_openDirectory"); fprintf (stderr, path);
+#endif
+ }
+ }
+
+ rtl_uString_release( ustrSystemPath );
+
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+}
+
+/****************************************************************************/
+/* osl_closeDirectory */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
+{
+ oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) Directory;
+ oslFileError err = osl_File_E_None;
+
+ OSL_ASSERT( Directory );
+
+ if( NULL == pDirImpl )
+ return osl_File_E_INVAL;
+
+ /* close directory */
+ if( closedir( pDirImpl->pDirStruct ) )
+ {
+ err = oslTranslateFileError(OSL_FET_ERROR, errno);
+ }
+
+ /* cleanup members */
+ rtl_uString_release( pDirImpl->ustrPath );
+
+ rtl_freeMemory( pDirImpl );
+
+ return err;
+}
+
+/**********************************************
+ * osl_readdir_impl_
+ *
+ * readdir wrapper, filters out "." and ".."
+ * on request
+ *********************************************/
+
+static struct dirent* osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir)
+{
+ struct dirent* pdirent;
+
+ while ((pdirent = readdir(pdir)) != NULL)
+ {
+ if (bFilterLocalAndParentDir &&
+ ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
+ continue;
+ else
+ break;
+ }
+
+ return pdirent;
+}
+
+/****************************************************************************
+ * osl_getNextDirectoryItem
+ ***************************************************************************/
+
+oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 /*uHint*/)
+{
+ oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*)Directory;
+ rtl_uString* ustrFileName = NULL;
+ rtl_uString* ustrFilePath = NULL;
+ struct dirent* pEntry;
+
+ OSL_ASSERT(Directory);
+ OSL_ASSERT(pItem);
+
+ if ((NULL == Directory) || (NULL == pItem))
+ return osl_File_E_INVAL;
+
+ pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
+
+ if (NULL == pEntry)
+ return osl_File_E_NOENT;
+
+
+#if defined(MACOSX)
+
+ // convert decomposed filename to precomposed unicode
+ char composed_name[BUFSIZ];
+ CFMutableStringRef strRef = CFStringCreateMutable (NULL, 0 );
+ CFStringAppendCString( strRef, pEntry->d_name, kCFStringEncodingUTF8 ); //UTF8 is default on Mac OSX
+ CFStringNormalize( strRef, kCFStringNormalizationFormC );
+ CFStringGetCString( strRef, composed_name, BUFSIZ, kCFStringEncodingUTF8 );
+ CFRelease( strRef );
+ rtl_string2UString( &ustrFileName, composed_name, strlen( composed_name),
+ osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+
+#else // not MACOSX
+ /* convert file name to unicode */
+ rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
+ osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(ustrFileName != 0);
+
+#endif
+
+ osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &ustrFilePath);
+ rtl_uString_release( ustrFileName );
+
+ DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(*pItem);
+ if (0 != pImpl)
+ {
+ pImpl->release(), pImpl = 0;
+ }
+#ifdef _DIRENT_HAVE_D_TYPE
+ pImpl = new DirectoryItem_Impl(ustrFilePath, pEntry->d_type);
+#else
+ pImpl = new DirectoryItem_Impl(ustrFilePath);
+#endif /* _DIRENT_HAVE_D_TYPE */
+ *pItem = pImpl;
+ rtl_uString_release( ustrFilePath );
+
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_getDirectoryItem */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
+{
+ rtl_uString* ustrSystemPath = NULL;
+ oslFileError osl_error = osl_File_E_INVAL;
+
+ OSL_ASSERT(ustrFileURL);
+ OSL_ASSERT(pItem);
+
+ if (0 == ustrFileURL->length || NULL == pItem)
+ return osl_File_E_INVAL;
+
+ osl_error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &ustrSystemPath, sal_False);
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+
+ osl_systemPathRemoveSeparator(ustrSystemPath);
+
+ if (-1 == access_u(ustrSystemPath, F_OK))
+ {
+ osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
+ }
+ else
+ {
+ *pItem = new DirectoryItem_Impl(ustrSystemPath);
+ }
+ rtl_uString_release(ustrSystemPath);
+
+ return osl_error;
+}
+
+
+/****************************************************************************/
+/* osl_acquireDirectoryItem */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
+{
+ DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
+ if (0 == pImpl)
+ return osl_File_E_INVAL;
+
+ pImpl->acquire();
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_releaseDirectoryItem */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
+{
+ DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
+ if (0 == pImpl)
+ return osl_File_E_INVAL;
+
+ pImpl->release();
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_createDirectory */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_createDirectory( rtl_uString* ustrDirectoryURL )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+
+ OSL_ASSERT( ustrDirectoryURL );
+
+ /* convert directory url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+#ifdef MACOSX
+ if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
+ return oslTranslateFileError( OSL_FET_ERROR, errno );
+#endif/* MACOSX */
+
+ return osl_psz_createDirectory( path );
+}
+
+/****************************************************************************/
+/* osl_removeDirectory */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+
+ OSL_ASSERT( ustrDirectoryURL );
+
+ /* convert directory url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+#ifdef MACOSX
+ if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
+ return oslTranslateFileError( OSL_FET_ERROR, errno );
+#endif/* MACOSX */
+
+ return osl_psz_removeDirectory( path );
+}
+
+/*****************************************
+ * osl_psz_createDirectory
+ ****************************************/
+
+static oslFileError osl_psz_createDirectory( const sal_Char* pszPath )
+{
+ int nRet=0;
+ int mode = S_IRWXU | S_IRWXG | S_IRWXO;
+
+ nRet = mkdir(pszPath,mode);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_psz_removeDirectory
+ ****************************************/
+
+static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
+{
+ int nRet=0;
+
+ nRet = rmdir(pszPath);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_createDirectoryPath */
+/****************************************************************************/
+
+static int path_make_parent(sal_Unicode* path)
+{
+ int i = rtl_ustr_lastIndexOfChar(path, '/');
+
+ if (i > 0)
+ {
+ *(path + i) = 0;
+ return i;
+ }
+ else
+ return 0;
+}
+
+static int create_dir_with_callback(
+ sal_Unicode* directory_path,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ int mode = S_IRWXU | S_IRWXG | S_IRWXO;
+
+ if (osl::mkdir(directory_path, mode) == 0)
+ {
+ if (aDirectoryCreationCallbackFunc)
+ {
+ rtl::OUString url;
+ osl::FileBase::getFileURLFromSystemPath(directory_path, url);
+ aDirectoryCreationCallbackFunc(pData, url.pData);
+ }
+ return 0;
+ }
+ return errno;
+}
+
+static oslFileError create_dir_recursively_(
+ sal_Unicode* dir_path,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
+ "Path must not end with a slash");
+
+ int native_err = create_dir_with_callback(
+ dir_path, aDirectoryCreationCallbackFunc, pData);
+
+ if (native_err == 0)
+ return osl_File_E_None;
+
+ if (native_err != ENOENT)
+ return oslTranslateFileError(OSL_FET_ERROR, native_err);
+
+ // we step back until '/a_dir' at maximum because
+ // we should get an error unequal ENOENT when
+ // we try to create 'a_dir' at '/' and would so
+ // return before
+ int pos = path_make_parent(dir_path);
+
+ oslFileError osl_error = create_dir_recursively_(
+ dir_path, aDirectoryCreationCallbackFunc, pData);
+
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+
+ dir_path[pos] = '/';
+
+ return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
+}
+
+oslFileError SAL_CALL osl_createDirectoryPath(
+ rtl_uString* aDirectoryUrl,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ if (aDirectoryUrl == NULL)
+ return osl_File_E_INVAL;
+
+ rtl::OUString sys_path;
+ oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
+ aDirectoryUrl, &sys_path.pData, sal_False);
+
+ if (osl_error != osl_File_E_None)
+ return osl_error;
+
+ osl::systemPathRemoveSeparator(sys_path);
+
+ // const_cast because sys_path is a local copy which we want to modify inplace instead of
+ // coyp it into another buffer on the heap again
+ return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
+}
+
+/******************************************************************************
+ *
+ * C-String Function Declarations
+ *
+ *****************************************************************************/
+
+static oslFileError osl_psz_removeFile(const sal_Char* pszPath);
+static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
+static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
+
+
+/******************************************************************************
+ *
+ * Static Module Utility Function Declarations
+ *
+ *****************************************************************************/
+
+static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists);
+static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID);
+static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName);
+static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode);
+static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
+
+/****************************************************************************/
+/* osl_moveFile */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
+{
+ char srcPath[PATH_MAX];
+ char destPath[PATH_MAX];
+ oslFileError eRet;
+
+ OSL_ASSERT( ustrFileURL );
+ OSL_ASSERT( ustrDestURL );
+
+ /* convert source url to system path */
+ eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ /* convert destination url to system path */
+ eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+#ifdef MACOSX
+ if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
+ return oslTranslateFileError( OSL_FET_ERROR, errno );
+#endif/* MACOSX */
+
+ return oslDoMoveFile( srcPath, destPath );
+}
+
+/****************************************************************************/
+/* osl_copyFile */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
+{
+ char srcPath[PATH_MAX];
+ char destPath[PATH_MAX];
+ oslFileError eRet;
+
+ OSL_ASSERT( ustrFileURL );
+ OSL_ASSERT( ustrDestURL );
+
+ /* convert source url to system path */
+ eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+ /* convert destination url to system path */
+ eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+#ifdef MACOSX
+ if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
+ return oslTranslateFileError( OSL_FET_ERROR, errno );
+#endif/* MACOSX */
+
+ return osl_psz_copyFile( srcPath, destPath );
+}
+
+/****************************************************************************/
+/* osl_removeFile */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_removeFile( rtl_uString* ustrFileURL )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+
+ OSL_ASSERT( ustrFileURL );
+
+ /* convert file url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+#ifdef MACOSX
+ if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
+ return oslTranslateFileError( OSL_FET_ERROR, errno );
+#endif/* MACOSX */
+
+ return osl_psz_removeFile( path );
+}
+
+/******************************************************************************
+ *
+ * Utility Functions
+ *
+ *****************************************************************************/
+
+/*****************************************
+ * oslDoMoveFile
+ ****************************************/
+
+static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
+{
+ oslFileError tErr=osl_File_E_invalidError;
+
+ tErr = osl_psz_moveFile(pszPath,pszDestPath);
+ if ( tErr == osl_File_E_None )
+ {
+ return tErr;
+ }
+
+ if ( tErr != osl_File_E_XDEV )
+ {
+ return tErr;
+ }
+
+ tErr=osl_psz_copyFile(pszPath,pszDestPath);
+
+ if ( tErr != osl_File_E_None )
+ {
+ oslFileError tErrRemove;
+ tErrRemove=osl_psz_removeFile(pszDestPath);
+ return tErr;
+ }
+
+ tErr=osl_psz_removeFile(pszPath);
+
+ return tErr;
+}
+
+/*****************************************
+ * osl_psz_removeFile
+ ****************************************/
+static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
+{
+ int nRet=0;
+ struct stat aStat;
+
+ nRet = lstat(pszPath,&aStat);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ if ( S_ISDIR(aStat.st_mode) )
+ {
+ return osl_File_E_ISDIR;
+ }
+
+ nRet = unlink(pszPath);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_psz_moveFile
+ ****************************************/
+
+static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
+{
+
+ int nRet = 0;
+
+ nRet = rename(pszPath,pszDestPath);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_psz_copyFile
+ ****************************************/
+
+static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
+{
+ time_t nAcTime=0;
+ time_t nModTime=0;
+ uid_t nUID=0;
+ gid_t nGID=0;
+ int nRet=0;
+ mode_t nMode=0;
+ struct stat aFileStat;
+ oslFileError tErr=osl_File_E_invalidError;
+ size_t nSourceSize=0;
+ int DestFileExists=1;
+
+ /* mfe: does the source file really exists? */
+ nRet = lstat(pszPath,&aFileStat);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ /* mfe: we do only copy files here! */
+ if ( S_ISDIR(aFileStat.st_mode) )
+ {
+ return osl_File_E_ISDIR;
+ }
+
+ nSourceSize=(size_t)aFileStat.st_size;
+ nMode=aFileStat.st_mode;
+ nAcTime=aFileStat.st_atime;
+ nModTime=aFileStat.st_mtime;
+ nUID=aFileStat.st_uid;
+ nGID=aFileStat.st_gid;
+
+ nRet = stat(pszDestPath,&aFileStat);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+
+ if ( nRet == ENOENT )
+ {
+ DestFileExists=0;
+ }
+/* return oslTranslateFileError(nRet);*/
+ }
+
+ /* mfe: the destination file must not be a directory! */
+ if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
+ {
+ return osl_File_E_ISDIR;
+ }
+ else
+ {
+ /* mfe: file does not exists or is no dir */
+ }
+
+ tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
+
+ if ( tErr != osl_File_E_None )
+ {
+ return tErr;
+ }
+
+ /*
+ * mfe: ignore return code
+ * since only the success of the copy is
+ * important
+ */
+ oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
+
+ return tErr;
+}
+
+
+/******************************************************************************
+ *
+ * Utility Functions
+ *
+ *****************************************************************************/
+
+/*****************************************
+ * oslDoCopy
+ ****************************************/
+
+#define TMP_DEST_FILE_EXTENSION ".osl-tmp"
+
+static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
+{
+ int nRet=0;
+ sal_Char pszTmpDestFile[PATH_MAX];
+ size_t size_tmp_dest_buff = sizeof(pszTmpDestFile);
+
+ /* Quick fix for #106048, the whole copy file function seems
+ to be erroneous anyway and needs to be rewritten.
+ Besides osl_copyFile is currently not used from OO/SO code.
+ */
+ memset(pszTmpDestFile, 0, size_tmp_dest_buff);
+
+ if ( DestFileExists )
+ {
+ strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1);
+
+ if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff)
+ return osl_File_E_NAMETOOLONG;
+
+ strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION));
+
+ /* FIXME: what if pszTmpDestFile already exists? */
+ /* with getcanonical??? */
+ nRet=rename(pszDestFileName,pszTmpDestFile);
+ }
+
+ /* mfe: should be S_ISREG */
+ if ( !S_ISLNK(nMode) )
+ {
+ /* copy SourceFile to DestFile */
+ nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
+ }
+ /* mfe: OK redundant at the moment */
+ else if ( S_ISLNK(nMode) )
+ {
+ nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
+ }
+ else
+ {
+ /* mfe: what to do here? */
+ nRet=ENOSYS;
+ }
+
+ if ( nRet > 0 && DestFileExists == 1 )
+ {
+ unlink(pszDestFileName);
+ rename(pszTmpDestFile,pszDestFileName);
+ }
+
+ if ( nRet > 0 )
+ {
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ if ( DestFileExists == 1 )
+ {
+ unlink(pszTmpDestFile);
+ }
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * oslChangeFileModes
+ ****************************************/
+
+static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
+{
+ int nRet=0;
+ struct utimbuf aTimeBuffer;
+
+ nRet = chmod(pszFileName,nMode);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ aTimeBuffer.actime=nAcTime;
+ aTimeBuffer.modtime=nModTime;
+ nRet=utime(pszFileName,&aTimeBuffer);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ if ( nUID != getuid() )
+ {
+ nUID=getuid();
+ }
+
+ nRet=chown(pszFileName,nUID,nGID);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+
+ /* mfe: do not return an error here! */
+ /* return oslTranslateFileError(nRet);*/
+ }
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * oslDoCopyLink
+ ****************************************/
+
+static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
+{
+ int nRet=0;
+
+ /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
+ /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
+ sal_Char pszLinkContent[PATH_MAX];
+
+ pszLinkContent[0] = '\0';
+
+ nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return nRet;
+ }
+ else
+ pszLinkContent[ nRet ] = 0;
+
+ nRet = symlink(pszLinkContent,pszDestFileName);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return nRet;
+ }
+
+ return 0;
+}
+
+/*****************************************
+ * oslDoCopyFile
+ ****************************************/
+
+static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
+{
+ int SourceFileFD=0;
+ int DestFileFD=0;
+ int nRet=0;
+
+ SourceFileFD=open(pszSourceFileName,O_RDONLY);
+ if ( SourceFileFD < 0 )
+ {
+ nRet=errno;
+ return nRet;
+ }
+
+ DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT, mode);
+
+ if ( DestFileFD < 0 )
+ {
+ nRet=errno;
+ close(SourceFileFD);
+ return nRet;
+ }
+
+ /* HACK: because memory mapping fails on various
+ platforms if the size of the source file is 0 byte */
+ if (0 == nSourceSize)
+ {
+ close(SourceFileFD);
+ close(DestFileFD);
+ return 0;
+ }
+
+ // read and lseek are used to check the possibility to access the data
+ // not a nice solution, but it allows to avoid a crash in case it is an opened samba file
+ // generally, reading of one byte should not affect the performance
+ char nCh;
+ if ( 1 != read( SourceFileFD, &nCh, 1 )
+ || -1 == lseek( SourceFileFD, 0, SEEK_SET ) )
+ {
+ nRet = errno;
+ close( SourceFileFD );
+ close( DestFileFD );
+ return nRet;
+ }
+
+ size_t nWritten = 0;
+ size_t nRemains = nSourceSize;
+
+ /* mmap file -- open dest file -- write -- fsync it at the end */
+ void* pSourceFile = mmap( 0, nSourceSize, PROT_READ, MAP_SHARED, SourceFileFD, 0 );
+ if ( pSourceFile != MAP_FAILED )
+ {
+ nWritten = write( DestFileFD, pSourceFile, nSourceSize );
+ nRemains -= nWritten;
+ munmap( (char*)pSourceFile, nSourceSize );
+ }
+
+ if ( nRemains )
+ {
+ /* mmap has problems, try the direct streaming */
+ char pBuffer[32000];
+ size_t nRead = 0;
+
+ nRemains = nSourceSize;
+
+ if ( -1 != lseek( SourceFileFD, 0, SEEK_SET )
+ && -1 != lseek( DestFileFD, 0, SEEK_SET ) )
+ {
+ do
+ {
+ nRead = 0;
+ nWritten = 0;
+
+ size_t nToRead = std::min( (size_t)32000, nRemains );
+ nRead = read( SourceFileFD, pBuffer, nToRead );
+ if ( (size_t)-1 != nRead )
+ nWritten = write( DestFileFD, pBuffer, nRead );
+
+ if ( (size_t)-1 != nWritten )
+ nRemains -= nWritten;
+ }
+ while( nRemains && (size_t)-1 != nRead && nRead == nWritten );
+ }
+ }
+
+ if ( nRemains )
+ {
+ if ( errno )
+ nRet = errno;
+ else
+ nRet = ENOSPC;
+ }
+
+ close( SourceFileFD );
+ if ( close( DestFileFD ) == -1 && nRet == 0 )
+ nRet = errno;
+
+ return nRet;
+}
+
diff --git a/sal/osl/unx/file_path_helper.cxx b/sal/osl/unx/file_path_helper.cxx
new file mode 100644
index 000000000000..04fdd13e7c15
--- /dev/null
+++ b/sal/osl/unx/file_path_helper.cxx
@@ -0,0 +1,350 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+ /*******************************************
+ Includes
+ ******************************************/
+
+ #ifndef _OSL_FILE_PATH_HELPER_H_
+ #include "file_path_helper.h"
+ #endif
+
+ #ifndef _OSL_FILE_PATH_HELPER_HXX_
+ #include "file_path_helper.hxx"
+ #endif
+
+ #ifndef _OSL_UUNXAPI_HXX_
+ #include "uunxapi.hxx"
+ #endif
+
+ #ifndef _OSL_DIAGNOSE_H_
+ #include <osl/diagnose.h>
+ #endif
+
+ #ifndef _RTL_USTRING_HXX_
+ #include <rtl/ustring.hxx>
+ #endif
+
+ /*******************************************
+ Constants
+ ******************************************/
+
+ const sal_Unicode FPH_CHAR_PATH_SEPARATOR = (sal_Unicode)'/';
+ const sal_Unicode FPH_CHAR_DOT = (sal_Unicode)'.';
+ const sal_Unicode FPH_CHAR_COLON = (sal_Unicode)':';
+
+ inline const rtl::OUString FPH_PATH_SEPARATOR()
+ { return rtl::OUString::createFromAscii("/"); }
+ inline const rtl::OUString FPH_LOCAL_DIR_ENTRY()
+ { return rtl::OUString::createFromAscii("."); }
+ inline const rtl::OUString FPH_PARENT_DIR_ENTRY()
+ { return rtl::OUString::createFromAscii(".."); }
+
+ /*******************************************
+ * osl_systemPathRemoveSeparator
+ ******************************************/
+
+ void SAL_CALL osl_systemPathRemoveSeparator(rtl_uString* pustrPath)
+ {
+ OSL_PRECOND(pustrPath, "osl_systemPathRemoveSeparator: Invalid parameter");
+
+ // maybe there are more than one separator at end
+ // so we run in a loop
+ while ((pustrPath->length > 1) && (FPH_CHAR_PATH_SEPARATOR == pustrPath->buffer[pustrPath->length - 1]))
+ {
+ pustrPath->length--;
+ pustrPath->buffer[pustrPath->length] = (sal_Unicode)'\0';
+ }
+
+ OSL_POSTCOND((0 == pustrPath->length) || (1 == pustrPath->length) || \
+ (pustrPath->length > 1 && pustrPath->buffer[pustrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR), \
+ "osl_systemPathRemoveSeparator: Post condition failed");
+ }
+
+ /*******************************************
+ osl_systemPathEnsureSeparator
+ ******************************************/
+
+ void SAL_CALL osl_systemPathEnsureSeparator(rtl_uString** ppustrPath)
+ {
+ OSL_PRECOND(ppustrPath && (NULL != *ppustrPath), \
+ "osl_systemPathEnsureSeparator: Invalid parameter");
+
+ rtl::OUString path(*ppustrPath);
+ sal_Int32 lp = path.getLength();
+ sal_Int32 i = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
+
+ if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0))
+ {
+ path += FPH_PATH_SEPARATOR();
+ rtl_uString_assign(ppustrPath, path.pData);
+ }
+
+ OSL_POSTCOND(path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR) == (path.getLength() - 1), \
+ "osl_systemPathEnsureSeparator: Post condition failed");
+ }
+
+ /*******************************************
+ * osl_systemPathIsRelativePath
+ ******************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsRelativePath(const rtl_uString* pustrPath)
+ {
+ OSL_PRECOND(pustrPath, "osl_systemPathIsRelativePath: Invalid parameter");
+ return ((0 == pustrPath->length) || (pustrPath->buffer[0] != FPH_CHAR_PATH_SEPARATOR));
+ }
+
+ /******************************************
+ osl_systemPathMakeAbsolutePath
+ *****************************************/
+
+ void SAL_CALL osl_systemPathMakeAbsolutePath(
+ const rtl_uString* pustrBasePath,
+ const rtl_uString* pustrRelPath,
+ rtl_uString** ppustrAbsolutePath)
+{
+ rtl::OUString base(rtl_uString_getStr(const_cast<rtl_uString*>(pustrBasePath)));
+ rtl::OUString rel(const_cast<rtl_uString*>(pustrRelPath));
+
+ if (base.getLength() > 0)
+ osl_systemPathEnsureSeparator(&base.pData);
+
+ base += rel;
+
+ rtl_uString_acquire(base.pData);
+ *ppustrAbsolutePath = base.pData;
+}
+
+
+ /*******************************************
+ osl_systemPathGetFileOrLastDirectoryPart
+ ******************************************/
+
+ void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart(
+ const rtl_uString* pustrPath,
+ rtl_uString** ppustrFileNameOrLastDirPart)
+{
+ OSL_PRECOND(pustrPath && ppustrFileNameOrLastDirPart, \
+ "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter");
+
+ rtl::OUString path(const_cast<rtl_uString*>(pustrPath));
+
+ osl_systemPathRemoveSeparator(path.pData);
+
+ rtl::OUString last_part;
+
+ if (path.getLength() > 1 || (1 == path.getLength() && *path.getStr() != FPH_CHAR_PATH_SEPARATOR))
+ {
+ sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
+ idx_ps++; // always right to increment by one even if idx_ps == -1!
+ last_part = rtl::OUString(path.getStr() + idx_ps);
+ }
+ rtl_uString_assign(ppustrFileNameOrLastDirPart, last_part.pData);
+}
+
+
+ /********************************************
+ osl_systemPathIsHiddenFileOrDirectoryEntry
+ *********************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry(
+ const rtl_uString* pustrPath)
+{
+ OSL_PRECOND(pustrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter");
+
+ sal_Bool is_hidden = sal_False;
+
+ if (pustrPath->length > 0)
+ {
+ rtl::OUString fdp;
+
+ osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &fdp.pData);
+
+ is_hidden = ((fdp.pData->length > 0) && (fdp.pData->buffer[0] == FPH_CHAR_DOT) &&
+ !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData));
+ }
+
+ return is_hidden;
+}
+
+
+ /************************************************
+ osl_systemPathIsLocalOrParentDirectoryEntry
+ ************************************************/
+
+sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry(
+ const rtl_uString* pustrPath)
+{
+ OSL_PRECOND(pustrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter");
+
+ rtl::OUString dirent;
+
+ osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &dirent.pData);
+
+ return (
+ (dirent == FPH_LOCAL_DIR_ENTRY()) ||
+ (dirent == FPH_PARENT_DIR_ENTRY())
+ );
+}
+
+/***********************************************
+ Simple iterator for a path list separated by
+ the specified character
+ **********************************************/
+
+class path_list_iterator
+{
+public:
+
+ /******************************************
+ constructor
+
+ after construction get_current_item
+ returns the first path in list, no need
+ to call reset first
+ *****************************************/
+ path_list_iterator(const rtl::OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) :
+ m_path_list(path_list),
+ m_end(m_path_list.getStr() + m_path_list.getLength() + 1),
+ m_separator(list_separator)
+ {
+ reset();
+ }
+
+ /******************************************
+ reset the iterator
+ *****************************************/
+ void reset()
+ {
+ m_path_segment_begin = m_path_segment_end = m_path_list.getStr();
+ advance();
+ }
+
+ /******************************************
+ move the iterator to the next position
+ *****************************************/
+ void next()
+ {
+ OSL_PRECOND(!done(), "path_list_iterator: Already done!");
+
+ m_path_segment_begin = ++m_path_segment_end;
+ advance();
+ }
+
+ /******************************************
+ check if done
+ *****************************************/
+ bool done() const
+ {
+ return (m_path_segment_end >= m_end);
+ }
+
+ /******************************************
+ return the current item
+ *****************************************/
+ rtl::OUString get_current_item() const
+ {
+ return rtl::OUString(
+ m_path_segment_begin,
+ (m_path_segment_end - m_path_segment_begin));
+ }
+
+private:
+
+ /******************************************
+ move m_path_end to the next separator or
+ to the edn of the string
+ *****************************************/
+ void advance()
+ {
+ while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator))
+ ++m_path_segment_end;
+
+ OSL_ASSERT(m_path_segment_end <= m_end);
+ }
+
+private:
+ rtl::OUString m_path_list;
+ const sal_Unicode* m_end;
+ const sal_Unicode m_separator;
+ const sal_Unicode* m_path_segment_begin;
+ const sal_Unicode* m_path_segment_end;
+
+// prevent copy and assignment
+private:
+ /******************************************
+ copy constructor
+ remember: do not simply copy m_path_begin
+ and m_path_end because they point to
+ the memory of other.m_path_list!
+ *****************************************/
+ path_list_iterator(const path_list_iterator& other);
+
+ /******************************************
+ assignment operator
+ remember: do not simply copy m_path_begin
+ and m_path_end because they point to
+ the memory of other.m_path_list!
+ *****************************************/
+ path_list_iterator& operator=(const path_list_iterator& other);
+};
+
+ /************************************************
+ osl_searchPath
+ ***********************************************/
+
+sal_Bool SAL_CALL osl_searchPath(
+ const rtl_uString* pustrFilePath,
+ const rtl_uString* pustrSearchPathList,
+ rtl_uString** ppustrPathFound)
+{
+ OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter");
+
+ bool bfound = false;
+ rtl::OUString fp(const_cast<rtl_uString*>(pustrFilePath));
+ rtl::OUString pl = rtl::OUString(const_cast<rtl_uString*>(pustrSearchPathList));
+ path_list_iterator pli(pl);
+
+ while (!pli.done())
+ {
+ rtl::OUString p = pli.get_current_item();
+ osl::systemPathEnsureSeparator(p);
+ p += fp;
+
+ if (osl::access(p, F_OK) > -1)
+ {
+ bfound = true;
+ rtl_uString_assign(ppustrPathFound, p.pData);
+ break;
+ }
+ pli.next();
+ }
+ return bfound;
+}
diff --git a/sal/osl/unx/file_path_helper.h b/sal/osl/unx/file_path_helper.h
new file mode 100644
index 000000000000..c1e3908fa9f2
--- /dev/null
+++ b/sal/osl/unx/file_path_helper.h
@@ -0,0 +1,247 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #ifndef _OSL_FILE_PATH_HELPER_H_
+ #define _OSL_FILE_PATH_HELPER_H_
+
+
+ #ifndef _SAL_TYPES_H_
+ #include <sal/types.h>
+ #endif
+
+ #ifndef _RTL_USTRING_H_
+ #include <rtl/ustring.h>
+ #endif
+
+
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+
+
+ /*******************************************
+ osl_systemPathRemoveSeparator
+ Removes the last separator from the
+ given system path if any and if the path
+ is not the root path '/'
+
+ @param ppustrPath [inout] a system path
+ if the path is not the root path
+ and the last character is a
+ path separator it will be cut off
+ ppustrPath must not be NULL and
+ must point to a valid rtl_uString
+
+ @returns nothing
+
+ ******************************************/
+
+ void SAL_CALL osl_systemPathRemoveSeparator(
+ /*inout*/ rtl_uString* pustrPath);
+
+ /*******************************************
+ osl_systemPathEnsureSeparator
+ Adds a trailing path separator to the
+ given system path if not already there
+ and if the path is not the root path '/'
+
+ @param pustrPath [inout] a system path
+ if the path is not the root path
+ '/' and has no trailing separator
+ a separator will be added
+ ppustrPath must not be NULL and
+ must point to a valid rtl_uString
+
+ @returns nothing
+
+ ******************************************/
+
+ void SAL_CALL osl_systemPathEnsureSeparator(
+ /*inout*/ rtl_uString** ppustrPath);
+
+ /*******************************************
+ osl_systemPathIsRelativePath
+ Returns true if the given path is a
+ relative path and so starts not with '/'
+
+ @param pustrPath [in] a system path
+ pustrPath must not be NULL
+
+ @returns sal_True if the given path
+ doesn't start with a separator
+ else sal_False will be returned
+
+ ******************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsRelativePath(
+ const rtl_uString* pustrPath);
+
+ /******************************************
+ osl_systemPathMakeAbsolutePath
+ Append a relative path to a base path
+
+ @param pustrBasePath [in] a system
+ path that will be considered as
+ base path
+ pustrBasePath must not be NULL
+
+ @param pustrRelPath [in] a system path
+ that will be considered as
+ relative path
+ pustrBasePath must not be NULL
+
+ @param ppustrAbsolutePath [out] the
+ resulting path which is a
+ concatination of the base and
+ the relative path
+ if base path is empty the
+ resulting absolute path is the
+ relative path
+ if relative path is empty the
+ resulting absolute path is the
+ base path
+ if base and relative path are
+ empty the resulting absolute
+ path is also empty
+ ppustrAbsolutePath must not be
+ NULL and *ppustrAbsolutePath
+ must be 0 or point to a valid
+ rtl_uString
+
+ *****************************************/
+
+ void SAL_CALL osl_systemPathMakeAbsolutePath(
+ const rtl_uString* pustrBasePath,
+ const rtl_uString* pustrRelPath,
+ rtl_uString** ppustrAbsolutePath);
+
+ /*****************************************
+ osl_systemPathGetFileOrLastDirectoryPart
+ Returns the file or the directory part
+ of the given path
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @param ppustrFileOrDirPart [out] on
+ return receives the last part
+ of the given directory or the
+ file name
+ if pustrPath is the root path
+ '/' an empty string will be
+ returned
+ if pustrPath has a trailing
+ '/' the last part before the
+ '/' will be returned else
+ the part after the last '/'
+ will be returned
+
+ @returns nothing
+
+ ****************************************/
+ void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart(
+ const rtl_uString* pustrPath,
+ rtl_uString** ppustrFileNameOrLastDirPart);
+
+
+ /********************************************
+ osl_systemPathIsHiddenFileOrDirectoryEntry
+ Returns sal_True if the last part of
+ given system path is not '.' or '..'
+ alone and starts with a '.'
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @returns sal_True if the last part of
+ the given system path starts
+ with '.' or sal_False the last
+ part is '.' or '..' alone or
+ doesn't start with a dot
+
+ *********************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry(
+ const rtl_uString* pustrPath);
+
+
+ /************************************************
+ osl_systemPathIsLocalOrParentDirectoryEntry
+ Returns sal_True if the last part of the given
+ system path is the local directory entry '.'
+ or the parent directory entry '..'
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @returns sal_True if the last part of the
+ given system path is '.' or '..'
+ else sal_False
+
+ ************************************************/
+
+ sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry(
+ const rtl_uString* pustrPath);
+
+
+ /************************************************
+ osl_searchPath
+ Searches for a file name or path name in all
+ directories specified by a given path list.
+ Symbolic links in the resulting path will not be
+ resolved, it's up to the caller to do this.
+
+ @param pustrFilePath [in] a file name or
+ directory name to search for, the name must
+ be provided as system path not as a file URL
+
+ @param pustrSearchPathList [in] a ':'
+ separated list of paths in which to search for
+ the file or directory name
+
+ @ppustrPathFound [out] on success receives the
+ complete path of the file or directory found
+ as a system path
+
+ @returns sal_True if the specified file or
+ directory was found else sal_False
+ ***********************************************/
+
+ sal_Bool SAL_CALL osl_searchPath(
+ const rtl_uString* pustrFilePath,
+ const rtl_uString* pustrSearchPathList,
+ rtl_uString** ppustrPathFound);
+
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+
+ #endif /* #ifndef _OSL_PATH_HELPER_H_ */
+
diff --git a/sal/osl/unx/file_path_helper.hxx b/sal/osl/unx/file_path_helper.hxx
new file mode 100644
index 000000000000..4b429b111799
--- /dev/null
+++ b/sal/osl/unx/file_path_helper.hxx
@@ -0,0 +1,247 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_FILE_PATH_HELPER_HXX_
+#define _OSL_FILE_PATH_HELPER_HXX_
+
+
+#ifndef _OSL_FILE_PATH_HELPER_H_
+#include "file_path_helper.h"
+#endif
+
+#include <rtl/ustring.hxx>
+
+
+namespace osl
+{
+
+ /*******************************************
+ systemPathRemoveSeparator
+ Removes the last separator from the
+ given system path if any and if the path
+ is not the root path '/'
+
+ @param ppustrPath [inout] a system path
+ if the path is not the root path
+ and the last character is a
+ path separator it will be cut off
+ ppustrPath must not be NULL and
+ must point to a valid rtl_uString
+
+ @returns nothing
+
+ ******************************************/
+
+ inline void systemPathRemoveSeparator(/*inout*/ rtl::OUString& Path)
+ {
+ osl_systemPathRemoveSeparator(Path.pData);
+ }
+
+ /*******************************************
+ systemPathEnsureSeparator
+ Adds a trailing path separator to the
+ given system path if not already there
+ and if the path is not the root path '/'
+
+ @param pustrPath [inout] a system path
+ if the path is not the root path
+ '/' and has no trailing separator
+ a separator will be added
+ ppustrPath must not be NULL and
+ must point to a valid rtl_uString
+
+ @returns nothing
+
+ ******************************************/
+
+ inline void systemPathEnsureSeparator(/*inout*/ rtl::OUString& Path)
+ {
+ osl_systemPathEnsureSeparator(&Path.pData);
+ }
+
+ /*******************************************
+ systemPathIsRelativePath
+ Returns true if the given path is a
+ relative path and so starts not with '/'
+
+ @param pustrPath [in] a system path
+ pustrPath must not be NULL
+
+ @returns sal_True if the given path
+ doesn't start with a separator
+ else sal_False will be returned
+
+ ******************************************/
+
+ inline bool systemPathIsRelativePath(const rtl::OUString& Path)
+ {
+ return osl_systemPathIsRelativePath(Path.pData);
+ }
+
+ /******************************************
+ systemPathMakeAbsolutePath
+ Append a relative path to a base path
+
+ @param pustrBasePath [in] a system
+ path that will be considered as
+ base path
+ pustrBasePath must not be NULL
+
+ @param pustrRelPath [in] a system path
+ that will be considered as
+ relative path
+ pustrBasePath must not be NULL
+
+ @param ppustrAbsolutePath [out] the
+ resulting path which is a
+ concatination of the base and
+ the relative path
+ if base path is empty the
+ resulting absolute path is the
+ relative path
+ if relative path is empty the
+ resulting absolute path is the
+ base path
+ if base and relative path are
+ empty the resulting absolute
+ path is also empty
+ ppustrAbsolutePath must not be
+ NULL and *ppustrAbsolutePath
+ must be 0 or point to a valid
+ rtl_uString
+
+ *****************************************/
+
+ inline void systemPathMakeAbsolutePath(
+ const rtl::OUString& BasePath,
+ const rtl::OUString& RelPath,
+ rtl::OUString& AbsolutePath)
+ {
+ osl_systemPathMakeAbsolutePath(
+ BasePath.pData, RelPath.pData, &AbsolutePath.pData);
+ }
+
+ /*****************************************
+ systemPathGetFileOrLastDirectoryPart
+ Returns the file or the directory part
+ of the given path
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @param ppustrFileOrDirPart [out] on
+ return receives the last part
+ of the given directory or the
+ file name
+ if pustrPath is the root path
+ '/' an empty string will be
+ returned
+ if pustrPath has a trailing
+ '/' the last part before the
+ '/' will be returned else
+ the part after the last '/'
+ will be returned
+
+ @returns nothing
+
+ ****************************************/
+
+ inline void systemPathGetFileNameOrLastDirectoryPart(
+ const rtl::OUString& Path,
+ rtl::OUString& FileNameOrLastDirPart)
+ {
+ osl_systemPathGetFileNameOrLastDirectoryPart(
+ Path.pData, &FileNameOrLastDirPart.pData);
+ }
+
+
+ /********************************************
+ systemPathIsHiddenFileOrDirectoryEntry
+ Returns sal_True if the last part of
+ given system path is not '.' or '..'
+ alone and starts with a '.'
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @returns sal_True if the last part of
+ the given system path starts
+ with '.' or sal_False the last
+ part is '.' or '..' alone or
+ doesn't start with a dot
+
+ *********************************************/
+
+ inline bool systemPathIsHiddenFileOrDirectoryEntry(
+ const rtl::OUString& Path)
+ {
+ return osl_systemPathIsHiddenFileOrDirectoryEntry(Path.pData);
+ }
+
+
+ /************************************************
+ systemPathIsLocalOrParentDirectoryEntry
+ Returns sal_True if the last part of the given
+ system path is the local directory entry '.'
+ or the parent directory entry '..'
+
+ @param pustrPath [in] a system path,
+ must not be NULL
+
+ @returns sal_True if the last part of the
+ given system path is '.' or '..'
+ else sal_False
+
+ ************************************************/
+
+ inline bool systemPathIsLocalOrParentDirectoryEntry(
+ const rtl::OUString& Path)
+ {
+ return osl_systemPathIsLocalOrParentDirectoryEntry(Path.pData);
+ }
+
+ /************************************************
+ searchPath
+ ***********************************************/
+
+ inline bool searchPath(
+ const rtl::OUString& ustrFilePath,
+ const rtl::OUString& ustrSearchPathList,
+ rtl::OUString& ustrPathFound)
+ {
+ return osl_searchPath(
+ ustrFilePath.pData,
+ ustrSearchPathList.pData,
+ &ustrPathFound.pData);
+ }
+
+
+ } // namespace osl
+
+
+ #endif /* #ifndef _OSL_PATH_HELPER_HXX_ */
+
diff --git a/sal/osl/unx/file_stat.cxx b/sal/osl/unx/file_stat.cxx
new file mode 100644
index 000000000000..df32fa105a50
--- /dev/null
+++ b/sal/osl/unx/file_stat.cxx
@@ -0,0 +1,492 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "osl/file.h"
+
+#include "system.h"
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include "file_impl.hxx"
+#include "file_error_transl.h"
+#include "file_path_helper.hxx"
+#include "file_url.h"
+#include "uunxapi.hxx"
+
+namespace /* private */
+{
+
+ inline void set_file_type(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ /* links to directories state also to be a directory */
+ if (S_ISLNK(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Link;
+ else if (S_ISDIR(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Directory;
+ else if (S_ISREG(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Regular;
+ else if (S_ISFIFO(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Fifo;
+ else if (S_ISSOCK(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Socket;
+ else if (S_ISCHR(file_stat.st_mode) || S_ISBLK(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Special;
+ else
+ pStat->eType = osl_File_Type_Unknown;
+
+ pStat->uValidFields |= osl_FileStatus_Mask_Type;
+ }
+
+ inline void set_file_access_mask(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ // user permissions
+ if (S_IRUSR & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OwnRead;
+
+ if (S_IWUSR & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OwnWrite;
+
+ if (S_IXUSR & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OwnExe;
+
+ // group permissions
+ if (S_IRGRP & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_GrpRead;
+
+ if (S_IWGRP & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_GrpWrite;
+
+ if (S_IXGRP & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_GrpExe;
+
+ // others permissions
+ if (S_IROTH & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OthRead;
+
+ if (S_IWOTH & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OthWrite;
+
+ if (S_IXOTH & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OthExe;
+
+ pStat->uValidFields |= osl_FileStatus_Mask_Attributes;
+ }
+
+ inline void set_file_access_rights(const struct stat& file_stat, int S_IR, int S_IW, int S_IX, oslFileStatus* pStat)
+ {
+ /* we cannot really map osl_File_Attribute_ReadOnly to
+ the Unix access rights, it's a Windows only flag
+ that's why the following hack. We set osl_FileStatus_Mask_Attributes
+ but if there is no read access for a file we clear the flag
+ again to signal to the caller that there are no file attributes
+ to read because that's better than to give them incorrect one.
+ */
+ pStat->uValidFields |= osl_FileStatus_Mask_Attributes;
+
+ if ((0 == (S_IW & file_stat.st_mode)) && (S_IR & file_stat.st_mode))
+ pStat->uAttributes |= osl_File_Attribute_ReadOnly;
+
+ if (S_IX & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_Executable;
+ }
+
+ /* a process may belong to up to NGROUPS_MAX groups, so when
+ checking group access rights, we have to check all belonging
+ groups */
+ inline bool is_in_process_grouplist(const gid_t file_group)
+ {
+ // check primary process group
+
+ if (getgid() == file_group)
+ return true;
+
+ // check supplementary process groups
+
+ gid_t grplist[NGROUPS_MAX];
+ int grp_number = getgroups(NGROUPS_MAX, grplist);
+
+ for (int i = 0; i < grp_number; i++)
+ {
+ if (grplist[i] == file_group)
+ return true;
+ }
+ return false;
+ }
+
+ /* Currently we are determining the file access right based
+ on the real user ID not the effective user ID!
+ We don't use access(...) because access follows links which
+ may cause performance problems see #97133.
+ */
+ inline void set_file_access_rights(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ if (getuid() == file_stat.st_uid)
+ {
+ set_file_access_rights(file_stat, S_IRUSR, S_IWUSR, S_IXUSR, pStat);
+ }
+ else if (is_in_process_grouplist(file_stat.st_gid))
+ {
+ set_file_access_rights(file_stat, S_IRGRP, S_IWGRP, S_IXGRP, pStat);
+ }
+ else
+ {
+ set_file_access_rights(file_stat, S_IROTH, S_IWOTH, S_IXOTH, pStat);
+ }
+ }
+
+ inline void set_file_hidden_status(const rtl::OUString& file_path, oslFileStatus* pStat)
+ {
+ pStat->uAttributes = osl::systemPathIsHiddenFileOrDirectoryEntry(file_path) ? osl_File_Attribute_Hidden : 0;
+ pStat->uValidFields |= osl_FileStatus_Mask_Attributes;
+ }
+
+ /* the set_file_access_rights must be called after set_file_hidden_status(...) and
+ set_file_access_mask(...) because of the hack in set_file_access_rights(...) */
+ inline void set_file_attributes(
+ const rtl::OUString& file_path, const struct stat& file_stat, const sal_uInt32 uFieldMask, oslFileStatus* pStat)
+ {
+ set_file_hidden_status(file_path, pStat);
+ set_file_access_mask(file_stat, pStat);
+
+ // we set the file access rights only on demand
+ // because it's potentially expensive
+ if (uFieldMask & osl_FileStatus_Mask_Attributes)
+ set_file_access_rights(file_stat, pStat);
+ }
+
+ inline void set_file_access_time(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ pStat->aAccessTime.Seconds = file_stat.st_atime;
+ pStat->aAccessTime.Nanosec = 0;
+ pStat->uValidFields |= osl_FileStatus_Mask_AccessTime;
+ }
+
+ inline void set_file_modify_time(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ pStat->aModifyTime.Seconds = file_stat.st_mtime;
+ pStat->aModifyTime.Nanosec = 0;
+ pStat->uValidFields |= osl_FileStatus_Mask_ModifyTime;
+ }
+
+ inline void set_file_size(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ if (S_ISREG(file_stat.st_mode))
+ {
+ pStat->uFileSize = file_stat.st_size;
+ pStat->uValidFields |= osl_FileStatus_Mask_FileSize;
+ }
+ }
+
+ /* we only need to call stat or lstat if one of the
+ following flags is set */
+ inline bool is_stat_call_necessary(sal_uInt32 field_mask, oslFileType file_type = osl_File_Type_Unknown)
+ {
+ return (
+ ((field_mask & osl_FileStatus_Mask_Type) && (file_type == osl_File_Type_Unknown)) ||
+ (field_mask & osl_FileStatus_Mask_Attributes) ||
+ (field_mask & osl_FileStatus_Mask_CreationTime) ||
+ (field_mask & osl_FileStatus_Mask_AccessTime) ||
+ (field_mask & osl_FileStatus_Mask_ModifyTime) ||
+ (field_mask & osl_FileStatus_Mask_FileSize) ||
+ (field_mask & osl_FileStatus_Mask_LinkTargetURL) ||
+ (field_mask & osl_FileStatus_Mask_Validate));
+ }
+
+ inline oslFileError set_link_target_url(const rtl::OUString& file_path, oslFileStatus* pStat)
+ {
+ rtl::OUString link_target;
+ if (!osl::realpath(file_path, link_target))
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ oslFileError osl_error = osl_getFileURLFromSystemPath(link_target.pData, &pStat->ustrLinkTargetURL);
+ if (osl_error != osl_File_E_None)
+ return osl_error;
+
+ pStat->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
+ return osl_File_E_None;
+ }
+
+ inline oslFileError setup_osl_getFileStatus(
+ DirectoryItem_Impl * pImpl, oslFileStatus* pStat, rtl::OUString& file_path)
+ {
+ if ((NULL == pImpl) || (NULL == pStat))
+ return osl_File_E_INVAL;
+
+ file_path = rtl::OUString(pImpl->m_ustrFilePath);
+ OSL_ASSERT(file_path.getLength() > 0);
+ if (file_path.getLength() <= 0)
+ return osl_File_E_INVAL;
+
+ pStat->uValidFields = 0;
+ return osl_File_E_None;
+ }
+
+} // end namespace private
+
+
+/****************************************************************************
+ * osl_getFileStatus
+ ****************************************************************************/
+
+oslFileError SAL_CALL osl_getFileStatus(oslDirectoryItem Item, oslFileStatus* pStat, sal_uInt32 uFieldMask)
+{
+ DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
+
+ rtl::OUString file_path;
+ oslFileError osl_error = setup_osl_getFileStatus(pImpl, pStat, file_path);
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ struct ::stat file_stat;
+#else
+ struct stat file_stat;
+#endif
+
+ bool bStatNeeded = is_stat_call_necessary(uFieldMask, pImpl->getFileType());
+ if (bStatNeeded && (0 != osl::lstat(file_path, file_stat)))
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ if (bStatNeeded)
+ {
+ // we set all these attributes because it's cheap
+ set_file_type(file_stat, pStat);
+ set_file_access_time(file_stat, pStat);
+ set_file_modify_time(file_stat, pStat);
+ set_file_size(file_stat, pStat);
+ set_file_attributes(file_path, file_stat, uFieldMask, pStat);
+
+ // file exists semantic of osl_FileStatus_Mask_Validate
+ if ((uFieldMask & osl_FileStatus_Mask_LinkTargetURL) && S_ISLNK(file_stat.st_mode))
+ {
+ osl_error = set_link_target_url(file_path, pStat);
+ if (osl_error != osl_File_E_None)
+ return osl_error;
+ }
+ }
+#ifdef _DIRENT_HAVE_D_TYPE
+ else if (uFieldMask & osl_FileStatus_Mask_Type)
+ {
+ pStat->eType = pImpl->getFileType();
+ pStat->uValidFields |= osl_FileStatus_Mask_Type;
+ }
+#endif /* _DIRENT_HAVE_D_TYPE */
+
+ if (uFieldMask & osl_FileStatus_Mask_FileURL)
+ {
+ if ((osl_error = osl_getFileURLFromSystemPath(file_path.pData, &pStat->ustrFileURL)) != osl_File_E_None)
+ return osl_error;
+
+ pStat->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+
+ if (uFieldMask & osl_FileStatus_Mask_FileName)
+ {
+ osl_systemPathGetFileNameOrLastDirectoryPart(file_path.pData, &pStat->ustrFileName);
+ pStat->uValidFields |= osl_FileStatus_Mask_FileName;
+ }
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_setFileAttributes */
+/****************************************************************************/
+
+static oslFileError osl_psz_setFileAttributes( const sal_Char* pszFilePath, sal_uInt64 uAttributes )
+{
+ oslFileError osl_error = osl_File_E_None;
+ mode_t nNewMode = 0;
+
+ OSL_ENSURE(!(osl_File_Attribute_Hidden & uAttributes), "osl_File_Attribute_Hidden doesn't work under Unix");
+
+ if (uAttributes & osl_File_Attribute_OwnRead)
+ nNewMode |= S_IRUSR;
+
+ if (uAttributes & osl_File_Attribute_OwnWrite)
+ nNewMode|=S_IWUSR;
+
+ if (uAttributes & osl_File_Attribute_OwnExe)
+ nNewMode|=S_IXUSR;
+
+ if (uAttributes & osl_File_Attribute_GrpRead)
+ nNewMode|=S_IRGRP;
+
+ if (uAttributes & osl_File_Attribute_GrpWrite)
+ nNewMode|=S_IWGRP;
+
+ if (uAttributes & osl_File_Attribute_GrpExe)
+ nNewMode|=S_IXGRP;
+
+ if (uAttributes & osl_File_Attribute_OthRead)
+ nNewMode|=S_IROTH;
+
+ if (uAttributes & osl_File_Attribute_OthWrite)
+ nNewMode|=S_IWOTH;
+
+ if (uAttributes & osl_File_Attribute_OthExe)
+ nNewMode|=S_IXOTH;
+
+ if (chmod(pszFilePath, nNewMode) < 0)
+ osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ return osl_error;
+}
+
+oslFileError SAL_CALL osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+
+ OSL_ASSERT( ustrFileURL );
+
+ /* convert file url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+#ifdef MACOSX
+ if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
+ return oslTranslateFileError( OSL_FET_ERROR, errno );
+#endif/* MACOSX */
+
+ return osl_psz_setFileAttributes( path, uAttributes );
+}
+
+/****************************************************************************/
+/* osl_setFileTime */
+/****************************************************************************/
+
+static oslFileError osl_psz_setFileTime (
+ const sal_Char* pszFilePath,
+ const TimeValue* /*pCreationTime*/,
+ const TimeValue* pLastAccessTime,
+ const TimeValue* pLastWriteTime )
+{
+ int nRet=0;
+ struct utimbuf aTimeBuffer;
+ struct stat aFileStat;
+#ifdef DEBUG_OSL_FILE
+ struct tm* pTM=0;
+#endif
+
+ nRet = lstat(pszFilePath,&aFileStat);
+
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"File Times are (in localtime):\n");
+ pTM=localtime(&aFileStat.st_ctime);
+ fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM));
+ pTM=localtime(&aFileStat.st_atime);
+ fprintf(stderr,"AccessTime is '%s'\n",asctime(pTM));
+ pTM=localtime(&aFileStat.st_mtime);
+ fprintf(stderr,"Modification is '%s'\n",asctime(pTM));
+
+ fprintf(stderr,"File Times are (in UTC):\n");
+ fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime));
+ fprintf(stderr,"AccessTime is '%s'\n",ctime(&aTimeBuffer.actime));
+ fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime));
+#endif
+
+ if ( pLastAccessTime != 0 )
+ {
+ aTimeBuffer.actime=pLastAccessTime->Seconds;
+ }
+ else
+ {
+ aTimeBuffer.actime=aFileStat.st_atime;
+ }
+
+ if ( pLastWriteTime != 0 )
+ {
+ aTimeBuffer.modtime=pLastWriteTime->Seconds;
+ }
+ else
+ {
+ aTimeBuffer.modtime=aFileStat.st_mtime;
+ }
+
+ /* mfe: Creation time not used here! */
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"File Times are (in localtime):\n");
+ pTM=localtime(&aFileStat.st_ctime);
+ fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM));
+ pTM=localtime(&aTimeBuffer.actime);
+ fprintf(stderr,"AccessTime now '%s'\n",asctime(pTM));
+ pTM=localtime(&aTimeBuffer.modtime);
+ fprintf(stderr,"Modification now '%s'\n",asctime(pTM));
+
+ fprintf(stderr,"File Times are (in UTC):\n");
+ fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime));
+ fprintf(stderr,"AccessTime now '%s'\n",ctime(&aTimeBuffer.actime));
+ fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime));
+#endif
+
+ nRet=utime(pszFilePath,&aTimeBuffer);
+ if ( nRet < 0 )
+ {
+ nRet=errno;
+ return oslTranslateFileError(OSL_FET_ERROR, nRet);
+ }
+
+ return osl_File_E_None;
+}
+
+oslFileError SAL_CALL osl_setFileTime (
+ rtl_uString* ustrFileURL,
+ const TimeValue* pCreationTime,
+ const TimeValue* pLastAccessTime,
+ const TimeValue* pLastWriteTime )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+
+ OSL_ASSERT( ustrFileURL );
+
+ /* convert file url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+#ifdef MACOSX
+ if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
+ return oslTranslateFileError( OSL_FET_ERROR, errno );
+#endif/* MACOSX */
+
+ return osl_psz_setFileTime( path, pCreationTime, pLastAccessTime, pLastWriteTime );
+}
diff --git a/sal/osl/unx/file_url.cxx b/sal/osl/unx/file_url.cxx
new file mode 100644
index 000000000000..26290957f802
--- /dev/null
+++ b/sal/osl/unx/file_url.cxx
@@ -0,0 +1,962 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "file_url.h"
+
+#include "system.h"
+
+#include <limits.h>
+#include <errno.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "osl/file.hxx"
+#include <osl/security.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/process.h>
+
+#include <rtl/uri.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.h>
+#include "rtl/textcvt.h"
+
+#include "file_error_transl.h"
+#include "file_path_helper.hxx"
+
+#include "uunxapi.hxx"
+
+/***************************************************
+
+ General note
+
+ This file contains the part that handles File URLs.
+
+ File URLs as scheme specific notion of URIs
+ (RFC2396) may be handled platform independend, but
+ will not in osl which is considered wrong.
+ Future version of osl should handle File URLs this
+ way. In rtl/uri there is already an URI parser etc.
+ so this code should be consolidated.
+
+ **************************************************/
+/************************************************************************
+ * ToDo
+ *
+ * Fix osl_getCanonicalName
+ *
+ ***********************************************************************/
+
+
+/***************************************************
+ * namespace directives
+ **************************************************/
+
+using namespace osl;
+
+/***************************************************
+ * constants
+ **************************************************/
+
+const sal_Unicode UNICHAR_SLASH = ((sal_Unicode)'/');
+const sal_Unicode UNICHAR_COLON = ((sal_Unicode)':');
+const sal_Unicode UNICHAR_DOT = ((sal_Unicode)'.');
+
+/******************************************************************************
+ *
+ * Exported Module Functions
+ *
+ *****************************************************************************/
+
+/* a slightly modified version of Pchar in rtl/source/uri.c */
+const sal_Bool uriCharClass[128] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */
+};
+
+
+/* check for top wrong usage strings */
+/*
+static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len )
+{
+ rtl_uString *pTmp = NULL;
+ sal_Bool bRet;
+
+ rtl_uString_newFromStr_WithLength( &pTmp, path, len );
+
+ rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length );
+
+ bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) );
+
+ rtl_uString_release( pTmp );
+ return bRet;
+}
+*/
+
+/****************************************************************************/
+/* osl_getCanonicalName */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL )
+{
+ OSL_ENSURE(0, "osl_getCanonicalName not implemented");
+
+ rtl_uString_newFromString(pustrValidURL, ustrFileURL);
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_getSystemPathFromFileURL */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath )
+{
+ sal_Int32 nIndex;
+ rtl_uString * pTmp = NULL;
+
+ sal_Unicode encodedSlash[3] = { '%', '2', 'F' };
+ sal_Unicode protocolDelimiter[3] = { ':', '/', '/' };
+
+ /* temporary hack: if already system path, return ustrFileURL */
+ /*
+ if( (sal_Unicode) '/' == ustrFileURL->buffer[0] )
+ {
+ OSL_ENSURE( 0, "osl_getSystemPathFromFileURL: input is already system path" );
+ rtl_uString_assign( pustrSystemPath, ustrFileURL );
+ return osl_File_E_None;
+ }
+ */
+
+ /* a valid file url may not start with '/' */
+ if( ( 0 == ustrFileURL->length ) || ( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ /* Check for non file:// protocols */
+
+ nIndex = rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, protocolDelimiter, 3 );
+ if ( -1 != nIndex && (4 != nIndex || 0 != rtl_ustr_ascii_shortenedCompare_WithLength( ustrFileURL->buffer, ustrFileURL->length,"file", 4 ) ) )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ /* search for encoded slashes (%2F) and decode every single token if we find one */
+
+ nIndex = 0;
+
+ if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, encodedSlash, 3 ) )
+ {
+ rtl_uString * ustrPathToken = NULL;
+ sal_Int32 nOffset = 7;
+
+ do
+ {
+ nOffset += nIndex;
+
+ /* break url down in '/' devided tokens tokens */
+ nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, (sal_Unicode) '/' );
+
+ /* copy token to new string */
+ rtl_uString_newFromStr_WithLength( &ustrPathToken, ustrFileURL->buffer + nOffset,
+ -1 == nIndex ? ustrFileURL->length - nOffset : nIndex++ );
+
+ /* decode token */
+ rtl_uriDecode( ustrPathToken, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
+
+ /* the result should not contain any '/' */
+ if( -1 != rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, (sal_Unicode) '/' ) )
+ {
+ rtl_uString_release( pTmp );
+ rtl_uString_release( ustrPathToken );
+
+ return osl_File_E_INVAL;
+ }
+
+ } while( -1 != nIndex );
+
+ /* release temporary string and restore index variable */
+ rtl_uString_release( ustrPathToken );
+ nIndex = 0;
+ }
+
+ /* protocol and server should not be encoded, so decode the whole string */
+ rtl_uriDecode( ustrFileURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
+
+ /* check if file protocol specified */
+ /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
+ if( 7 <= pTmp->length )
+ {
+ rtl_uString * pProtocol = NULL;
+ rtl_uString_newFromStr_WithLength( &pProtocol, pTmp->buffer, 7 );
+
+ /* protocol is case insensitive */
+ rtl_ustr_toAsciiLowerCase_WithLength( pProtocol->buffer, pProtocol->length );
+
+ if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pProtocol->buffer, pProtocol->length,"file://", 7 ) )
+ nIndex = 7;
+
+ rtl_uString_release( pProtocol );
+ }
+
+ /* skip "localhost" or "127.0.0.1" if "file://" is specified */
+ /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
+ if( nIndex && ( 10 <= pTmp->length - nIndex ) )
+ {
+ rtl_uString * pServer = NULL;
+ rtl_uString_newFromStr_WithLength( &pServer, pTmp->buffer + nIndex, 10 );
+
+ /* server is case insensitive */
+ rtl_ustr_toAsciiLowerCase_WithLength( pServer->buffer, pServer->length );
+
+ if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"localhost/", 10 ) ) ||
+ ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"127.0.0.1/", 10 ) ) )
+ {
+ /* don't exclude the '/' */
+ nIndex += 9;
+ }
+
+ rtl_uString_release( pServer );
+ }
+
+ if( nIndex )
+ rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex );
+
+ /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
+ if( (sal_Unicode) '~' == pTmp->buffer[0] )
+ {
+ /* check if another user is specified */
+ if( ( 1 == pTmp->length ) || ( (sal_Unicode)'/' == pTmp->buffer[1] ) )
+ {
+ rtl_uString *pTmp2 = NULL;
+
+ /* osl_getHomeDir returns file URL */
+ osl_getHomeDir( osl_getCurrentSecurity(), &pTmp2 );
+
+ /* remove "file://" prefix */
+ rtl_uString_newFromStr_WithLength( &pTmp2, pTmp2->buffer + 7, pTmp2->length - 7 );
+
+ /* replace '~' in original string */
+ rtl_uString_newReplaceStrAt( &pTmp, pTmp, 0, 1, pTmp2 );
+ rtl_uString_release( pTmp2 );
+ }
+
+ else
+ {
+ /* FIXME: replace ~user with users home directory */
+ return osl_File_E_INVAL;
+ }
+ }
+
+ /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
+ /*
+ OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
+ */
+
+ *pustrSystemPath = pTmp;
+ return osl_File_E_None;
+}
+
+/****************************************************************************/
+/* osl_getFileURLFromSystemPath */
+/****************************************************************************/
+
+oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL )
+{
+ static const sal_Unicode pDoubleSlash[2] = { '/', '/' };
+
+ rtl_uString *pTmp = NULL;
+ sal_Int32 nIndex;
+
+ if( 0 == ustrSystemPath->length )
+ return osl_File_E_INVAL;
+
+ /* temporary hack: if already file url, return ustrSystemPath */
+
+ if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file:", 5 ) )
+ {
+ /*
+ if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file://", 7 ) )
+ {
+ OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is already file URL" );
+ rtl_uString_assign( pustrFileURL, ustrSystemPath );
+ }
+ else
+ {
+ rtl_uString *pTmp2 = NULL;
+
+ OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is wrong file URL" );
+ rtl_uString_newFromStr_WithLength( pustrFileURL, ustrSystemPath->buffer + 5, ustrSystemPath->length - 5 );
+ rtl_uString_newFromAscii( &pTmp2, "file://" );
+ rtl_uString_newConcat( pustrFileURL, *pustrFileURL, pTmp2 );
+ rtl_uString_release( pTmp2 );
+ }
+ return osl_File_E_None;
+ */
+ return osl_File_E_INVAL;
+ }
+
+
+ /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
+ if( (sal_Unicode) '~' == ustrSystemPath->buffer[0] )
+ {
+ /* check if another user is specified */
+ if( ( 1 == ustrSystemPath->length ) || ( (sal_Unicode)'/' == ustrSystemPath->buffer[1] ) )
+ {
+ /* osl_getHomeDir returns file URL */
+ osl_getHomeDir( osl_getCurrentSecurity(), &pTmp );
+
+ /* remove "file://" prefix */
+ rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + 7, pTmp->length - 7 );
+
+ /* replace '~' in original string */
+ rtl_uString_newReplaceStrAt( &pTmp, ustrSystemPath, 0, 1, pTmp );
+ }
+
+ else
+ {
+ /* FIXME: replace ~user with users home directory */
+ return osl_File_E_INVAL;
+ }
+ }
+
+ /* check if initial string contains double instances of '/' */
+ nIndex = rtl_ustr_indexOfStr_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, pDoubleSlash, 2 );
+ if( -1 != nIndex )
+ {
+ sal_Int32 nSrcIndex;
+ sal_Int32 nDeleted = 0;
+
+ /* if pTmp is not already allocated, copy ustrSystemPath for modification */
+ if( NULL == pTmp )
+ rtl_uString_newFromString( &pTmp, ustrSystemPath );
+
+ /* adapt index to pTmp */
+ nIndex += pTmp->length - ustrSystemPath->length;
+
+ /* remove all occurances of '//' */
+ for( nSrcIndex = nIndex + 1; nSrcIndex < pTmp->length; nSrcIndex++ )
+ {
+ if( ((sal_Unicode) '/' == pTmp->buffer[nSrcIndex]) && ((sal_Unicode) '/' == pTmp->buffer[nIndex]) )
+ nDeleted++;
+ else
+ pTmp->buffer[++nIndex] = pTmp->buffer[nSrcIndex];
+ }
+
+ /* adjust length member */
+ pTmp->length -= nDeleted;
+ }
+
+ if( NULL == pTmp )
+ rtl_uString_assign( &pTmp, ustrSystemPath );
+
+ /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
+ /*
+ OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
+ */
+
+ /* file URLs must be URI encoded */
+ rtl_uriEncode( pTmp, uriCharClass, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8, pustrFileURL );
+
+ rtl_uString_release( pTmp );
+
+ /* absolute urls should start with 'file://' */
+ if( (sal_Unicode)'/' == (*pustrFileURL)->buffer[0] )
+ {
+ rtl_uString *pProtocol = NULL;
+
+ rtl_uString_newFromAscii( &pProtocol, "file://" );
+ rtl_uString_newConcat( pustrFileURL, pProtocol, *pustrFileURL );
+ rtl_uString_release( pProtocol );
+ }
+
+ return osl_File_E_None;
+}
+
+/****************************************************************************
+ * osl_getSystemPathFromFileURL_Ex - helper function
+ * clients may specify if they want to accept relative
+ * URLs or not
+ ****************************************************************************/
+
+oslFileError osl_getSystemPathFromFileURL_Ex(
+ rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative)
+{
+ rtl_uString* temp = 0;
+ oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &temp);
+
+ if (osl_File_E_None == osl_error)
+ {
+ if (bAllowRelative || (UNICHAR_SLASH == temp->buffer[0]))
+ {
+ *pustrSystemPath = temp;
+ }
+ else
+ {
+ rtl_uString_release(temp);
+ osl_error = osl_File_E_INVAL;
+ }
+ }
+
+ return osl_error;
+}
+
+namespace /* private */
+{
+
+ /******************************************************
+ * Helper function, return a pinter to the final '\0'
+ * of a string
+ ******************************************************/
+
+ sal_Unicode* ustrtoend(sal_Unicode* pStr)
+ {
+ return (pStr + rtl_ustr_getLength(pStr));
+ }
+
+ /*********************************************
+
+ ********************************************/
+
+ sal_Unicode* ustrchrcat(const sal_Unicode chr, sal_Unicode* d)
+ {
+ sal_Unicode* p = ustrtoend(d);
+ *p++ = chr;
+ *p = 0;
+ return d;
+ }
+
+ /******************************************************
+ *
+ ******************************************************/
+
+ bool _islastchr(sal_Unicode* pStr, sal_Unicode Chr)
+ {
+ sal_Unicode* p = ustrtoend(pStr);
+ if (p > pStr)
+ p--;
+ return (*p == Chr);
+ }
+
+ /******************************************************
+ * Remove the last part of a path, a path that has
+ * only a '/' or no '/' at all will be returned
+ * unmodified
+ ******************************************************/
+
+ sal_Unicode* _rmlastpathtoken(sal_Unicode* aPath)
+ {
+ /* we always may skip -2 because we
+ may at least stand on a '/' but
+ either there is no other character
+ before this '/' or it's another
+ character than the '/'
+ */
+ sal_Unicode* p = ustrtoend(aPath) - 2;
+
+ // move back to the next path separator
+ // or to the start of the string
+ while ((p > aPath) && (*p != UNICHAR_SLASH))
+ p--;
+
+ if (p >= aPath)
+ {
+ if (UNICHAR_SLASH == *p)
+ {
+ p++;
+ *p = '\0';
+ }
+ else
+ {
+ *p = '\0';
+ }
+ }
+
+ return aPath;
+ }
+
+ /******************************************************
+ *
+ ******************************************************/
+
+ oslFileError _osl_resolvepath(
+ /*inout*/ sal_Unicode* path,
+ /*inout*/ sal_Unicode* current_pos,
+ /*inout*/ bool* failed)
+ {
+ oslFileError ferr = osl_File_E_None;
+
+ if (!*failed)
+ {
+ char unresolved_path[PATH_MAX];
+ if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), path, rtl_ustr_getLength(path)))
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ char resolved_path[PATH_MAX];
+ if (realpath(unresolved_path, resolved_path))
+ {
+ if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX))
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ current_pos = ustrtoend(path) - 1;
+ }
+ else
+ {
+ if (EACCES == errno || ENOTDIR == errno || ENOENT == errno)
+ *failed = true;
+ else
+ ferr = oslTranslateFileError(OSL_FET_ERROR, errno);
+ }
+ }
+
+ return ferr;
+ }
+
+ /******************************************************
+ * Works even with non existing paths. The resulting
+ * path must not exceed PATH_MAX else
+ * osl_File_E_NAMETOOLONG is the result
+ ******************************************************/
+
+ oslFileError osl_getAbsoluteFileURL_impl_(const rtl::OUString& unresolved_path, rtl::OUString& resolved_path)
+ {
+ // the given unresolved path must not exceed PATH_MAX
+ if (unresolved_path.getLength() >= (PATH_MAX - 2))
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ sal_Unicode path_resolved_so_far[PATH_MAX];
+ const sal_Unicode* punresolved = unresolved_path.getStr();
+ sal_Unicode* presolvedsf = path_resolved_so_far;
+
+ // reserve space for leading '/' and trailing '\0'
+ // do not exceed this limit
+ sal_Unicode* sentinel = path_resolved_so_far + PATH_MAX - 2;
+
+ // if realpath fails with error ENOTDIR, EACCES or ENOENT
+ // we will not call it again, because _osl_realpath should also
+ // work with non existing directories etc.
+ bool realpath_failed = false;
+ oslFileError ferr;
+
+ path_resolved_so_far[0] = '\0';
+
+ while (*punresolved != '\0')
+ {
+ // ignore '/.' , skip one part back when '/..'
+
+ if ((UNICHAR_DOT == *punresolved) && (UNICHAR_SLASH == *presolvedsf))
+ {
+ if ('\0' == *(punresolved + 1))
+ {
+ punresolved++;
+ continue;
+ }
+ else if (UNICHAR_SLASH == *(punresolved + 1))
+ {
+ punresolved += 2;
+ continue;
+ }
+ else if ((UNICHAR_DOT == *(punresolved + 1)) && ('\0' == *(punresolved + 2) || (UNICHAR_SLASH == *(punresolved + 2))))
+ {
+ _rmlastpathtoken(path_resolved_so_far);
+
+ presolvedsf = ustrtoend(path_resolved_so_far) - 1;
+
+ if (UNICHAR_SLASH == *(punresolved + 2))
+ punresolved += 3;
+ else
+ punresolved += 2;
+
+ continue;
+ }
+ else // a file or directory name may start with '.'
+ {
+ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ ustrchrcat(*punresolved++, path_resolved_so_far);
+
+ if ('\0' == *punresolved && !realpath_failed)
+ {
+ ferr = _osl_resolvepath(
+ path_resolved_so_far,
+ presolvedsf,
+ &realpath_failed);
+
+ if (osl_File_E_None != ferr)
+ return ferr;
+ }
+ }
+ }
+ else if (UNICHAR_SLASH == *punresolved)
+ {
+ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ ustrchrcat(*punresolved++, path_resolved_so_far);
+
+ if (!realpath_failed)
+ {
+ ferr = _osl_resolvepath(
+ path_resolved_so_far,
+ presolvedsf,
+ &realpath_failed);
+
+ if (osl_File_E_None != ferr)
+ return ferr;
+
+ if (!_islastchr(path_resolved_so_far, UNICHAR_SLASH))
+ {
+ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ ustrchrcat(UNICHAR_SLASH, path_resolved_so_far);
+ }
+ }
+ }
+ else // any other character
+ {
+ if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
+ return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
+
+ ustrchrcat(*punresolved++, path_resolved_so_far);
+
+ if ('\0' == *punresolved && !realpath_failed)
+ {
+ ferr = _osl_resolvepath(
+ path_resolved_so_far,
+ presolvedsf,
+ &realpath_failed);
+
+ if (osl_File_E_None != ferr)
+ return ferr;
+ }
+ }
+ }
+
+ sal_Int32 len = rtl_ustr_getLength(path_resolved_so_far);
+
+ OSL_ASSERT(len < PATH_MAX);
+
+ resolved_path = rtl::OUString(path_resolved_so_far, len);
+
+ return osl_File_E_None;
+ }
+
+} // end namespace private
+
+
+/******************************************************
+ * osl_getAbsoluteFileURL
+ ******************************************************/
+
+oslFileError osl_getAbsoluteFileURL(rtl_uString* ustrBaseDirURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL)
+{
+ FileBase::RC rc;
+ rtl::OUString unresolved_path;
+
+ rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrRelativeURL), unresolved_path);
+
+ if(FileBase::E_None != rc)
+ return oslFileError(rc);
+
+ if (systemPathIsRelativePath(unresolved_path))
+ {
+ rtl::OUString base_path;
+ rc = (FileBase::RC) osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL, &base_path.pData, sal_False);
+
+ if (FileBase::E_None != rc)
+ return oslFileError(rc);
+
+ rtl::OUString abs_path;
+ systemPathMakeAbsolutePath(base_path, unresolved_path, abs_path);
+
+ unresolved_path = abs_path;
+ }
+
+ rtl::OUString resolved_path;
+ rc = (FileBase::RC) osl_getAbsoluteFileURL_impl_(unresolved_path, resolved_path);
+
+ if (FileBase::E_None == rc)
+ {
+ rc = (FileBase::RC) osl_getFileURLFromSystemPath(resolved_path.pData, pustrAbsoluteURL);
+ OSL_ASSERT(FileBase::E_None == rc);
+ }
+
+ return oslFileError(rc);
+}
+
+
+namespace /* private */
+{
+
+ /*********************************************
+ No separate error code if unicode to text
+ conversion or getenv fails because for the
+ caller there is no difference why a file
+ could not be found in $PATH
+ ********************************************/
+
+ bool find_in_PATH(const rtl::OUString& file_path, rtl::OUString& result)
+ {
+ bool bfound = false;
+ rtl::OUString path = rtl::OUString::createFromAscii("PATH");
+ rtl::OUString env_path;
+
+ if (osl_Process_E_None == osl_getEnvironment(path.pData, &env_path.pData))
+ bfound = osl::searchPath(file_path, env_path, result);
+
+ return bfound;
+ }
+
+ /*********************************************
+ No separate error code if unicode to text
+ conversion or getcwd fails because for the
+ caller there is no difference why a file
+ could not be found in CDW
+ ********************************************/
+
+ bool find_in_CWD(const rtl::OUString& file_path, rtl::OUString& result)
+ {
+ bool bfound = false;
+ rtl::OUString cwd_url;
+
+ if (osl_Process_E_None == osl_getProcessWorkingDir(&cwd_url.pData))
+ {
+ rtl::OUString cwd;
+ FileBase::getSystemPathFromFileURL(cwd_url, cwd);
+ bfound = osl::searchPath(file_path, cwd, result);
+ }
+ return bfound;
+ }
+
+ /*********************************************
+
+ ********************************************/
+
+ bool find_in_searchPath(const rtl::OUString& file_path, rtl_uString* search_path, rtl::OUString& result)
+ {
+ return (search_path && osl::searchPath(file_path, rtl::OUString(search_path), result));
+ }
+
+} // end namespace private
+
+
+/****************************************************************************
+ * osl_searchFileURL
+ ***************************************************************************/
+
+oslFileError osl_searchFileURL(rtl_uString* ustrFilePath, rtl_uString* ustrSearchPath, rtl_uString** pustrURL)
+{
+ OSL_PRECOND(ustrFilePath && pustrURL, "osl_searchFileURL: invalid parameter");
+
+ FileBase::RC rc;
+ rtl::OUString file_path;
+
+ // try to interpret search path as file url else assume it's a system path list
+ rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath), file_path);
+ if ((FileBase::E_None != rc) && (FileBase::E_INVAL == rc))
+ file_path = ustrFilePath;
+ else if (FileBase::E_None != rc)
+ return oslFileError(rc);
+
+ bool bfound = false;
+ rtl::OUString result;
+
+ if (find_in_searchPath(file_path, ustrSearchPath, result) ||
+ find_in_PATH(file_path, result) ||
+ find_in_CWD(file_path, result))
+ {
+ rtl::OUString resolved;
+
+ if (osl::realpath(result, resolved))
+ {
+#if OSL_DEBUG_LEVEL > 0
+ oslFileError osl_error =
+#endif
+ osl_getFileURLFromSystemPath(resolved.pData, pustrURL);
+ OSL_ASSERT(osl_File_E_None == osl_error);
+ bfound = true;
+ }
+ }
+ return bfound ? osl_File_E_None : osl_File_E_NOENT;
+}
+
+
+/****************************************************************************
+ * FileURLToPath
+ ***************************************************************************/
+
+oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL)
+{
+ rtl_uString* ustrSystemPath = NULL;
+ oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &ustrSystemPath);
+
+ if(osl_File_E_None != osl_error)
+ return osl_error;
+
+ osl_systemPathRemoveSeparator(ustrSystemPath);
+
+ /* convert unicode path to text */
+ if(!UnicodeToText( buffer, bufLen, ustrSystemPath->buffer, ustrSystemPath->length))
+ osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ rtl_uString_release(ustrSystemPath);
+
+ return osl_error;
+}
+
+/*****************************************************************************
+ * UnicodeToText
+ ****************************************************************************/
+
+namespace /* private */
+{
+ class UnicodeToTextConverter_Impl
+ {
+ rtl_UnicodeToTextConverter m_converter;
+
+ UnicodeToTextConverter_Impl()
+ : m_converter (rtl_createUnicodeToTextConverter (osl_getThreadTextEncoding()))
+ {}
+
+ ~UnicodeToTextConverter_Impl()
+ {
+ rtl_destroyUnicodeToTextConverter (m_converter);
+ }
+ public:
+ static UnicodeToTextConverter_Impl & getInstance()
+ {
+ static UnicodeToTextConverter_Impl g_theConverter;
+ return g_theConverter;
+ }
+
+ sal_Size convert(
+ sal_Unicode const * pSrcBuf, sal_Size nSrcChars, sal_Char * pDstBuf, sal_Size nDstBytes,
+ sal_uInt32 nFlags, sal_uInt32 * pInfo, sal_Size * pSrcCvtChars)
+ {
+ OSL_ASSERT(m_converter != 0);
+ return rtl_convertUnicodeToText (
+ m_converter, 0, pSrcBuf, nSrcChars, pDstBuf, nDstBytes, nFlags, pInfo, pSrcCvtChars);
+ }
+ };
+} // end namespace private
+
+int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen )
+{
+ sal_uInt32 nInfo = 0;
+ sal_Size nSrcChars = 0;
+
+ sal_Size nDestBytes = UnicodeToTextConverter_Impl::getInstance().convert (
+ uniText, uniTextLen, buffer, bufLen,
+ OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH, &nInfo, &nSrcChars);
+
+ if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
+ {
+ errno = EOVERFLOW;
+ return 0;
+ }
+
+ /* ensure trailing '\0' */
+ buffer[nDestBytes] = '\0';
+ return nDestBytes;
+}
+
+/*****************************************************************************
+ * TextToUnicode
+ ****************************************************************************/
+
+namespace /* private */
+{
+ class TextToUnicodeConverter_Impl
+ {
+ rtl_TextToUnicodeConverter m_converter;
+
+ TextToUnicodeConverter_Impl()
+ : m_converter (rtl_createTextToUnicodeConverter (osl_getThreadTextEncoding()))
+ {}
+
+ ~TextToUnicodeConverter_Impl()
+ {
+ rtl_destroyTextToUnicodeConverter (m_converter);
+ }
+
+ public:
+ static TextToUnicodeConverter_Impl & getInstance()
+ {
+ static TextToUnicodeConverter_Impl g_theConverter;
+ return g_theConverter;
+ }
+
+ sal_Size convert(
+ sal_Char const * pSrcBuf, sal_Size nSrcBytes, sal_Unicode * pDstBuf, sal_Size nDstChars,
+ sal_uInt32 nFlags, sal_uInt32 * pInfo, sal_Size * pSrcCvtBytes)
+ {
+ OSL_ASSERT(m_converter != 0);
+ return rtl_convertTextToUnicode (
+ m_converter, 0, pSrcBuf, nSrcBytes, pDstBuf, nDstChars, nFlags, pInfo, pSrcCvtBytes);
+ }
+ };
+} // end namespace private
+
+int TextToUnicode(
+ const char* text,
+ size_t text_buffer_size,
+ sal_Unicode* unic_text,
+ sal_Int32 unic_text_buffer_size)
+{
+ sal_uInt32 nInfo = 0;
+ sal_Size nSrcChars = 0;
+
+ sal_Size nDestBytes = TextToUnicodeConverter_Impl::getInstance().convert(
+ text, text_buffer_size, unic_text, unic_text_buffer_size,
+ OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH, &nInfo, &nSrcChars);
+
+ if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
+ {
+ errno = EOVERFLOW;
+ return 0;
+ }
+
+ /* ensure trailing '\0' */
+ unic_text[nDestBytes] = '\0';
+ return nDestBytes;
+}
diff --git a/sal/osl/unx/file_url.h b/sal/osl/unx/file_url.h
new file mode 100644
index 000000000000..0a0d07823bba
--- /dev/null
+++ b/sal/osl/unx/file_url.h
@@ -0,0 +1,69 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_FILE_URL_H
+#define INCLUDED_FILE_URL_H
+
+#include "osl/file.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************************************
+ * osl_getSystemPathFromFileURL_Ex
+ *************************************************/
+
+#define FURL_ALLOW_RELATIVE sal_True
+#define FURL_DENY_RELATIVE sal_False
+
+oslFileError osl_getSystemPathFromFileURL_Ex(rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative);
+
+/**************************************************
+ * FileURLToPath
+ *************************************************/
+
+oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL);
+
+/***************************************************
+ * UnicodeToText
+ **************************************************/
+
+int UnicodeToText(char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen);
+
+/***************************************************
+ * TextToUniCode
+ **************************************************/
+
+int TextToUnicode(const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #define INCLUDED_FILE_URL_H */
diff --git a/sal/osl/unx/file_volume.cxx b/sal/osl/unx/file_volume.cxx
new file mode 100644
index 000000000000..cc7f61ec6a8b
--- /dev/null
+++ b/sal/osl/unx/file_volume.cxx
@@ -0,0 +1,1155 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "osl/file.h"
+
+#include "osl/diagnose.h"
+#include "osl/thread.h"
+#include "rtl/alloc.h"
+
+#include "file_error_transl.h"
+#include "file_url.h"
+#include "system.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#ifdef HAVE_STATFS_H
+#undef HAVE_STATFS_H
+#endif
+
+#if defined(LINUX) && defined(__FreeBSD_kernel__)
+#undef LINUX
+#define FREEBSD 1
+#endif
+
+
+#if defined(SOLARIS)
+
+#include <sys/mnttab.h>
+#include <sys/statvfs.h>
+#define HAVE_STATFS_H
+#include <sys/fs/ufs_quota.h>
+static const sal_Char* MOUNTTAB="/etc/mnttab";
+
+#elif defined(LINUX)
+
+#include <mntent.h>
+#include <sys/vfs.h>
+#define HAVE_STATFS_H
+#include <sys/quota.h>
+//#include <ctype.h>
+static const sal_Char* MOUNTTAB="/etc/mtab";
+
+#elif defined(NETBSD) || defined(FREEBSD)
+
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <ufs/ufs/quota.h>
+//#include <ctype.h>
+#define HAVE_STATFS_H
+
+/* No mounting table on *BSD
+ * This information is stored only in the kernel. */
+/* static const sal_Char* MOUNTTAB="/etc/mtab"; */
+
+#elif defined(MACOSX)
+
+#include <ufs/ufs/quota.h>
+//#include <ctype.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#define HAVE_STATFS_H
+// static const sal_Char* MOUNTTAB="/etc/mtab";
+
+#endif /* HAVE_STATFS_H */
+
+/************************************************************************
+ * ToDo
+ *
+ * - Fix: check for corresponding struct sizes in exported functions
+ * - check size/use of oslVolumeDeviceHandle
+ * - check size/use of oslVolumeInfo
+ ***********************************************************************/
+/******************************************************************************
+ *
+ * Data Type Definition
+ *
+ ******************************************************************************/
+
+typedef struct _oslVolumeDeviceHandleImpl
+{
+ sal_Char pszMountPoint[PATH_MAX];
+ sal_Char pszFilePath[PATH_MAX];
+ sal_Char pszDevice[PATH_MAX];
+ sal_Char ident[4];
+ sal_uInt32 RefCount;
+} oslVolumeDeviceHandleImpl;
+
+/******************************************************************************
+ *
+ * 'removeable device' aka floppy functions
+ *
+ *****************************************************************************/
+
+static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath);
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy);
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy);
+
+#if defined(SOLARIS)
+static sal_Bool osl_isFloppyMounted(sal_Char* pszPath, sal_Char* pszMountPath);
+static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, sal_Char* pBuffer);
+static sal_Bool osl_checkFloppyPath(sal_Char* pszPath, sal_Char* pszFilePath, sal_Char* pszDevicePath);
+#endif /* SOLARIS */
+
+#if defined(LINUX)
+static sal_Bool osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice);
+static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem);
+#endif /* LINUX */
+
+#ifdef DEBUG_OSL_FILE
+static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* hFloppy);
+#endif /* DEBUG_OSL_FILE */
+
+/******************************************************************************
+ *
+ * C-String Function Declarations
+ *
+ *****************************************************************************/
+
+static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask);
+
+/****************************************************************************/
+/* osl_getVolumeInformation */
+/****************************************************************************/
+
+oslFileError osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask )
+{
+ char path[PATH_MAX];
+ oslFileError eRet;
+
+ OSL_ASSERT( ustrDirectoryURL );
+ OSL_ASSERT( pInfo );
+
+ /* convert directory url to system path */
+ eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
+ if( eRet != osl_File_E_None )
+ return eRet;
+
+#ifdef MACOSX
+ if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
+ return oslTranslateFileError( OSL_FET_ERROR, errno );
+#endif/* MACOSX */
+
+ return osl_psz_getVolumeInformation( path, pInfo, uFieldMask);
+}
+
+/******************************************************************************
+ *
+ * C-String Versions of Exported Module Functions
+ *
+ *****************************************************************************/
+
+#ifdef HAVE_STATFS_H
+
+#if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX)
+# define __OSL_STATFS_STRUCT struct statfs
+# define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
+# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
+# define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename)
+# define __OSL_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 0)
+
+/* always return true if queried for the properties of
+ the file system. If you think this is wrong under any
+ of the target platforms fix it!!!! */
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
+#endif /* FREEBSD || NETBSD || MACOSX */
+
+#if defined(LINUX)
+# define __OSL_NFS_SUPER_MAGIC 0x6969
+# define __OSL_SMB_SUPER_MAGIC 0x517B
+# define __OSL_MSDOS_SUPER_MAGIC 0x4d44
+# define __OSL_NTFS_SUPER_MAGIC 0x5346544e
+# define __OSL_STATFS_STRUCT struct statfs
+# define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
+# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
+# define __OSL_STATFS_IS_NFS(a) (__OSL_NFS_SUPER_MAGIC == (a).f_type)
+# define __OSL_STATFS_IS_SMB(a) (__OSL_SMB_SUPER_MAGIC == (a).f_type)
+# define __OSL_STATFS_ISREMOTE(a) (__OSL_STATFS_IS_NFS((a)) || __OSL_STATFS_IS_SMB((a)))
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type) && (__OSL_NTFS_SUPER_MAGIC != (a).f_type))
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type))
+#endif /* LINUX */
+
+#if defined(SOLARIS)
+# define __OSL_STATFS_STRUCT struct statvfs
+# define __OSL_STATFS(dir, sfs) statvfs((dir), (sfs))
+# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_frsize))
+# define __OSL_STATFS_TYPENAME(a) ((a).f_basetype)
+# define __OSL_STATFS_ISREMOTE(a) (rtl_str_compare((a).f_basetype, "nfs") == 0)
+
+/* always return true if queried for the properties of
+ the file system. If you think this is wrong under any
+ of the target platforms fix it!!!! */
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
+#endif /* SOLARIS */
+
+# define __OSL_STATFS_INIT(a) (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT)))
+
+#else /* no statfs available */
+
+# define __OSL_STATFS_STRUCT struct dummy {int i;}
+# define __OSL_STATFS_INIT(a) ((void)0)
+# define __OSL_STATFS(dir, sfs) (1)
+# define __OSL_STATFS_ISREMOTE(sfs) (0)
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
+#endif /* HAVE_STATFS_H */
+
+
+static oslFileError osl_psz_getVolumeInformation (
+ const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask)
+{
+ __OSL_STATFS_STRUCT sfs;
+
+ if (!pInfo)
+ return osl_File_E_INVAL;
+
+ __OSL_STATFS_INIT(sfs);
+
+ pInfo->uValidFields = 0;
+ pInfo->uAttributes = 0;
+
+ if ((__OSL_STATFS(pszDirectory, &sfs)) < 0)
+ {
+ oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno);
+ return (result);
+ }
+
+ /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */
+ if (uFieldMask & osl_VolumeInfo_Mask_Attributes)
+ {
+ if (__OSL_STATFS_ISREMOTE(sfs))
+ pInfo->uAttributes |= osl_Volume_Attribute_Remote;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+
+ if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling)
+ {
+ if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs))
+ pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive;
+
+ if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs))
+ pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+
+ pInfo->uTotalSpace = 0;
+ pInfo->uFreeSpace = 0;
+ pInfo->uUsedSpace = 0;
+
+#if defined(__OSL_STATFS_BLKSIZ)
+
+ if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) ||
+ (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
+ {
+ pInfo->uTotalSpace = __OSL_STATFS_BLKSIZ(sfs);
+ pInfo->uTotalSpace *= (sal_uInt64)(sfs.f_blocks);
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace;
+ }
+
+ if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) ||
+ (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
+ {
+ pInfo->uFreeSpace = __OSL_STATFS_BLKSIZ(sfs);
+
+ if (getuid() == 0)
+ pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree);
+ else
+ pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail);
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace;
+ }
+
+#endif /* __OSL_STATFS_BLKSIZ */
+
+ if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) &&
+ (pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace ))
+ {
+ pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace;
+ }
+
+ pInfo->uMaxNameLength = 0;
+ if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength)
+ {
+ long nLen = pathconf(pszDirectory, _PC_NAME_MAX);
+ if (nLen > 0)
+ {
+ pInfo->uMaxNameLength = (sal_uInt32)nLen;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
+ }
+ }
+
+ pInfo->uMaxPathLength = 0;
+ if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength)
+ {
+ long nLen = pathconf (pszDirectory, _PC_PATH_MAX);
+ if (nLen > 0)
+ {
+ pInfo->uMaxPathLength = (sal_uInt32)nLen;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
+ }
+ }
+
+#if defined(__OSL_STATFS_TYPENAME)
+
+ if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName)
+ {
+ rtl_string2UString(
+ &(pInfo->ustrFileSystemName),
+ __OSL_STATFS_TYPENAME(sfs),
+ rtl_str_getLength(__OSL_STATFS_TYPENAME(sfs)),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(pInfo->ustrFileSystemName != 0);
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
+ }
+
+#endif /* __OSL_STATFS_TYPENAME */
+
+ if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
+ {
+ /* FIXME: check also entries in mntent for the device
+ and fill it with correct values */
+
+ *pInfo->pDeviceHandle = osl_isFloppyDrive(pszDirectory);
+
+ if (*pInfo->pDeviceHandle)
+ {
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
+ pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+ }
+ return osl_File_E_None;
+}
+
+/******************************************************************************
+ *
+ * GENERIC FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+
+/*****************************************
+ * osl_unmountVolumeDevice
+ ****************************************/
+
+oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ oslFileError tErr = osl_File_E_NOSYS;
+
+ tErr = osl_unmountFloppy(Handle);
+
+ /* Perhaps current working directory is set to mount point */
+
+ if ( tErr )
+ {
+ sal_Char *pszHomeDir = getenv("HOME");
+
+ if ( pszHomeDir && strlen( pszHomeDir ) && 0 == chdir( pszHomeDir ) )
+ {
+ /* try again */
+
+ tErr = osl_unmountFloppy(Handle);
+
+ OSL_ENSURE( tErr, "osl_unmountvolumeDevice: CWD was set to volume mount point" );
+ }
+ }
+
+ return tErr;
+}
+
+/*****************************************
+ * osl_automountVolumeDevice
+ ****************************************/
+
+oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ oslFileError tErr = osl_File_E_NOSYS;
+
+ tErr = osl_mountFloppy(Handle);
+
+ return tErr;
+}
+
+/*****************************************
+ * osl_getVolumeDeviceMountPath
+ ****************************************/
+static rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
+{
+ rtl_string2UString(
+ ustrValid,
+ pszStr,
+ rtl_str_getLength( pszStr ),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*ustrValid != 0);
+
+ return *ustrValid;
+}
+
+oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
+{
+ oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle;
+ sal_Char Buffer[PATH_MAX];
+
+ Buffer[0] = '\0';
+
+ if ( pItem == 0 || pstrPath == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+ return osl_File_E_INVAL;
+ }
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"Handle is:\n");
+ osl_printFloppyHandle(pItem);
+#endif
+
+ snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint);
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"Mount Point is: '%s'\n",Buffer);
+#endif
+
+ oslMakeUStrFromPsz(Buffer, pstrPath);
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_acquireVolumeDeviceHandle
+ ****************************************/
+
+oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
+
+ if ( pItem == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ ++pItem->RefCount;
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_releaseVolumeDeviceHandle
+ ****************************************/
+
+oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
+
+ if ( pItem == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ --pItem->RefCount;
+
+ if ( pItem->RefCount == 0 )
+ {
+ rtl_freeMemory(pItem);
+ }
+
+ return osl_File_E_None;
+}
+
+#ifndef MACOSX
+
+/*****************************************
+ * osl_newVolumeDeviceHandleImpl
+ ****************************************/
+
+static oslVolumeDeviceHandleImpl* osl_newVolumeDeviceHandleImpl()
+{
+ oslVolumeDeviceHandleImpl* pHandle;
+ const size_t nSizeOfHandle = sizeof(oslVolumeDeviceHandleImpl);
+
+ pHandle = (oslVolumeDeviceHandleImpl*) rtl_allocateMemory (nSizeOfHandle);
+ if (pHandle != NULL)
+ {
+ pHandle->ident[0] = 'O';
+ pHandle->ident[1] = 'V';
+ pHandle->ident[2] = 'D';
+ pHandle->ident[3] = 'H';
+ pHandle->pszMountPoint[0] = '\0';
+ pHandle->pszFilePath[0] = '\0';
+ pHandle->pszDevice[0] = '\0';
+ pHandle->RefCount = 1;
+ }
+ return pHandle;
+}
+
+/*****************************************
+ * osl_freeVolumeDeviceHandleImpl
+ ****************************************/
+
+static void osl_freeVolumeDeviceHandleImpl (oslVolumeDeviceHandleImpl* pHandle)
+{
+ if (pHandle != NULL)
+ rtl_freeMemory (pHandle);
+}
+#endif
+
+/******************************************************************************
+ *
+ * SOLARIS FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+#if defined(SOLARIS)
+/* compare a given devicename with the typical device names on a Solaris box */
+static sal_Bool
+osl_isAFloppyDevice (const char* pDeviceName)
+{
+ const char* pFloppyDevice [] = {
+ "/dev/fd", "/dev/rfd",
+ "/dev/diskette", "/dev/rdiskette",
+ "/vol/dev/diskette", "/vol/dev/rdiskette"
+ };
+
+ int i;
+ for (i = 0; i < (sizeof(pFloppyDevice)/sizeof(pFloppyDevice[0])); i++)
+ {
+ if (strncmp(pDeviceName, pFloppyDevice[i], strlen(pFloppyDevice[i])) == 0)
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/* compare two directories whether the first may be a parent of the second. this
+ * does not realpath() resolving */
+static sal_Bool
+osl_isAParentDirectory (const char* pParentDir, const char* pSubDir)
+{
+ return strncmp(pParentDir, pSubDir, strlen(pParentDir)) == 0;
+}
+
+/* the name of the routine is obviously silly. But anyway create a
+ * oslVolumeDeviceHandle with correct mount point, device name and a resolved filepath
+ * only if pszPath points to file or directory on a floppy */
+static oslVolumeDeviceHandle
+osl_isFloppyDrive(const sal_Char* pszPath)
+{
+ FILE* pMountTab;
+ struct mnttab aMountEnt;
+ oslVolumeDeviceHandleImpl* pHandle;
+
+ if ((pHandle = osl_newVolumeDeviceHandleImpl()) == NULL)
+ {
+ return NULL;
+ }
+ if (realpath(pszPath, pHandle->pszFilePath) == NULL)
+ {
+ osl_freeVolumeDeviceHandleImpl (pHandle);
+ return NULL;
+ }
+ if ((pMountTab = fopen (MOUNTTAB, "r")) == NULL)
+ {
+ osl_freeVolumeDeviceHandleImpl (pHandle);
+ return NULL;
+ }
+
+ while (getmntent(pMountTab, &aMountEnt) == 0)
+ {
+ const char *pMountPoint = aMountEnt.mnt_mountp;
+ const char *pDevice = aMountEnt.mnt_special;
+ if ( osl_isAParentDirectory (aMountEnt.mnt_mountp, pHandle->pszFilePath)
+ && osl_isAFloppyDevice (aMountEnt.mnt_special))
+ {
+ /* skip the last item for it is the name of the disk */
+ char * pc = strrchr( aMountEnt.mnt_special, '/' );
+
+ if ( NULL != pc )
+ {
+ int len = pc - aMountEnt.mnt_special;
+
+ strncpy( pHandle->pszDevice, aMountEnt.mnt_special, len );
+ pHandle->pszDevice[len] = '\0';
+ }
+ else
+ {
+ /* #106048 use save str functions to avoid buffer overflows */
+ memset(pHandle->pszDevice, 0, sizeof(pHandle->pszDevice));
+ strncpy(pHandle->pszDevice, aMountEnt.mnt_special, sizeof(pHandle->pszDevice) - 1);
+ }
+
+ /* remember the mount point */
+ memset(pHandle->pszMountPoint, 0, sizeof(pHandle->pszMountPoint));
+ strncpy(pHandle->pszMountPoint, aMountEnt.mnt_mountp, sizeof(pHandle->pszMountPoint) - 1);
+
+ fclose (pMountTab);
+ return pHandle;
+ }
+ }
+
+ fclose (pMountTab);
+ osl_freeVolumeDeviceHandleImpl (pHandle);
+ return NULL;
+}
+
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ FILE* pMountTab;
+ struct mnttab aMountEnt;
+ oslVolumeDeviceHandleImpl* pHandle = (oslVolumeDeviceHandleImpl*) hFloppy;
+
+ int nRet=0;
+ sal_Char pszCmd[512] = "";
+
+ if ( pHandle == 0 )
+ return osl_File_E_INVAL;
+
+ /* FIXME: don't know what this is good for */
+ if ( pHandle->ident[0] != 'O' || pHandle->ident[1] != 'V' || pHandle->ident[2] != 'D' || pHandle->ident[3] != 'H' )
+ return osl_File_E_INVAL;
+
+ snprintf(pszCmd, sizeof(pszCmd), "eject -q %s > /dev/null 2>&1", pHandle->pszDevice);
+
+ nRet = system( pszCmd );
+
+ switch ( WEXITSTATUS(nRet) )
+ {
+ case 0:
+ {
+ /* lookup the device in mount tab again */
+ if ((pMountTab = fopen (MOUNTTAB, "r")) == NULL)
+ return osl_File_E_BUSY;
+
+ while (getmntent(pMountTab, &aMountEnt) == 0)
+ {
+ const char *pMountPoint = aMountEnt.mnt_mountp;
+ const char *pDevice = aMountEnt.mnt_special;
+ if ( 0 == strncmp( pHandle->pszDevice, aMountEnt.mnt_special, strlen(pHandle->pszDevice) ) )
+ {
+ memset(pHandle->pszMountPoint, 0, sizeof(pHandle->pszMountPoint));
+ strncpy (pHandle->pszMountPoint, aMountEnt.mnt_mountp, sizeof(pHandle->pszMountPoint) - 1);
+
+ fclose (pMountTab);
+ return osl_File_E_None;
+ }
+ }
+
+ fclose (pMountTab);
+ return osl_File_E_BUSY;
+ }
+ //break; // break not necessary here, see return statements before
+
+ case 1:
+ return osl_File_E_BUSY;
+
+ default:
+ break;
+ }
+
+ return osl_File_E_BUSY;
+}
+
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+// FILE* pMountTab;
+// struct mnttab aMountEnt;
+ oslVolumeDeviceHandleImpl* pHandle = (oslVolumeDeviceHandleImpl*) hFloppy;
+
+ int nRet=0;
+ sal_Char pszCmd[512] = "";
+
+ if ( pHandle == 0 )
+ return osl_File_E_INVAL;
+
+ /* FIXME: don't know what this is good for */
+ if ( pHandle->ident[0] != 'O' || pHandle->ident[1] != 'V' || pHandle->ident[2] != 'D' || pHandle->ident[3] != 'H' )
+ return osl_File_E_INVAL;
+
+ snprintf(pszCmd, sizeof(pszCmd), "eject %s > /dev/null 2>&1", pHandle->pszDevice);
+
+ nRet = system( pszCmd );
+
+ switch ( WEXITSTATUS(nRet) )
+ {
+ case 0:
+ {
+ FILE* pMountTab;
+ struct mnttab aMountEnt;
+
+ /* lookup if device is still in mount tab */
+ if ((pMountTab = fopen (MOUNTTAB, "r")) == NULL)
+ return osl_File_E_BUSY;
+
+ while (getmntent(pMountTab, &aMountEnt) == 0)
+ {
+ const char *pMountPoint = aMountEnt.mnt_mountp;
+ const char *pDevice = aMountEnt.mnt_special;
+ if ( 0 == strncmp( pHandle->pszDevice, aMountEnt.mnt_special, strlen(pHandle->pszDevice) ) )
+ {
+ fclose (pMountTab);
+ return osl_File_E_BUSY;
+ }
+ }
+
+ fclose (pMountTab);
+ pHandle->pszMountPoint[0] = 0;
+ return osl_File_E_None;
+ }
+
+ //break; //break not necessary, see return statements before
+
+ case 1:
+ return osl_File_E_NODEV;
+
+ case 4:
+ pHandle->pszMountPoint[0] = 0;
+ return osl_File_E_None;
+
+ default:
+ break;
+ }
+
+ return osl_File_E_BUSY;
+}
+
+#endif /* SOLARIS */
+
+/******************************************************************************
+ *
+ * LINUX FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+#if defined(LINUX)
+static oslVolumeDeviceHandle
+osl_isFloppyDrive (const sal_Char* pszPath)
+{
+ oslVolumeDeviceHandleImpl* pItem = osl_newVolumeDeviceHandleImpl();
+ if (osl_getFloppyMountEntry(pszPath, pItem))
+ return (oslVolumeDeviceHandle) pItem;
+
+ osl_freeVolumeDeviceHandleImpl (pItem);
+ return 0;
+}
+#endif /* LINUX */
+
+#if defined(LINUX)
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ sal_Bool bRet = sal_False;
+ oslVolumeDeviceHandleImpl* pItem=0;
+ int nRet;
+ sal_Char pszCmd[PATH_MAX];
+ const sal_Char* pszMountProg = "mount";
+ sal_Char* pszSuDo = 0;
+ sal_Char* pszTmp = 0;
+
+ pszCmd[0] = '\0';
+
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"In osl_mountFloppy\n");
+#endif
+
+ pItem = (oslVolumeDeviceHandleImpl*) hFloppy;
+
+ if ( pItem == 0 )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_mountFloppy [pItem == 0]\n");
+#endif
+
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_mountFloppy [invalid handle]\n");
+#endif
+ return osl_File_E_INVAL;
+ }
+
+ bRet = osl_isFloppyMounted(pItem);
+ if ( bRet == sal_True )
+ {
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"detected mounted floppy at '%s'\n",pItem->pszMountPoint);
+#endif
+ return osl_File_E_BUSY;
+ }
+
+ /* mfe: we can't use the mount(2) system call!!! */
+ /* even if we are root */
+ /* since mtab is not updated!!! */
+ /* but we need it to be updated */
+ /* some "magic" must be done */
+
+/* nRet = mount(pItem->pszDevice,pItem->pszMountPoint,0,0,0); */
+/* if ( nRet != 0 ) */
+/* { */
+/* nRet=errno; */
+/* #ifdef DEBUG_OSL_FILE */
+/* perror("mount"); */
+/* #endif */
+/* } */
+
+ pszTmp = getenv("SAL_MOUNT_MOUNTPROG");
+ if ( pszTmp != 0 )
+ {
+ pszMountProg=pszTmp;
+ }
+
+ pszTmp=getenv("SAL_MOUNT_SU_DO");
+ if ( pszTmp != 0 )
+ {
+ pszSuDo=pszTmp;
+ }
+
+ if ( pszSuDo != 0 )
+ {
+ snprintf(pszCmd, sizeof(pszCmd), "%s %s %s %s",pszSuDo,pszMountProg,pItem->pszDevice,pItem->pszMountPoint);
+ }
+ else
+ {
+ snprintf(pszCmd, sizeof(pszCmd), "%s %s",pszMountProg,pItem->pszMountPoint);
+ }
+
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"executing '%s'\n",pszCmd);
+#endif
+
+ nRet = system(pszCmd);
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"call returned '%i'\n",nRet);
+ fprintf(stderr,"exit status is '%i'\n", WEXITSTATUS(nRet));
+#endif
+
+
+ switch ( WEXITSTATUS(nRet) )
+ {
+ case 0:
+ nRet=0;
+ break;
+
+ case 2:
+ nRet=EPERM;
+ break;
+
+ case 4:
+ nRet=ENOENT;
+ break;
+
+ case 8:
+ nRet=EINTR;
+ break;
+
+ case 16:
+ nRet=EPERM;
+ break;
+
+ case 32:
+ nRet=EBUSY;
+ break;
+
+ case 64:
+ nRet=EAGAIN;
+ break;
+
+ default:
+ nRet=EBUSY;
+ break;
+ }
+
+ return ((0 == nRet) ? oslTranslateFileError(OSL_FET_SUCCESS, nRet) : oslTranslateFileError(OSL_FET_ERROR, nRet));
+}
+#endif /* LINUX */
+
+
+#if defined(LINUX)
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ oslVolumeDeviceHandleImpl* pItem=0;
+ int nRet=0;
+ sal_Char pszCmd[PATH_MAX];
+ sal_Char* pszTmp = 0;
+ sal_Char* pszSuDo = 0;
+ const sal_Char* pszUmountProg = "umount";
+
+ pszCmd[0] = '\0';
+
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"In osl_unmountFloppy\n");
+#endif
+
+ pItem = (oslVolumeDeviceHandleImpl*) hFloppy;
+
+ if ( pItem == 0 )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_unmountFloppy [pItem==0]\n");
+#endif
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_unmountFloppy [invalid handle]\n");
+#endif
+ return osl_File_E_INVAL;
+ }
+
+ /* mfe: we can't use the umount(2) system call!!! */
+ /* even if we are root */
+ /* since mtab is not updated!!! */
+ /* but we need it to be updated */
+ /* some "magic" must be done */
+
+/* nRet=umount(pItem->pszDevice); */
+/* if ( nRet != 0 ) */
+/* { */
+/* nRet = errno; */
+
+/* #ifdef DEBUG_OSL_FILE */
+/* perror("mount"); */
+/* #endif */
+/* } */
+
+
+ pszTmp = getenv("SAL_MOUNT_UMOUNTPROG");
+ if ( pszTmp != 0 )
+ {
+ pszUmountProg=pszTmp;
+ }
+
+ pszTmp = getenv("SAL_MOUNT_SU_DO");
+ if ( pszTmp != 0 )
+ {
+ pszSuDo=pszTmp;
+ }
+
+ if ( pszSuDo != 0 )
+ {
+ snprintf(pszCmd, sizeof(pszCmd), "%s %s %s",pszSuDo,pszUmountProg,pItem->pszMountPoint);
+ }
+ else
+ {
+ snprintf(pszCmd, sizeof(pszCmd), "%s %s",pszUmountProg,pItem->pszMountPoint);
+ }
+
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"executing '%s'\n",pszCmd);
+#endif
+
+ nRet = system(pszCmd);
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"call returned '%i'\n",nRet);
+ fprintf(stderr,"exit status is '%i'\n", WEXITSTATUS(nRet));
+#endif
+
+ switch ( WEXITSTATUS(nRet) )
+ {
+ case 0:
+ nRet=0;
+ break;
+
+ default:
+ nRet=EBUSY;
+ break;
+ }
+
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_unmountFloppy [ok]\n");
+#endif
+
+ return ((0 == nRet) ? oslTranslateFileError(OSL_FET_SUCCESS, nRet) : oslTranslateFileError(OSL_FET_ERROR, nRet));
+
+/* return osl_File_E_None;*/
+}
+
+#endif /* LINUX */
+
+#if defined(LINUX)
+static sal_Bool
+osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem)
+{
+ struct mntent* pMountEnt;
+ FILE* pMountTab;
+
+ pMountTab = setmntent (MOUNTTAB, "r");
+ if (pMountTab == 0)
+ return sal_False;
+
+ while ((pMountEnt = getmntent(pMountTab)) != 0)
+ {
+ if ( strncmp(pMountEnt->mnt_dir, pszPath, strlen(pMountEnt->mnt_dir)) == 0
+ && strncmp(pMountEnt->mnt_fsname, "/dev/fd", strlen("/dev/fd")) == 0)
+ {
+ memset(pItem->pszMountPoint, 0, sizeof(pItem->pszMountPoint));
+ strncpy(pItem->pszMountPoint, pMountEnt->mnt_dir, sizeof(pItem->pszMountPoint) - 1);
+
+ memset(pItem->pszFilePath, 0, sizeof(pItem->pszFilePath));
+ strncpy(pItem->pszFilePath, pMountEnt->mnt_dir, sizeof(pItem->pszFilePath) - 1);
+
+ memset(pItem->pszDevice, 0, sizeof(pItem->pszDevice));
+ strncpy(pItem->pszDevice, pMountEnt->mnt_fsname, sizeof(pItem->pszDevice) - 1);
+
+ endmntent (pMountTab);
+ return sal_True;
+ }
+ }
+
+ endmntent (pMountTab);
+ return sal_False;
+}
+#endif /* LINUX */
+
+#if defined(LINUX)
+static sal_Bool
+osl_isFloppyMounted (oslVolumeDeviceHandleImpl* pDevice)
+{
+ oslVolumeDeviceHandleImpl aItem;
+
+ if ( osl_getFloppyMountEntry (pDevice->pszMountPoint, &aItem)
+ && strcmp (aItem.pszMountPoint, pDevice->pszMountPoint) == 0
+ && strcmp (aItem.pszDevice, pDevice->pszDevice) == 0)
+ {
+ return sal_True;
+ }
+ return sal_False;
+}
+#endif /* LINUX */
+
+/* NetBSD floppy functions have to be added here. Until we have done that,
+ * we use the MACOSX definitions for nonexistent floppy.
+ * */
+
+/******************************************************************************
+ *
+ * MAC OS X FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+#if (defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath)
+{
+ return NULL;
+}
+#endif /* MACOSX */
+
+#if ( defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ return osl_File_E_BUSY;
+}
+#endif /* MACOSX */
+
+#if ( defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ return osl_File_E_BUSY;
+}
+#endif /* MACOSX */
+
+#if ( defined(NETBSD) || defined(FREEBSD) )
+static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem)
+{
+ return sal_False;
+}
+#endif /* NETBSD || FREEBSD */
+
+#if ( defined(NETBSD) || defined(FREEBSD) )
+static sal_Bool osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice)
+{
+ return sal_False;
+}
+#endif /* NETBSD || FREEBSD */
+
+
+#ifdef DEBUG_OSL_FILE
+static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* pItem)
+{
+ if (pItem == 0 )
+ {
+ fprintf(stderr,"NULL Handle\n");
+ return;
+ }
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Invalid Handle]\n");
+#endif
+ return;
+ }
+
+
+ fprintf(stderr,"MountPoint : '%s'\n",pItem->pszMountPoint);
+ fprintf(stderr,"FilePath : '%s'\n",pItem->pszFilePath);
+ fprintf(stderr,"Device : '%s'\n",pItem->pszDevice);
+
+ return;
+}
+#endif
diff --git a/sal/osl/unx/interlck.c b/sal/osl/unx/interlck.c
new file mode 100644
index 000000000000..0342cdd983b4
--- /dev/null
+++ b/sal/osl/unx/interlck.c
@@ -0,0 +1,170 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/interlck.h>
+#include <osl/diagnose.h>
+
+#if ( defined ( SOLARIS ) || defined ( NETBSD ) ) && defined ( SPARC )
+#error please use asm/interlck_sparc.s
+#elif defined ( SOLARIS) && defined ( X86 )
+#error please use asm/interlck_x86.s
+#elif defined ( GCC ) && ( defined ( X86 ) || defined ( X86_64 ) )
+/* That's possible on x86-64 too since oslInterlockedCount is a sal_Int32 */
+
+extern int osl_isSingleCPU;
+
+/*****************************************************************************/
+/* osl_incrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
+{
+ register oslInterlockedCount nCount asm("%eax");
+
+ nCount = 1;
+
+ if ( osl_isSingleCPU ) {
+ __asm__ __volatile__ (
+ "xaddl %0, %1\n\t"
+ : "+r" (nCount), "+m" (*pCount)
+ : /* nothing */
+ : "memory");
+ }
+ else {
+ __asm__ __volatile__ (
+ "lock\n\t"
+ "xaddl %0, %1\n\t"
+ : "+r" (nCount), "+m" (*pCount)
+ : /* nothing */
+ : "memory");
+ }
+
+ return ++nCount;
+}
+
+oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
+{
+ register oslInterlockedCount nCount asm("%eax");
+
+ nCount = -1;
+
+ if ( osl_isSingleCPU ) {
+ __asm__ __volatile__ (
+ "xaddl %0, %1\n\t"
+ : "+r" (nCount), "+m" (*pCount)
+ : /* nothing */
+ : "memory");
+ }
+ else {
+ __asm__ __volatile__ (
+ "lock\n\t"
+ "xaddl %0, %1\n\t"
+ : "+r" (nCount), "+m" (*pCount)
+ : /* nothing */
+ : "memory");
+ }
+
+ return --nCount;
+}
+
+#elif defined ( GCC ) && defined ( POWERPC )
+
+/*****************************************************************************/
+/* osl_incrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
+{
+ /* "addi" doesn't work with r0 as second parameter */
+ register oslInterlockedCount nCount __asm__ ("r4");
+
+ __asm__ __volatile__ (
+ "1: lwarx %0,0,%2\n\t"
+ " addi %0,%0,1\n\t"
+ " stwcx. %0,0,%2\n\t"
+ " bne- 1b\n\t"
+ " isync"
+ : "=&r" (nCount), "=m" (*pCount)
+ : "r" (pCount)
+ : "memory");
+
+ return nCount;
+}
+
+oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
+{
+ /* "subi" doesn't work with r0 as second parameter */
+ register oslInterlockedCount nCount __asm__ ("r4");
+
+ __asm__ __volatile__ (
+ "1: lwarx %0,0,%2\n\t"
+ " subi %0,%0,1\n\t"
+ " stwcx. %0,0,%2\n\t"
+ " bne- 1b\n\t"
+ " isync"
+ : "=&r" (nCount), "=m" (*pCount)
+ : "r" (pCount)
+ : "memory");
+
+ return nCount;
+}
+
+#else
+/* use only if nothing else works, expensive due to single mutex for all reference counts */
+
+static pthread_mutex_t InterLock = PTHREAD_MUTEX_INITIALIZER;
+
+/*****************************************************************************/
+/* osl_incrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
+{
+ oslInterlockedCount Count;
+
+ pthread_mutex_lock(&InterLock);
+ Count = ++(*pCount);
+ pthread_mutex_unlock(&InterLock);
+
+ return (Count);
+}
+
+/*****************************************************************************/
+/* osl_decrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
+{
+ oslInterlockedCount Count;
+
+ pthread_mutex_lock(&InterLock);
+ Count = --(*pCount);
+ pthread_mutex_unlock(&InterLock);
+
+ return (Count);
+}
+
+#endif /* default */
diff --git a/sal/osl/unx/makefile.mk b/sal/osl/unx/makefile.mk
new file mode 100644
index 000000000000..1dd47fb4d19b
--- /dev/null
+++ b/sal/osl/unx/makefile.mk
@@ -0,0 +1,189 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=sal
+.IF "$(WORK_STAMP)"=="MIX364"
+TARGET=cppsal
+.ELSE
+TARGET=cpposl
+.ENDIF
+USE_LDUMP2=TRUE
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=cont_pch
+PROJECTPCHSOURCE=cont_pch
+
+TARGETTYPE=CUI
+
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+CFLAGS+= $(LFS_CFLAGS)
+CXXFLAGS+= $(LFS_CFLAGS)
+
+# --- Files --------------------------------------------------------
+
+SLOFILES= \
+ $(SLO)$/conditn.obj \
+ $(SLO)$/diagnose.obj \
+ $(SLO)$/semaphor.obj \
+ $(SLO)$/socket.obj \
+ $(SLO)$/interlck.obj \
+ $(SLO)$/mutex.obj \
+ $(SLO)$/nlsupport.obj \
+ $(SLO)$/thread.obj \
+ $(SLO)$/module.obj \
+ $(SLO)$/process.obj \
+ $(SLO)$/security.obj \
+ $(SLO)$/profile.obj \
+ $(SLO)$/time.obj \
+ $(SLO)$/signal.obj \
+ $(SLO)$/pipe.obj \
+ $(SLO)$/system.obj \
+ $(SLO)$/util.obj \
+ $(SLO)$/tempfile.obj\
+ $(SLO)$/file.obj \
+ $(SLO)$/file_misc.obj\
+ $(SLO)$/file_url.obj\
+ $(SLO)$/file_error_transl.obj\
+ $(SLO)$/file_path_helper.obj\
+ $(SLO)$/file_stat.obj \
+ $(SLO)$/file_volume.obj \
+ $(SLO)$/uunxapi.obj\
+ $(SLO)$/process_impl.obj\
+ $(SLO)$/salinit.obj
+
+
+#.IF "$(UPDATER)"=="YES"
+OBJFILES= $(OBJ)$/conditn.obj \
+ $(OBJ)$/diagnose.obj \
+ $(OBJ)$/semaphor.obj \
+ $(OBJ)$/socket.obj \
+ $(OBJ)$/interlck.obj \
+ $(OBJ)$/mutex.obj \
+ $(OBJ)$/nlsupport.obj \
+ $(OBJ)$/thread.obj \
+ $(OBJ)$/module.obj \
+ $(OBJ)$/process.obj \
+ $(OBJ)$/security.obj \
+ $(OBJ)$/profile.obj \
+ $(OBJ)$/time.obj \
+ $(OBJ)$/signal.obj \
+ $(OBJ)$/pipe.obj \
+ $(OBJ)$/system.obj \
+ $(OBJ)$/util.obj \
+ $(OBJ)$/tempfile.obj\
+ $(OBJ)$/file.obj \
+ $(OBJ)$/file_misc.obj\
+ $(OBJ)$/file_url.obj\
+ $(OBJ)$/file_error_transl.obj\
+ $(OBJ)$/file_path_helper.obj\
+ $(OBJ)$/file_stat.obj \
+ $(OBJ)$/file_volume.obj \
+ $(OBJ)$/uunxapi.obj\
+ $(OBJ)$/process_impl.obj\
+ $(OBJ)$/salinit.obj
+
+#.ENDIF
+
+.IF "$(OS)"=="MACOSX"
+SLOFILES += $(SLO)$/osxlocale.obj
+.ENDIF
+
+.IF "$(OS)"=="SOLARIS" || "$(OS)"=="FREEBSD" || "$(OS)"=="NETBSD" || "$(OS)$(CPU)"=="LINUXS" || "$(OS)"=="MACOSX"
+SLOFILES += $(SLO)$/backtrace.obj
+OBJFILES += $(OBJ)$/backtrace.obj
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.IF "$(COM)"=="C50"
+APP1STDLIBS+=-lC
+.ENDIF
+
+.IF "$(OS)" == "LINUX"
+.IF "$(PAM)" == "NO"
+CFLAGS+=-DNOPAM
+.IF "$(NEW_SHADOW_API)" == "YES"
+CFLAGS+=-DNEW_SHADOW_API
+.ENDIF
+.ENDIF
+.IF "$(PAM_LINK)" == "YES"
+CFLAGS+=-DPAM_LINK
+.ENDIF
+.IF "$(CRYPT_LINK)" == "YES"
+CFLAGS+=-DCRYPT_LINK
+.ENDIF
+.ENDIF
+
+.IF "$(ENABLE_CRASHDUMP)" != "" || "$(PRODUCT)" == ""
+CFLAGS+=-DSAL_ENABLE_CRASH_REPORT
+.ENDIF
+
+.INCLUDE : target.mk
+
+.IF "$(OS)$(CPU)"=="SOLARISU" || "$(OS)$(CPU)"=="SOLARISS" || "$(OS)$(CPU)"=="NETBSDS" || "$(OS)$(CPU)"=="LINUXS"
+
+$(SLO)$/interlck.obj: $(SLO)$/interlck.o
+ touch $(SLO)$/interlck.obj
+
+$(OBJ)$/interlck.obj: $(OBJ)$/interlck.o
+ touch $(OBJ)$/interlck.obj
+
+$(SLO)$/interlck.o: $(MISC)$/interlck_sparc.s
+ $(ASM) $(AFLAGS) -o $@ $<
+
+$(OBJ)$/interlck.o: $(MISC)$/interlck_sparc.s
+ $(ASM) $(AFLAGS) -o $@ $<
+
+$(MISC)$/interlck_sparc.s: asm/interlck_sparc.s
+ tr -d "\015" < $< > $@
+
+.ENDIF
+
+.IF "$(OS)$(CPU)"=="SOLARISI"
+
+$(SLO)$/interlck.obj: $(SLO)$/interlck.o
+ touch $(SLO)$/interlck.obj
+
+$(OBJ)$/interlck.obj: $(OBJ)$/interlck.o
+ touch $(OBJ)$/interlck.obj
+
+$(SLO)$/interlck.o: $(MISC)$/interlck_x86.s
+ $(ASM) $(AFLAGS) -o $@ $<
+
+$(OBJ)$/interlck.o: $(MISC)$/interlck_x86.s
+ $(ASM) $(AFLAGS) -o $@ $<
+
+$(MISC)$/interlck_x86.s: asm/interlck_x86.s
+ tr -d "\015" < $< > $@
+
+.ENDIF
diff --git a/sal/osl/unx/module.c b/sal/osl/unx/module.c
new file mode 100644
index 000000000000..8f8f76a8656c
--- /dev/null
+++ b/sal/osl/unx/module.c
@@ -0,0 +1,242 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <sal/types.h>
+#include <osl/diagnose.h>
+#include <osl/module.h>
+#include <osl/thread.h>
+#include <osl/process.h>
+#include <osl/file.h>
+
+#include "system.h"
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+/* implemented in file.c */
+extern int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32);
+
+oslModule SAL_CALL osl_psz_loadModule(const sal_Char *pszModuleName, sal_Int32 nRtldMode);
+
+/*****************************************************************************/
+/* osl_loadModule */
+/*****************************************************************************/
+
+oslModule SAL_CALL osl_loadModule(rtl_uString *ustrModuleName, sal_Int32 nRtldMode)
+{
+ oslModule pModule=0;
+ rtl_uString* ustrTmp = NULL;
+
+ OSL_ENSURE(ustrModuleName,"osl_loadModule : string is not valid");
+
+ /* ensure ustrTmp hold valid string */
+ if (osl_File_E_None != osl_getSystemPathFromFileURL(ustrModuleName, &ustrTmp))
+ rtl_uString_assign(&ustrTmp, ustrModuleName);
+
+ if (ustrTmp)
+ {
+ char buffer[PATH_MAX];
+
+ if (UnicodeToText(buffer, PATH_MAX, ustrTmp->buffer, ustrTmp->length))
+ pModule = osl_psz_loadModule(buffer, nRtldMode);
+ rtl_uString_release(ustrTmp);
+ }
+
+ return pModule;
+}
+
+/*****************************************************************************/
+/* osl_psz_loadModule */
+/*****************************************************************************/
+
+oslModule SAL_CALL osl_psz_loadModule(const sal_Char *pszModuleName, sal_Int32 nRtldMode)
+{
+ OSL_ASSERT(
+ (nRtldMode & SAL_LOADMODULE_LAZY) == 0 ||
+ (nRtldMode & SAL_LOADMODULE_NOW) == 0); /* only either LAZY or NOW */
+ if (pszModuleName)
+ {
+#ifndef NO_DL_FUNCTIONS
+ int rtld_mode =
+ ((nRtldMode & SAL_LOADMODULE_NOW) ? RTLD_NOW : RTLD_LAZY) |
+ ((nRtldMode & SAL_LOADMODULE_GLOBAL) ? RTLD_GLOBAL : RTLD_LOCAL);
+ void* pLib = dlopen(pszModuleName, rtld_mode);
+
+#if OSL_DEBUG_LEVEL > 1
+ if (pLib == 0)
+ OSL_TRACE("Error osl_loadModule: %s\n", dlerror());
+#endif /* OSL_DEBUG_LEVEL */
+
+ return ((oslModule)(pLib));
+
+#else /* NO_DL_FUNCTIONS */
+ printf("No DL Functions\n");
+#endif /* NO_DL_FUNCTIONS */
+ }
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_getModuleHandle */
+/*****************************************************************************/
+
+sal_Bool SAL_CALL
+osl_getModuleHandle(rtl_uString *pModuleName, oslModule *pResult)
+{
+ (void) pModuleName; /* avoid warning about unused parameter */
+ *pResult = (oslModule) RTLD_DEFAULT;
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_unloadModule */
+/*****************************************************************************/
+void SAL_CALL osl_unloadModule(oslModule hModule)
+{
+ if (hModule)
+ {
+#ifndef NO_DL_FUNCTIONS
+ int nRet = dlclose(hModule);
+
+#if OSL_DEBUG_LEVEL > 1
+ if (nRet != 0)
+ {
+ fprintf(stderr, "Error osl_unloadModule: %s\n", dlerror());
+ }
+#else
+ (void) nRet;
+#endif /* if OSL_DEBUG_LEVEL */
+
+#endif /* ifndef NO_DL_FUNCTIONS */
+ }
+}
+
+/*****************************************************************************/
+/* osl_getSymbol */
+/*****************************************************************************/
+void* SAL_CALL
+osl_getSymbol(oslModule Module, rtl_uString* pSymbolName)
+{
+ return (void *) osl_getFunctionSymbol(Module, pSymbolName);
+}
+
+
+/*****************************************************************************/
+/* osl_getAsciiFunctionSymbol */
+/*****************************************************************************/
+oslGenericFunction SAL_CALL
+osl_getAsciiFunctionSymbol(oslModule Module, const sal_Char *pSymbol)
+{
+ void *fcnAddr = NULL;
+
+#ifndef NO_DL_FUNCTIONS
+ if (pSymbol)
+ {
+ fcnAddr = dlsym(Module, pSymbol);
+
+ if (!fcnAddr)
+ OSL_TRACE("Error osl_getAsciiFunctionSymbol: %s\n", dlerror());
+ }
+#endif
+
+ return (oslGenericFunction) fcnAddr;
+}
+
+/*****************************************************************************/
+/* osl_getFunctionSymbol */
+/*****************************************************************************/
+oslGenericFunction SAL_CALL
+osl_getFunctionSymbol(oslModule module, rtl_uString *puFunctionSymbolName)
+{
+ oslGenericFunction pSymbol = NULL;
+
+ if( puFunctionSymbolName )
+ {
+ rtl_String* pSymbolName = NULL;
+
+ rtl_uString2String( &pSymbolName,
+ rtl_uString_getStr(puFunctionSymbolName),
+ rtl_uString_getLength(puFunctionSymbolName),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ if( pSymbolName != NULL )
+ {
+ pSymbol = osl_getAsciiFunctionSymbol(module, rtl_string_getStr(pSymbolName));
+ rtl_string_release(pSymbolName);
+ }
+ }
+
+ return pSymbol;
+}
+
+/*****************************************************************************/
+/* osl_getModuleURLFromAddress */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_getModuleURLFromAddress(void * addr, rtl_uString ** ppLibraryUrl)
+{
+ sal_Bool result = sal_False;
+ Dl_info dl_info;
+
+ if ((result = dladdr(addr, &dl_info)) != 0)
+ {
+ rtl_uString * workDir = NULL;
+ osl_getProcessWorkingDir(&workDir);
+ if (workDir)
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_TRACE("module.c::osl_getModuleURLFromAddress - %s\n", dl_info.dli_fname);
+#endif
+ rtl_string2UString(ppLibraryUrl,
+ dl_info.dli_fname,
+ strlen(dl_info.dli_fname),
+ osl_getThreadTextEncoding(),
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+
+ OSL_ASSERT(*ppLibraryUrl != NULL);
+ osl_getFileURLFromSystemPath(*ppLibraryUrl, ppLibraryUrl);
+ osl_getAbsoluteFileURL(workDir, *ppLibraryUrl, ppLibraryUrl);
+
+ rtl_uString_release(workDir);
+ result = sal_True;
+ }
+ else
+ {
+ result = sal_False;
+ }
+ }
+ return result;
+}
+
+/*****************************************************************************/
+/* osl_getModuleURLFromFunctionAddress */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress(oslGenericFunction addr, rtl_uString ** ppLibraryUrl)
+{
+ return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
+}
diff --git a/sal/osl/unx/mutex.c b/sal/osl/unx/mutex.c
new file mode 100644
index 000000000000..2f47ba8791ad
--- /dev/null
+++ b/sal/osl/unx/mutex.c
@@ -0,0 +1,221 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/mutex.h>
+#include <osl/diagnose.h>
+
+#include <pthread.h>
+#include <stdlib.h>
+
+#if defined LINUX /* bad hack */
+int pthread_mutexattr_setkind_np(pthread_mutexattr_t *, int);
+#define pthread_mutexattr_settype pthread_mutexattr_setkind_np
+#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
+#endif
+
+/*
+ Implementation notes:
+ oslMutex hides a pointer to the oslMutexImpl structure, which
+ ist needed to manage recursive locks on a mutex.
+
+*/
+
+typedef struct _oslMutexImpl
+{
+ pthread_mutex_t mutex;
+} oslMutexImpl;
+
+
+/*****************************************************************************/
+/* osl_createMutex */
+/*****************************************************************************/
+oslMutex SAL_CALL osl_createMutex()
+{
+ oslMutexImpl* pMutex = (oslMutexImpl*) malloc(sizeof(oslMutexImpl));
+ pthread_mutexattr_t aMutexAttr;
+ int nRet=0;
+
+ OSL_ASSERT(pMutex);
+
+ if ( pMutex == 0 )
+ {
+ return 0;
+ }
+
+ pthread_mutexattr_init(&aMutexAttr);
+
+ nRet = pthread_mutexattr_settype(&aMutexAttr, PTHREAD_MUTEX_RECURSIVE);
+
+ nRet = pthread_mutex_init(&(pMutex->mutex), &aMutexAttr);
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_createMutex : mutex init failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+
+ free(pMutex);
+ pMutex = 0;
+ }
+
+ pthread_mutexattr_destroy(&aMutexAttr);
+
+ return (oslMutex) pMutex;
+}
+
+/*****************************************************************************/
+/* osl_destroyMutex */
+/*****************************************************************************/
+void SAL_CALL osl_destroyMutex(oslMutex Mutex)
+{
+ oslMutexImpl* pMutex = (oslMutexImpl*) Mutex;
+
+ OSL_ASSERT(pMutex);
+
+ if ( pMutex != 0 )
+ {
+ int nRet=0;
+
+ nRet = pthread_mutex_destroy(&(pMutex->mutex));
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_destroyMutex : mutex destroy failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ }
+
+ free(pMutex);
+ }
+
+ return;
+}
+
+/*****************************************************************************/
+/* osl_acquireMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_acquireMutex(oslMutex Mutex)
+{
+ oslMutexImpl* pMutex = (oslMutexImpl*) Mutex;
+
+ OSL_ASSERT(pMutex);
+
+ if ( pMutex != 0 )
+ {
+ int nRet=0;
+
+ nRet = pthread_mutex_lock(&(pMutex->mutex));
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_acquireMutex : mutex lock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ return sal_False;
+ }
+ return sal_True;
+ }
+
+ /* not initialized */
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_tryToAcquireMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_tryToAcquireMutex(oslMutex Mutex)
+{
+ oslMutexImpl* pMutex = (oslMutexImpl*) Mutex;
+
+ OSL_ASSERT(pMutex);
+
+ if ( pMutex )
+ {
+ int nRet = 0;
+ nRet = pthread_mutex_trylock(&(pMutex->mutex));
+ if ( nRet != 0 )
+ return sal_False;
+
+ return sal_True;
+ }
+
+ /* not initialized */
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_releaseMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_releaseMutex(oslMutex Mutex)
+{
+ oslMutexImpl* pMutex = (oslMutexImpl*) Mutex;
+
+ OSL_ASSERT(pMutex);
+
+ if ( pMutex )
+ {
+ int nRet=0;
+ nRet = pthread_mutex_unlock(&(pMutex->mutex));
+ if ( nRet != 0 )
+ {
+ OSL_TRACE("osl_releaseMutex : mutex unlock failed. Errno: %d; %s\n",
+ nRet, strerror(nRet));
+ return sal_False;
+ }
+
+ return sal_True;
+ }
+
+ /* not initialized */
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_getGlobalMutex */
+/*****************************************************************************/
+
+static oslMutexImpl globalMutexImpl;
+
+static void globalMutexInitImpl(void) {
+ pthread_mutexattr_t attr;
+ if (pthread_mutexattr_init(&attr) != 0 ||
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) ||
+ pthread_mutex_init(&globalMutexImpl.mutex, &attr) != 0 ||
+ pthread_mutexattr_destroy(&attr) != 0)
+ {
+ abort();
+ }
+}
+
+oslMutex * SAL_CALL osl_getGlobalMutex()
+{
+ /* necessary to get a "oslMutex *" */
+ static oslMutex globalMutex = (oslMutex) &globalMutexImpl;
+
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
+ if (pthread_once(&once, &globalMutexInitImpl) != 0) {
+ abort();
+ }
+
+ return &globalMutex;
+}
diff --git a/sal/osl/unx/nlsupport.c b/sal/osl/unx/nlsupport.c
new file mode 100644
index 000000000000..c9f4fd18df21
--- /dev/null
+++ b/sal/osl/unx/nlsupport.c
@@ -0,0 +1,949 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <osl/nlsupport.h>
+#include <osl/diagnose.h>
+#include <osl/process.h>
+#include <rtl/memory.h>
+
+#if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD) || defined(MACOSX)
+#include <pthread.h>
+#ifndef MACOSX
+ #include <locale.h>
+ #include <langinfo.h>
+#else
+#include <osl/module.h>
+#include <osl/thread.h>
+#endif /* !MACOSX */
+#endif /* LINUX || SOLARIS || NETBSD || MACOSX */
+
+#include <string.h>
+
+/*****************************************************************************
+ typedefs
+ *****************************************************************************/
+
+
+typedef struct {
+ const char *key;
+ const rtl_TextEncoding value;
+} _pair;
+
+
+/*****************************************************************************
+ compare function for binary search
+ *****************************************************************************/
+
+static int
+_pair_compare (const char *key, const _pair *pair)
+{
+ int result = rtl_str_compareIgnoreAsciiCase( key, pair->key );
+ return result;
+}
+
+/*****************************************************************************
+ binary search on encoding tables
+ *****************************************************************************/
+
+static const _pair*
+_pair_search (const char *key, const _pair *base, unsigned int member )
+{
+ unsigned int lower = 0;
+ unsigned int upper = member;
+ unsigned int current;
+ int comparison;
+
+ /* check for validity of input */
+ if ( (key == NULL) || (base == NULL) || (member == 0) )
+ return NULL;
+
+ /* binary search */
+ while ( lower < upper )
+ {
+ current = (lower + upper) / 2;
+ comparison = _pair_compare( key, base + current );
+ if (comparison < 0)
+ upper = current;
+ else if (comparison > 0)
+ lower = current + 1;
+ else
+ return base + current;
+ }
+
+ return NULL;
+}
+
+
+/*****************************************************************************
+ convert rtl_Locale to locale string
+ *****************************************************************************/
+
+static char * _compose_locale( rtl_Locale * pLocale, char * buffer, size_t n )
+{
+ /* check if a valid locale is specified */
+ if( pLocale && pLocale->Language &&
+ (pLocale->Language->length == 2 || pLocale->Language->length == 3) )
+ {
+ size_t offset = 0;
+
+ /* convert language code to ascii */
+ {
+ rtl_String *pLanguage = NULL;
+
+ rtl_uString2String( &pLanguage,
+ pLocale->Language->buffer, pLocale->Language->length,
+ RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ if( SAL_INT_CAST(sal_uInt32, pLanguage->length) < n )
+ {
+ strcpy( buffer, pLanguage->buffer );
+ offset = pLanguage->length;
+ }
+
+ rtl_string_release( pLanguage );
+ }
+
+ /* convert country code to ascii */
+ if( pLocale->Country && (pLocale->Country->length == 2) )
+ {
+ rtl_String *pCountry = NULL;
+
+ rtl_uString2String( &pCountry,
+ pLocale->Country->buffer, pLocale->Country->length,
+ RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ if( offset + pCountry->length + 1 < n )
+ {
+ strcpy( buffer + offset++, "_" );
+ strcpy( buffer + offset, pCountry->buffer );
+ offset += pCountry->length;
+ }
+
+ rtl_string_release( pCountry );
+ }
+
+ /* convert variant to ascii - check if there is enough space for the variant string */
+ if( pLocale->Variant && pLocale->Variant->length &&
+ ( SAL_INT_CAST(sal_uInt32, pLocale->Variant->length) < n - 6 ) )
+ {
+ rtl_String *pVariant = NULL;
+
+ rtl_uString2String( &pVariant,
+ pLocale->Variant->buffer, pLocale->Variant->length,
+ RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ if( offset + pVariant->length + 1 < n )
+ {
+ strcpy( buffer + offset, pVariant->buffer );
+ offset += pVariant->length;
+ }
+
+ rtl_string_release( pVariant );
+ }
+
+ return buffer;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************
+ convert locale string to rtl_Locale
+ *****************************************************************************/
+
+static rtl_Locale * _parse_locale( const char * locale )
+{
+ static sal_Unicode c_locale[2] = { (sal_Unicode) 'C', 0 };
+
+ /* check if locale contains a valid string */
+ if( locale )
+ {
+ size_t len = strlen( locale );
+
+ if( len >= 2 )
+ {
+ rtl_uString * pLanguage = NULL;
+ rtl_uString * pCountry = NULL;
+ rtl_uString * pVariant = NULL;
+
+ size_t offset = 2;
+
+ rtl_Locale * ret;
+
+ /* language is a two or three letter code */
+ if( (len > 3 && '_' == locale[3]) || (len == 3 && '_' != locale[2]) )
+ offset = 3;
+
+ /* convert language code to unicode */
+ rtl_string2UString( &pLanguage, locale, offset, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(pLanguage != NULL);
+
+ /* convert country code to unicode */
+ if( len >= offset+3 && '_' == locale[offset] )
+ {
+ rtl_string2UString( &pCountry, locale + offset + 1, 2, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(pCountry != NULL);
+ offset += 3;
+ }
+
+ /* convert variant code to unicode - do not rely on "." as delimiter */
+ if( len > offset ) {
+ rtl_string2UString( &pVariant, locale + offset, len - offset, RTL_TEXTENCODING_ASCII_US, OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(pVariant != NULL);
+ }
+
+ ret = rtl_locale_register( pLanguage->buffer, pCountry ? pCountry->buffer : c_locale + 1, pVariant ? pVariant->buffer : c_locale + 1 );
+
+ if (pVariant) rtl_uString_release(pVariant);
+ if (pCountry) rtl_uString_release(pCountry);
+ if (pLanguage) rtl_uString_release(pLanguage);
+
+ return ret;
+ }
+ else
+ return rtl_locale_register( c_locale, c_locale + 1, c_locale + 1 );
+ }
+
+ return NULL;
+}
+
+#if defined(LINUX) || defined(SOLARIS) || defined(NETBSD) || defined(FREEBSD)
+
+/*
+ * This implementation of osl_getTextEncodingFromLocale maps
+ * from nl_langinfo(CODESET) to rtl_textencoding defines.
+ * nl_langinfo() is supported only on Linux, Solaris,
+ * >= NetBSD 1.6 and >= FreeBSD 4.4
+ *
+ * This routine is SLOW because of the setlocale call, so
+ * grab the result and cache it.
+ *
+ * XXX this code has the usual mt problems aligned with setlocale() XXX
+ */
+
+#ifdef LINUX
+#if !defined(CODESET)
+#define CODESET _NL_CTYPE_CODESET_NAME
+#endif
+#endif
+
+/*
+ * _nl_language_list[] is an array list of supported encodings. Because
+ * we are using a binary search, the list has to be in ascending order.
+ * We are comparing the encodings case insensitiv, so the list has
+ * to be completly upper- , or lowercase.
+ */
+
+#if defined(SOLARIS)
+
+/* The values in the below list can be obtained with a script like
+ * #!/bin/sh
+ * for i in `locale -a`; do
+ * LC_ALL=$i locale -k code_set_name
+ * done
+ */
+const _pair _nl_language_list[] = {
+ { "5601", RTL_TEXTENCODING_EUC_KR }, /* ko_KR.EUC */
+ { "646", RTL_TEXTENCODING_ISO_8859_1 }, /* fake: ASCII_US */
+ { "ANSI-1251", RTL_TEXTENCODING_MS_1251 }, /* ru_RU.ANSI1251 */
+ { "BIG5", RTL_TEXTENCODING_BIG5 }, /* zh_CN.BIG5 */
+ { "BIG5-HKSCS", RTL_TEXTENCODING_BIG5_HKSCS }, /* zh_CN.BIG5HK */
+ { "CNS11643", RTL_TEXTENCODING_EUC_TW }, /* zh_TW.EUC */
+ { "EUCJP", RTL_TEXTENCODING_EUC_JP }, /* ja_JP.eucjp */
+ { "GB18030", RTL_TEXTENCODING_GB_18030 }, /* zh_CN.GB18030 */
+ { "GB2312", RTL_TEXTENCODING_GB_2312 }, /* zh_CN */
+ { "GBK", RTL_TEXTENCODING_GBK }, /* zh_CN.GBK */
+ { "ISO8859-1", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ISO8859-10", RTL_TEXTENCODING_ISO_8859_10 },
+ { "ISO8859-13", RTL_TEXTENCODING_ISO_8859_13 }, /* lt_LT lv_LV */
+ { "ISO8859-14", RTL_TEXTENCODING_ISO_8859_14 },
+ { "ISO8859-15", RTL_TEXTENCODING_ISO_8859_15 },
+ { "ISO8859-2", RTL_TEXTENCODING_ISO_8859_2 },
+ { "ISO8859-3", RTL_TEXTENCODING_ISO_8859_3 },
+ { "ISO8859-4", RTL_TEXTENCODING_ISO_8859_4 },
+ { "ISO8859-5", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ISO8859-6", RTL_TEXTENCODING_ISO_8859_6 },
+ { "ISO8859-7", RTL_TEXTENCODING_ISO_8859_7 },
+ { "ISO8859-8", RTL_TEXTENCODING_ISO_8859_8 },
+ { "ISO8859-9", RTL_TEXTENCODING_ISO_8859_9 },
+ { "KOI8-R", RTL_TEXTENCODING_KOI8_R },
+ { "KOI8-U", RTL_TEXTENCODING_KOI8_U },
+ { "PCK", RTL_TEXTENCODING_MS_932 },
+ { "SUN_EU_GREEK", RTL_TEXTENCODING_ISO_8859_7 }, /* 8859-7 + Euro */
+ { "TIS620.2533", RTL_TEXTENCODING_MS_874 }, /* th_TH.TIS620 */
+ { "UTF-8", RTL_TEXTENCODING_UTF8 }
+};
+
+/* XXX MS-874 is an extension to tis620, so this is not
+ * really equivalent */
+
+#elif defined(LINUX) || defined(NETBSD)
+
+const _pair _nl_language_list[] = {
+ { "ANSI_X3.110-1983", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-99 NAPLPS */
+ { "ANSI_X3.4-1968", RTL_TEXTENCODING_ISO_8859_1 }, /* fake: ASCII_US */
+ { "ASMO_449", RTL_TEXTENCODING_DONTKNOW }, /* ISO_9036 ARABIC7 */
+ { "BALTIC", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-179 */
+ { "BIG5", RTL_TEXTENCODING_BIG5 }, /* locale: zh_TW */
+ { "BIG5-HKSCS", RTL_TEXTENCODING_BIG5_HKSCS }, /* locale: zh_CN.BIG5HK */
+ { "BIG5HKSCS", RTL_TEXTENCODING_BIG5_HKSCS }, /* depricated */
+ { "BS_4730", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-4 ISO646-GB */
+ { "BS_VIEWDATA", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-47 */
+ { "CP1250", RTL_TEXTENCODING_MS_1250 }, /* MS-EE */
+ { "CP1251", RTL_TEXTENCODING_MS_1251 }, /* MS-CYRL */
+ { "CP1252", RTL_TEXTENCODING_MS_1252 }, /* MS-ANSI */
+ { "CP1253", RTL_TEXTENCODING_MS_1253 }, /* MS-GREEK */
+ { "CP1254", RTL_TEXTENCODING_MS_1254 }, /* MS-TURK */
+ { "CP1255", RTL_TEXTENCODING_MS_1255 }, /* MS-HEBR */
+ { "CP1256", RTL_TEXTENCODING_MS_1256 }, /* MS-ARAB */
+ { "CP1257", RTL_TEXTENCODING_MS_1257 }, /* WINBALTRIM */
+ { "CSA_Z243.4-1985-1", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-121 */
+ { "CSA_Z243.4-1985-2", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-122 CSA7-2 */
+ { "CSA_Z243.4-1985-GR", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-123 */
+ { "CSN_369103", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-139 */
+ { "CWI", RTL_TEXTENCODING_DONTKNOW }, /* CWI-2 CP-HU */
+ { "DEC-MCS", RTL_TEXTENCODING_DONTKNOW }, /* DEC */
+ { "DIN_66003", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-21 */
+ { "DS_2089", RTL_TEXTENCODING_DONTKNOW }, /* DS2089 ISO646-DK */
+ { "EBCDIC-AT-DE", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-AT-DE-A", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-CA-FR", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-DK-NO", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-DK-NO-A", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-ES", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-ES-A", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-ES-S", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-FI-SE", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-FI-SE-A", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-FR", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-IS-FRISS", RTL_TEXTENCODING_DONTKNOW }, /* FRISS */
+ { "EBCDIC-IT", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-PT", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-UK", RTL_TEXTENCODING_DONTKNOW },
+ { "EBCDIC-US", RTL_TEXTENCODING_DONTKNOW },
+ { "ECMA-CYRILLIC", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-111 */
+ { "ES", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-17 */
+ { "ES2", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-85 */
+ { "EUC-JP", RTL_TEXTENCODING_EUC_JP }, /* locale: ja_JP.eucjp */
+ { "EUC-KR", RTL_TEXTENCODING_EUC_KR }, /* locale: ko_KR.euckr */
+ { "EUC-TW", RTL_TEXTENCODING_EUC_TW }, /* locale: zh_TW.euctw */
+ { "GB18030", RTL_TEXTENCODING_GB_18030 }, /* locale: zh_CN.gb18030 */
+ { "GB2312", RTL_TEXTENCODING_GB_2312 }, /* locale: zh_CN */
+ { "GB_1988-80", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-57 */
+ { "GBK", RTL_TEXTENCODING_GBK }, /* locale: zh_CN.GBK */
+ { "GOST_19768-74", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-153 */
+ { "GREEK-CCITT", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-150 */
+ { "GREEK7", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-88 */
+ { "GREEK7-OLD", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-18 */
+ { "HP-ROMAN8", RTL_TEXTENCODING_DONTKNOW }, /* ROMAN8 R8 */
+ { "IBM037", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-[US|CA|WT] */
+ { "IBM038", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-INT CP038 */
+ { "IBM1004", RTL_TEXTENCODING_DONTKNOW }, /* CP1004 OS2LATIN1 */
+ { "IBM1026", RTL_TEXTENCODING_DONTKNOW }, /* CP1026 1026 */
+ { "IBM1047", RTL_TEXTENCODING_DONTKNOW }, /* CP1047 1047 */
+ { "IBM256", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-INT1 */
+ { "IBM273", RTL_TEXTENCODING_DONTKNOW }, /* CP273 */
+ { "IBM274", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-BE CP274 */
+ { "IBM275", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-BR CP275 */
+ { "IBM277", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-CP-[DK|NO] */
+ { "IBM278", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-CP-[FISE]*/
+ { "IBM280", RTL_TEXTENCODING_DONTKNOW }, /* CP280 EBCDIC-CP-IT*/
+ { "IBM281", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-JP-E CP281 */
+ { "IBM284", RTL_TEXTENCODING_DONTKNOW }, /* CP284 EBCDIC-CP-ES */
+ { "IBM285", RTL_TEXTENCODING_DONTKNOW }, /* CP285 EBCDIC-CP-GB */
+ { "IBM290", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-JP-KANA */
+ { "IBM297", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-CP-FR */
+ { "IBM420", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-CP-AR1 */
+ { "IBM423", RTL_TEXTENCODING_DONTKNOW }, /* CP423 EBCDIC-CP-GR */
+ { "IBM424", RTL_TEXTENCODING_DONTKNOW }, /* CP424 EBCDIC-CP-HE */
+ { "IBM437", RTL_TEXTENCODING_IBM_437 }, /* CP437 437 */
+ { "IBM500", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-CP-[BE|CH] */
+ { "IBM850", RTL_TEXTENCODING_IBM_850 }, /* CP850 850 */
+ { "IBM851", RTL_TEXTENCODING_DONTKNOW }, /* CP851 851 */
+ { "IBM852", RTL_TEXTENCODING_IBM_852 }, /* CP852 852 */
+ { "IBM855", RTL_TEXTENCODING_IBM_855 }, /* CP855 855 */
+ { "IBM857", RTL_TEXTENCODING_IBM_857 }, /* CP857 857 */
+ { "IBM860", RTL_TEXTENCODING_IBM_860 }, /* CP860 860 */
+ { "IBM861", RTL_TEXTENCODING_IBM_861 }, /* CP861 861 CP-IS */
+ { "IBM862", RTL_TEXTENCODING_IBM_862 }, /* CP862 862 */
+ { "IBM863", RTL_TEXTENCODING_IBM_863 }, /* CP863 863 */
+ { "IBM864", RTL_TEXTENCODING_IBM_864 }, /* CP864 */
+ { "IBM865", RTL_TEXTENCODING_IBM_865 }, /* CP865 865 */
+ { "IBM866", RTL_TEXTENCODING_IBM_866 }, /* CP866 866 */
+ { "IBM868", RTL_TEXTENCODING_DONTKNOW }, /* CP868 CP-AR */
+ { "IBM869", RTL_TEXTENCODING_IBM_869 }, /* CP869 869 CP-GR */
+ { "IBM870", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-[ROECE|YU] */
+ { "IBM871", RTL_TEXTENCODING_DONTKNOW }, /* CP871 EBCDIC-CP-IS */
+ { "IBM875", RTL_TEXTENCODING_DONTKNOW }, /* CP875 EBCDIC-GREEK */
+ { "IBM880", RTL_TEXTENCODING_DONTKNOW }, /* EBCDIC-CYRILLIC */
+ { "IBM891", RTL_TEXTENCODING_DONTKNOW }, /* CP891 */
+ { "IBM903", RTL_TEXTENCODING_DONTKNOW }, /* CP903 */
+ { "IBM904", RTL_TEXTENCODING_DONTKNOW }, /* CP904 904 */
+ { "IBM905", RTL_TEXTENCODING_DONTKNOW }, /* CP905 EBCDIC-CP-TR */
+ { "IBM918", RTL_TEXTENCODING_DONTKNOW }, /* CP918 EBCDIC-AR2 */
+ { "IEC_P27-1", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-143 */
+ { "INIS", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-49 */
+ { "INIS-8", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-50 */
+ { "INIS-CYRILLIC", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-51 */
+ { "INVARIANT", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-170 */
+ { "ISO-8859-1", RTL_TEXTENCODING_ISO_8859_1 }, /* ISO-IR-100 CP819 */
+ { "ISO-8859-10", RTL_TEXTENCODING_ISO_8859_10 }, /* ISO-IR-157 LATIN6 */
+ { "ISO-8859-13", RTL_TEXTENCODING_ISO_8859_13 }, /* ISO-IR-179 LATIN7 */
+ { "ISO-8859-14", RTL_TEXTENCODING_ISO_8859_14 }, /* LATIN8 L8 */
+ { "ISO-8859-15", RTL_TEXTENCODING_ISO_8859_15 },
+ { "ISO-8859-2", RTL_TEXTENCODING_ISO_8859_2 }, /* LATIN2 L2 */
+ { "ISO-8859-3", RTL_TEXTENCODING_ISO_8859_3 }, /* LATIN3 L3 */
+ { "ISO-8859-4", RTL_TEXTENCODING_ISO_8859_4 }, /* LATIN4 L4 */
+ { "ISO-8859-5", RTL_TEXTENCODING_ISO_8859_5 }, /* CYRILLIC */
+ { "ISO-8859-6", RTL_TEXTENCODING_ISO_8859_6 }, /* ECMA-114 ARABIC */
+ { "ISO-8859-7", RTL_TEXTENCODING_ISO_8859_7 }, /* ECMA-118 GREEK8 */
+ { "ISO-8859-8", RTL_TEXTENCODING_ISO_8859_8 }, /* ISO_8859-8 HEBREW */
+ { "ISO-8859-9", RTL_TEXTENCODING_ISO_8859_9 }, /* ISO_8859-9 LATIN5 */
+ { "ISO-IR-90", RTL_TEXTENCODING_DONTKNOW }, /* ISO_6937-2:1983 */
+ { "ISO_10367-BOX", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-155 */
+ { "ISO_2033-1983", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-98 E13B */
+ { "ISO_5427", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-37 KOI-7 */
+ { "ISO_5427-EXT", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-54 */
+ { "ISO_5428", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-55 */
+ { "ISO_646.BASIC", RTL_TEXTENCODING_ASCII_US }, /* REF */
+ { "ISO_646.IRV", RTL_TEXTENCODING_ASCII_US }, /* ISO-IR-2 IRV */
+ { "ISO_646.IRV:1983", RTL_TEXTENCODING_ISO_8859_1 }, /* fake: ASCII_US, used for "C" locale*/
+ { "ISO_6937", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-156 ISO6937*/
+ { "ISO_6937-2-25", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-152 */
+ { "ISO_6937-2-ADD", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-142 */
+ { "ISO_8859-SUPP", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-154 */
+ { "IT", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-15 */
+ { "JIS_C6220-1969-JP", RTL_TEXTENCODING_DONTKNOW }, /* KATAKANA X0201-7 */
+ { "JIS_C6220-1969-RO", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-14 */
+ { "JIS_C6229-1984-A", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-91 */
+ { "JIS_C6229-1984-B", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-92 */
+ { "JIS_C6229-1984-B-ADD", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-93 */
+ { "JIS_C6229-1984-HAND", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-94 */
+ { "JIS_C6229-1984-HAND-ADD", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-95 */
+ { "JIS_C6229-1984-KANA", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-96 */
+ { "JIS_X0201", RTL_TEXTENCODING_DONTKNOW }, /* X0201 */
+ { "JUS_I.B1.002", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-141 */
+ { "JUS_I.B1.003-MAC", RTL_TEXTENCODING_DONTKNOW }, /* MACEDONIAN */
+ { "JUS_I.B1.003-SERB", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-146 SERBIAN */
+ { "KOI-8", RTL_TEXTENCODING_DONTKNOW },
+ { "KOI8-R", RTL_TEXTENCODING_KOI8_R },
+ { "KOI8-U", RTL_TEXTENCODING_KOI8_U },
+ { "KSC5636", RTL_TEXTENCODING_DONTKNOW }, /* ISO646-KR */
+ { "LATIN-GREEK", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-19 */
+ { "LATIN-GREEK-1", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-27 */
+ { "MAC-IS", RTL_TEXTENCODING_APPLE_ROMAN },
+ { "MAC-UK", RTL_TEXTENCODING_APPLE_ROMAN },
+ { "MACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN }, /* MAC */
+ { "MSZ_7795.3", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-86 */
+ { "NATS-DANO", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-9-1 */
+ { "NATS-DANO-ADD", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-9-2 */
+ { "NATS-SEFI", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-8-1 */
+ { "NATS-SEFI-ADD", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-8-2 */
+ { "NC_NC00-10", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-151 */
+ { "NEXTSTEP", RTL_TEXTENCODING_DONTKNOW }, /* NEXT */
+ { "NF_Z_62-010", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-69 */
+ { "NF_Z_62-010_(1973)", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-25 */
+ { "NS_4551-1", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-60 */
+ { "NS_4551-2", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-61 */
+ { "PT", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-16 */
+ { "PT2", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-84 */
+ { "SAMI", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-158 */
+ { "SEN_850200_B", RTL_TEXTENCODING_DONTKNOW }, /* ISO646-[FI|SE] */
+ { "SEN_850200_C", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-11 */
+ { "T.101-G2", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-128 */
+ { "T.61-7BIT", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-102 */
+ { "T.61-8BIT", RTL_TEXTENCODING_DONTKNOW }, /* T.61 ISO-IR-103 */
+ { "TIS-620", RTL_TEXTENCODING_MS_874 }, /* locale: th_TH */
+ { "UTF-8", RTL_TEXTENCODING_UTF8 }, /* ISO-10646/UTF-8 */
+ { "VIDEOTEX-SUPPL", RTL_TEXTENCODING_DONTKNOW }, /* ISO-IR-70 */
+ { "WIN-SAMI-2", RTL_TEXTENCODING_DONTKNOW } /* WS2 */
+};
+
+#elif defined(FREEBSD)
+
+const _pair _nl_language_list[] = {
+ { "ASCII", RTL_TEXTENCODING_ASCII_US }, /* US-ASCII */
+ { "BIG5", RTL_TEXTENCODING_BIG5 }, /* China - Traditional Chinese */
+ { "CP1251", RTL_TEXTENCODING_MS_1251 }, /* MS-CYRL */
+ { "CP866", RTL_TEXTENCODING_IBM_866 }, /* CP866 866 */
+ { "EUCCN", RTL_TEXTENCODING_EUC_CN }, /* China - Simplified Chinese */
+ { "EUCJP", RTL_TEXTENCODING_EUC_JP }, /* Japan */
+ { "EUCKR", RTL_TEXTENCODING_EUC_KR }, /* Korea */
+ { "ISO8859-1", RTL_TEXTENCODING_ISO_8859_1 }, /* Western */
+ { "ISO8859-15", RTL_TEXTENCODING_ISO_8859_15 }, /* Western Updated (w/Euro sign) */
+ { "ISO8859-2", RTL_TEXTENCODING_ISO_8859_2 }, /* Central European */
+ { "ISO8859-4", RTL_TEXTENCODING_ISO_8859_4 }, /* LATIN4 L4 */
+ { "ISO8859-5", RTL_TEXTENCODING_ISO_8859_5 }, /* Cyrillic */
+ { "ISO8859-7", RTL_TEXTENCODING_ISO_8859_7 }, /* Greek */
+ { "ISO8859-9", RTL_TEXTENCODING_ISO_8859_9 }, /* Turkish */
+ { "KOI8-R", RTL_TEXTENCODING_KOI8_R }, /* KOI8-R */
+ { "KOI8-U", RTL_TEXTENCODING_KOI8_U }, /* KOI8-U */
+ { "SJIS", RTL_TEXTENCODING_SHIFT_JIS }, /* Japan */
+ { "US-ASCII", RTL_TEXTENCODING_ASCII_US }, /* US-ASCII */
+ { "UTF-8", RTL_TEXTENCODING_UTF8 } /* ISO-10646/UTF-8 */
+};
+
+#elif defined(NETBSD)
+
+const _pair _nl_language_list[] = {
+ { "ASCII", RTL_TEXTENCODING_ASCII_US }, /* US-ASCII */
+ { "BIG5", RTL_TEXTENCODING_BIG5 }, /* China - Traditional Chinese */
+ { "CP1251", RTL_TEXTENCODING_MS_1251 }, /* MS-CYRL */
+ { "CP866", RTL_TEXTENCODING_IBM_866 }, /* CP866 866 */
+ { "CTEXT", RTL_TEXTENCODING_ASCII_US }, /* US-ASCII */
+ { "EUCCN", RTL_TEXTENCODING_EUC_CN }, /* China - Simplified Chinese */
+ { "EUCJP", RTL_TEXTENCODING_EUC_JP }, /* Japan */
+ { "EUCKR", RTL_TEXTENCODING_EUC_KR }, /* Korea */
+ { "EUCTW", RTL_TEXTENCODING_EUC_TW }, /* China - Traditional Chinese */
+ { "ISO-2022-JP", RTL_TEXTENCODING_DONTKNOW }, /* */
+ { "ISO-2022-JP-2", RTL_TEXTENCODING_DONTKNOW }, /* */
+ { "ISO8859-1", RTL_TEXTENCODING_ISO_8859_1 }, /* Western */
+ { "ISO8859-15", RTL_TEXTENCODING_ISO_8859_15 }, /* Western Updated (w/Euro sign) */
+ { "ISO8859-2", RTL_TEXTENCODING_ISO_8859_2 }, /* Central European */
+ { "ISO8859-4", RTL_TEXTENCODING_ISO_8859_4 }, /* LATIN4 L4 */
+ { "ISO8859-5", RTL_TEXTENCODING_ISO_8859_5 }, /* Cyrillic */
+ { "ISO8859-7", RTL_TEXTENCODING_ISO_8859_7 }, /* Greek */
+ { "ISO8859-9", RTL_TEXTENCODING_ISO_8859_9 }, /* Turkish */
+ { "KOI8-R", RTL_TEXTENCODING_KOI8_R }, /* KOI8-R */
+ { "KOI8-U", RTL_TEXTENCODING_KOI8_U }, /* KOI8-U */
+ { "SJIS", RTL_TEXTENCODING_SHIFT_JIS }, /* Japan */
+ { "US-ASCII", RTL_TEXTENCODING_ASCII_US }, /* US-ASCII */
+ { "UTF-8", RTL_TEXTENCODING_UTF8 } /* ISO-10646/UTF-8 */
+};
+
+#endif /* ifdef SOLARIS LINUX FREEBSD NETBSD */
+
+static pthread_mutex_t aLocalMutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*****************************************************************************
+ return the text encoding corresponding to the given locale
+ *****************************************************************************/
+
+rtl_TextEncoding osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
+{
+ const _pair *language=0;
+
+ char locale_buf[64] = "";
+ char codeset_buf[64];
+
+ char *ctype_locale = 0;
+ char *codeset = 0;
+
+ /* default to process locale if pLocale == NULL */
+ if( NULL == pLocale )
+ osl_getProcessLocale( &pLocale );
+
+ /* convert rtl_Locale to locale string */
+ _compose_locale( pLocale, locale_buf, 64 );
+
+ /* basic thread safeness */
+ pthread_mutex_lock( &aLocalMutex );
+
+ /* remember the charset as indicated by the LC_CTYPE locale */
+ ctype_locale = setlocale( LC_CTYPE, NULL );
+
+ /* set the desired LC_CTYPE locale */
+ if( NULL == setlocale( LC_CTYPE, locale_buf ) )
+ {
+ pthread_mutex_unlock(&aLocalMutex);
+ return RTL_TEXTENCODING_DONTKNOW;
+ }
+
+ /* get the charset as indicated by the LC_CTYPE locale */
+#if defined(NETBSD) && !defined(CODESET)
+ codeset = NULL;
+#else
+ codeset = nl_langinfo( CODESET );
+#endif
+
+ if ( codeset != NULL )
+ {
+ /* get codeset into mt save memory */
+ strncpy( codeset_buf, codeset, sizeof(codeset_buf) );
+ codeset_buf[sizeof(codeset_buf) - 1] = 0;
+ codeset = codeset_buf;
+ }
+
+ /* restore the original value of locale */
+ if ( ctype_locale != NULL )
+ setlocale( LC_CTYPE, ctype_locale );
+
+ pthread_mutex_unlock( &aLocalMutex );
+
+ /* search the codeset in our language list */
+ if ( codeset != NULL )
+ {
+ const unsigned int members = sizeof(_nl_language_list) / sizeof(_pair);
+ language = _pair_search (codeset, _nl_language_list, members);
+ }
+
+ OSL_ASSERT( language && ( RTL_TEXTENCODING_DONTKNOW != language->value ) );
+
+ /* a matching item in our list provides a mapping from codeset to
+ * rtl-codeset */
+ if ( language != NULL )
+ return language->value;
+
+ return RTL_TEXTENCODING_DONTKNOW;
+}
+
+/*****************************************************************************
+ return the current process locale
+ *****************************************************************************/
+
+void _imp_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ char * locale;
+
+ /* basic thread safeness */
+ pthread_mutex_lock( &aLocalMutex );
+
+ /* set the locale defined by the env vars */
+ locale = setlocale( LC_CTYPE, "" );
+
+ /* fallback to the current locale */
+ if( NULL == locale )
+ locale = setlocale( LC_CTYPE, NULL );
+
+ /* return the LC_CTYPE locale */
+ *ppLocale = _parse_locale( locale );
+
+ pthread_mutex_unlock( &aLocalMutex );
+}
+
+/*****************************************************************************
+ set the current process locale
+ *****************************************************************************/
+
+int _imp_setProcessLocale( rtl_Locale * pLocale )
+{
+ char locale_buf[64] = "";
+ int ret = 0;
+
+ /* convert rtl_Locale to locale string */
+ _compose_locale( pLocale, locale_buf, 64 );
+
+ /* basic thread safeness */
+ pthread_mutex_lock( &aLocalMutex );
+
+ /* try to set LC_ALL locale */
+ if( NULL == setlocale( LC_ALL, locale_buf ) )
+ ret = -1;
+
+ pthread_mutex_unlock( &aLocalMutex );
+ return ret;
+}
+
+#else /* ifdef LINUX || SOLARIS || MACOSX || NETBSD */
+
+/*
+ * This implementation of osl_getTextEncodingFromLocale maps
+ * from the ISO language codes.
+ */
+
+const _pair _full_locale_list[] = {
+ { "ja_JP.eucJP", RTL_TEXTENCODING_EUC_JP },
+ { "ja_JP.EUC", RTL_TEXTENCODING_EUC_JP },
+ { "ko_KR.EUC", RTL_TEXTENCODING_EUC_KR },
+ { "zh_CN.EUC", RTL_TEXTENCODING_EUC_CN },
+ { "zh_TW.EUC", RTL_TEXTENCODING_EUC_TW }
+};
+
+const _pair _locale_extension_list[] = {
+ { "big5", RTL_TEXTENCODING_BIG5 },
+ { "big5hk", RTL_TEXTENCODING_BIG5_HKSCS },
+ { "gb18030", RTL_TEXTENCODING_GB_18030 },
+ { "euc", RTL_TEXTENCODING_EUC_JP },
+ { "iso8859-1", RTL_TEXTENCODING_ISO_8859_1 },
+ { "iso8859-10", RTL_TEXTENCODING_ISO_8859_10 },
+ { "iso8859-13", RTL_TEXTENCODING_ISO_8859_13 },
+ { "iso8859-14", RTL_TEXTENCODING_ISO_8859_14 },
+ { "iso8859-15", RTL_TEXTENCODING_ISO_8859_15 },
+ { "iso8859-2", RTL_TEXTENCODING_ISO_8859_2 },
+ { "iso8859-3", RTL_TEXTENCODING_ISO_8859_3 },
+ { "iso8859-4", RTL_TEXTENCODING_ISO_8859_4 },
+ { "iso8859-5", RTL_TEXTENCODING_ISO_8859_5 },
+ { "iso8859-6", RTL_TEXTENCODING_ISO_8859_6 },
+ { "iso8859-7", RTL_TEXTENCODING_ISO_8859_7 },
+ { "iso8859-8", RTL_TEXTENCODING_ISO_8859_8 },
+ { "iso8859-9", RTL_TEXTENCODING_ISO_8859_9 },
+ { "koi8-r", RTL_TEXTENCODING_KOI8_R },
+ { "koi8-u", RTL_TEXTENCODING_KOI8_U },
+ { "pck", RTL_TEXTENCODING_MS_932 },
+#if (0)
+ { "sun_eu_greek", RTL_TEXTENCODING_DONTKNOW },
+#endif
+ { "utf-16", RTL_TEXTENCODING_UNICODE },
+ { "utf-7", RTL_TEXTENCODING_UTF7 },
+ { "utf-8", RTL_TEXTENCODING_UTF8 }
+};
+
+const _pair _iso_language_list[] = {
+ { "af", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ar", RTL_TEXTENCODING_ISO_8859_6 },
+ { "az", RTL_TEXTENCODING_ISO_8859_9 },
+ { "be", RTL_TEXTENCODING_ISO_8859_5 },
+ { "bg", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ca", RTL_TEXTENCODING_ISO_8859_1 },
+ { "cs", RTL_TEXTENCODING_ISO_8859_2 },
+ { "da", RTL_TEXTENCODING_ISO_8859_1 },
+ { "de", RTL_TEXTENCODING_ISO_8859_1 },
+ { "el", RTL_TEXTENCODING_ISO_8859_7 },
+ { "en", RTL_TEXTENCODING_ISO_8859_1 },
+ { "es", RTL_TEXTENCODING_ISO_8859_1 },
+ { "et", RTL_TEXTENCODING_ISO_8859_4 },
+ { "eu", RTL_TEXTENCODING_ISO_8859_1 },
+ { "fa", RTL_TEXTENCODING_ISO_8859_6 },
+ { "fi", RTL_TEXTENCODING_ISO_8859_1 },
+ { "fo", RTL_TEXTENCODING_ISO_8859_1 },
+ { "fr", RTL_TEXTENCODING_ISO_8859_1 },
+ { "gr", RTL_TEXTENCODING_ISO_8859_7 },
+ { "he", RTL_TEXTENCODING_ISO_8859_8 },
+ { "hi", RTL_TEXTENCODING_DONTKNOW },
+ { "hr", RTL_TEXTENCODING_ISO_8859_2 },
+ { "hu", RTL_TEXTENCODING_ISO_8859_2 },
+ { "hy", RTL_TEXTENCODING_DONTKNOW },
+ { "id", RTL_TEXTENCODING_ISO_8859_1 },
+ { "is", RTL_TEXTENCODING_ISO_8859_1 },
+ { "it", RTL_TEXTENCODING_ISO_8859_1 },
+ { "iw", RTL_TEXTENCODING_ISO_8859_8 },
+ { "ja", RTL_TEXTENCODING_EUC_JP },
+ { "ka", RTL_TEXTENCODING_DONTKNOW },
+ { "kk", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ko", RTL_TEXTENCODING_EUC_KR },
+ { "lt", RTL_TEXTENCODING_ISO_8859_4 },
+ { "lv", RTL_TEXTENCODING_ISO_8859_4 },
+ { "mk", RTL_TEXTENCODING_ISO_8859_5 },
+ { "mr", RTL_TEXTENCODING_DONTKNOW },
+ { "ms", RTL_TEXTENCODING_ISO_8859_1 },
+ { "nl", RTL_TEXTENCODING_ISO_8859_1 },
+ { "no", RTL_TEXTENCODING_ISO_8859_1 },
+ { "pl", RTL_TEXTENCODING_ISO_8859_2 },
+ { "pt", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ro", RTL_TEXTENCODING_ISO_8859_2 },
+ { "ru", RTL_TEXTENCODING_ISO_8859_5 },
+ { "sa", RTL_TEXTENCODING_DONTKNOW },
+ { "sk", RTL_TEXTENCODING_ISO_8859_2 },
+ { "sl", RTL_TEXTENCODING_ISO_8859_2 },
+ { "sq", RTL_TEXTENCODING_ISO_8859_2 },
+ { "sv", RTL_TEXTENCODING_ISO_8859_1 },
+ { "sw", RTL_TEXTENCODING_ISO_8859_1 },
+ { "ta", RTL_TEXTENCODING_DONTKNOW },
+ { "th", RTL_TEXTENCODING_DONTKNOW },
+ { "tr", RTL_TEXTENCODING_ISO_8859_9 },
+ { "tt", RTL_TEXTENCODING_ISO_8859_5 },
+ { "uk", RTL_TEXTENCODING_ISO_8859_5 },
+ { "ur", RTL_TEXTENCODING_ISO_8859_6 },
+ { "uz", RTL_TEXTENCODING_ISO_8859_9 },
+ { "vi", RTL_TEXTENCODING_DONTKNOW },
+ { "zh", RTL_TEXTENCODING_BIG5 }
+};
+
+/*****************************************************************************
+ return the text encoding corresponding to the given locale
+ *****************************************************************************/
+
+rtl_TextEncoding osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
+{
+ const _pair *language = 0;
+ char locale_buf[64] = "";
+ char *cp;
+
+ /* default to process locale if pLocale == NULL */
+ if( NULL == pLocale )
+ osl_getProcessLocale( &pLocale );
+
+ /* convert rtl_Locale to locale string */
+ if( _compose_locale( pLocale, locale_buf, 64 ) )
+ {
+ /* check special handling list (EUC) first */
+ const unsigned int members = sizeof( _full_locale_list ) / sizeof( _pair );
+ language = _pair_search( locale_buf, _full_locale_list, members);
+
+ if( NULL == language )
+ {
+ /*
+ * check if there is a charset qualifier at the end of the given locale string
+ * e.g. de.ISO8859-15 or de.ISO8859-15@euro which strongly indicates what
+ * charset to use
+ */
+ cp = strrchr( locale_buf, '.' );
+
+ if( NULL != cp )
+ {
+ const unsigned int members = sizeof( _locale_extension_list ) / sizeof( _pair );
+ language = _pair_search( cp + 1, _locale_extension_list, members);
+ }
+ }
+
+ /* use iso language code to determine the charset */
+ if( NULL == language )
+ {
+ const unsigned int members = sizeof( _iso_language_list ) / sizeof( _pair );
+
+ /* iso lang codes have 2 charaters */
+ locale_buf[2] = '\0';
+
+ language = _pair_search( locale_buf, _iso_language_list, members);
+ }
+ }
+
+ /* a matching item in our list provides a mapping from codeset to
+ * rtl-codeset */
+ if ( language != NULL )
+ return language->value;
+
+ return RTL_TEXTENCODING_DONTKNOW;
+}
+
+#ifdef MACOSX
+#include "system.h"
+
+/* OS X locale discovery function */
+int (*pGetOSXLocale)( char *, sal_uInt32 );
+
+oslModule SAL_CALL osl_psz_loadModule(const sal_Char *pszModuleName, sal_Int32 nRtldMode);
+/*****************************************************************************
+ return the current process locale
+ *****************************************************************************/
+
+int macosx_getLocale(char *locale, sal_uInt32 bufferLen);
+
+void _imp_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ static char *locale = NULL;
+
+ /* basic thread safeness */
+// pthread_mutex_lock( &aLocalMutex );
+
+ /* Only fetch the locale once and cache it */
+ if ( NULL == locale )
+ {
+
+ locale = (char *)malloc( 20 );
+ if ( locale )
+ macosx_getLocale( locale, 20 );
+ else
+ fprintf( stderr, "nlsupport.c: locale allocation returned NULL!\n" );
+ }
+
+ /* handle the case where OS specific method of finding locale fails */
+ if ( NULL == locale )
+ {
+ /* simulate behavior of setlocale */
+ locale = getenv( "LC_ALL" );
+
+ if( NULL == locale )
+ locale = getenv( "LC_CTYPE" );
+
+ if( NULL == locale )
+ locale = getenv( "LANG" );
+
+ if( NULL == locale )
+ locale = "C";
+ }
+
+ /* return the locale */
+ *ppLocale = _parse_locale( locale );
+
+ setenv( "LC_ALL", locale, 1);
+ setenv("LC_CTYPE", locale, 1 );
+ setenv("LANG", locale, 1 );
+
+#ifdef DEBUG
+ fprintf( stderr, "nlsupport.c: _imp_getProcessLocale() returning %s as current locale.\n", locale );
+#endif
+
+// pthread_mutex_unlock( &aLocalMutex );
+
+}
+#else
+/*****************************************************************************
+ return the current process locale
+ *****************************************************************************/
+
+void _imp_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ /* simulate behavior off setlocale */
+ char * locale = getenv( "LC_ALL" );
+
+ if( NULL == locale )
+ locale = getenv( "LC_CTYPE" );
+
+ if( NULL == locale )
+ locale = getenv( "LANG" );
+
+ if( NULL == locale )
+ locale = "C";
+
+ *ppLocale = _parse_locale( locale );
+}
+#endif
+
+/*****************************************************************************
+ set the current process locale
+ *****************************************************************************/
+
+int _imp_setProcessLocale( rtl_Locale * pLocale )
+{
+ char locale_buf[64];
+
+ /* convert rtl_Locale to locale string */
+ if( NULL != _compose_locale( pLocale, locale_buf, 64 ) )
+ {
+ /* only change env vars that exist already */
+ if( getenv( "LC_ALL" ) ) {
+#if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX )
+ setenv( "LC_ALL", locale_buf, 1);
+#else
+ setenv( "LC_ALL", locale_buf );
+#endif
+ }
+
+ if( getenv( "LC_CTYPE" ) ) {
+#if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX )
+ setenv("LC_CTYPE", locale_buf, 1 );
+#else
+ setenv( "LC_CTYPE", locale_buf );
+#endif
+ }
+
+ if( getenv( "LANG" ) ) {
+#if defined( FREEBSD ) || defined( NETBSD ) || defined( MACOSX )
+ setenv("LC_CTYPE", locale_buf, 1 );
+#else
+ setenv( "LANG", locale_buf );
+#endif
+ }
+ }
+
+ return 0;
+}
+
+#endif /* ifdef LINUX || SOLARIS || MACOSX || NETBSD */
+
+
diff --git a/sal/osl/unx/osxlocale.cxx b/sal/osl/unx/osxlocale.cxx
new file mode 100644
index 000000000000..9a20fd9ceb12
--- /dev/null
+++ b/sal/osl/unx/osxlocale.cxx
@@ -0,0 +1,129 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include <sal/types.h>
+#include <assert.h>
+
+#include <premac.h>
+#include <CoreServices/CoreServices.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <postmac.h>
+
+namespace /* private */
+{
+ template <typename T>
+ class CFGuard
+ {
+ public:
+ explicit CFGuard(T& rT) : rT_(rT) {}
+ ~CFGuard() { if (rT_) CFRelease(rT_); }
+ private:
+ T& rT_;
+ };
+
+ typedef CFGuard<CFArrayRef> CFArrayGuard;
+ typedef CFGuard<CFStringRef> CFStringGuard;
+ typedef CFGuard<CFPropertyListRef> CFPropertyListGuard;
+
+ /** Get the current process locale from system
+ */
+ CFStringRef getProcessLocale()
+ {
+ CFPropertyListRef pref = CFPreferencesCopyAppValue(CFSTR("AppleLocale"), kCFPreferencesCurrentApplication);
+ CFPropertyListGuard proplGuard(pref);
+
+ if (pref == NULL) // return fallback value 'en_US'
+ return CFStringCreateWithCString(kCFAllocatorDefault, "en_US", kCFStringEncodingASCII);
+
+ CFStringRef sref = (CFGetTypeID(pref) == CFArrayGetTypeID()) ? (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)pref, 0) : (CFStringRef)pref;
+
+ // NOTE: this API is only available with Mac OS X >=10.3. We need to use it because
+ // Apple used non-ISO values on systems <10.2 like "German" for instance but didn't
+ // upgrade those values during upgrade to newer Mac OS X versions. See also #i54337#
+ return CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, sref);
+ }
+} // namespace private
+
+/** Grab current locale from system.
+*/
+extern "C" {
+int macosx_getLocale(char *locale, sal_uInt32 bufferLen)
+{
+ CFStringRef sref = getProcessLocale();
+ CFStringGuard sGuard(sref);
+
+ assert(sref != NULL && "osxlocale.cxx: getProcessLocale must return a non-NULL value");
+
+ // split the string into substrings; the first two (if there are two) substrings
+ // are language and country
+ CFArrayRef subs = CFStringCreateArrayBySeparatingStrings(NULL, sref, CFSTR("_"));
+ CFArrayGuard arrGuard(subs);
+
+ CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(subs, 0);
+ CFStringGetCString(lang, locale, bufferLen, kCFStringEncodingASCII);
+
+ // country also available? Assumption: if the array contains more than one
+ // value the second value is always the country!
+ if (CFArrayGetCount(subs) > 1)
+ {
+ strlcat(locale, "_", bufferLen - strlen(locale));
+
+ CFStringRef country = (CFStringRef)CFArrayGetValueAtIndex(subs, 1);
+ CFStringGetCString(country, locale + strlen(locale), bufferLen - strlen(locale), kCFStringEncodingASCII);
+ }
+ // Append 'UTF-8' to the locale because the Mac OS X file
+ // system interface is UTF-8 based and sal tries to determine
+ // the file system locale from the locale information
+ strlcat(locale, ".UTF-8", bufferLen - strlen(locale));
+
+ return noErr;
+}
+}
+
+
+
+/*
+ * macxp_OSXConvertCFEncodingToIANACharSetName
+ *
+ * Convert a CoreFoundation text encoding to an IANA charset name.
+ */
+extern "C" int macxp_OSXConvertCFEncodingToIANACharSetName( char *buffer, unsigned int bufferLen, CFStringEncoding cfEncoding )
+{
+ CFStringRef sCFEncodingName;
+
+ sCFEncodingName = CFStringConvertEncodingToIANACharSetName( cfEncoding );
+ CFStringGetCString( sCFEncodingName, buffer, bufferLen, cfEncoding );
+
+ if ( sCFEncodingName )
+ CFRelease( sCFEncodingName );
+
+ return( noErr );
+}
+
diff --git a/sal/osl/unx/pipe.c b/sal/osl/unx/pipe.c
new file mode 100644
index 000000000000..ede4cd7e074f
--- /dev/null
+++ b/sal/osl/unx/pipe.c
@@ -0,0 +1,592 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/pipe.h>
+#include <osl/diagnose.h>
+/*#include <osl/signal.h>*/
+#include <osl/thread.h>
+#include <osl/interlck.h>
+
+#include "sockimpl.h"
+
+#define PIPEDEFAULTPATH "/tmp"
+#define PIPEALTERNATEPATH "/var/tmp"
+
+#define PIPENAMEMASK "OSL_PIPE_%s"
+#define SECPIPENAMEMASK "OSL_PIPE_%s_%s"
+
+sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax);
+oslPipe SAL_CALL osl_psz_createPipe(const sal_Char *pszPipeName, oslPipeOptions Options, oslSecurity Security);
+
+/*#define DEBUG_OSL_PIPE*/
+/*#define TRACE_OSL_PIPE*/
+
+
+/*****************************************************************************/
+/* enum oslPipeError */
+/*****************************************************************************/
+
+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_TO_NATIVE(x) osl_NativeFromPipeError(x)
+#define ERROR_FROM_NATIVE(y) osl_PipeErrorFromNative(y)
+
+
+/*****************************************************************************/
+/* osl_create/destroy-PipeImpl */
+/*****************************************************************************/
+
+oslPipe __osl_createPipeImpl()
+{
+ oslPipe pPipeImpl;
+
+ pPipeImpl = (oslPipe)calloc(1, sizeof(struct oslPipeImpl));
+ 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);
+}
+
+
+/*****************************************************************************/
+/* osl_createPipe */
+/*****************************************************************************/
+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;
+
+}
+
+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];
+ oslPipe pPipe;
+
+ if (access(PIPEDEFAULTPATH, R_OK|W_OK) == 0)
+ {
+ strncpy(name, PIPEDEFAULTPATH, sizeof(name));
+ }
+ else
+ {
+ strncpy(name, PIPEALTERNATEPATH, sizeof(name));
+ }
+
+
+ strncat(name, "/", sizeof(name));
+
+ if (Security)
+ {
+ sal_Char Ident[256];
+
+ Ident[0] = '\0';
+
+ OSL_VERIFY(osl_psz_getUserIdent(Security, Ident, sizeof(Ident)));
+
+ snprintf(&name[strlen(name)], sizeof(name), SECPIPENAMEMASK, Ident, pszPipeName);
+ }
+ else
+ {
+ snprintf(&name[strlen(name)], sizeof(name), PIPENAMEMASK, pszPipeName);
+ }
+
+
+ /* alloc memory */
+ pPipe= __osl_createPipeImpl();
+
+ /* 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\n",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\n",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));
+#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\n",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\n",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));
+
+ if ( listen(pPipe->m_Socket, 5) < 0 )
+ {
+ OSL_TRACE("osl_createPipe failed to listen. Errno: %d; %s\n",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\n",errno,strerror(errno));
+ }
+
+ close (pPipe->m_Socket);
+ __osl_destroyPipeImpl(pPipe);
+ return NULL;
+ }
+}
+
+void SAL_CALL osl_acquirePipe( oslPipe pPipe )
+{
+ osl_incrementInterlockedCount( &(pPipe->m_nRefCount) );
+}
+
+void SAL_CALL osl_releasePipe( oslPipe pPipe )
+{
+
+ if( 0 == pPipe )
+ return;
+
+ if( 0 == osl_decrementInterlockedCount( &(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);
+ 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));
+ len = sizeof(addr);
+
+ nRet = connect( fd, (struct sockaddr *)&addr, len);
+#if OSL_DEBUG_LEVEL > 1
+ if ( nRet < 0 )
+ {
+ perror("connect in osl_destroyPipe");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+ close(fd);
+ }
+#endif /* LINUX */
+
+
+ nRet = shutdown(ConnFD, 2);
+ if ( nRet < 0 )
+ {
+ OSL_TRACE("shutdown in destroyPipe failed : '%s'\n",strerror(errno));
+ }
+
+ nRet = close(ConnFD);
+ if ( nRet < 0 )
+ {
+ OSL_TRACE("close in destroyPipe failed : '%s'\n",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"); */
+}
+
+
+/*****************************************************************************/
+/* osl_acceptPipe */
+/*****************************************************************************/
+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;
+}
+
+/*****************************************************************************/
+/* osl_receivePipe */
+/*****************************************************************************/
+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;
+}
+
+
+/*****************************************************************************/
+/* osl_sendPipe */
+/*****************************************************************************/
+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;
+}
+
+
+/*****************************************************************************/
+/* osl_getLastPipeError */
+/*****************************************************************************/
+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 occured */
+ sal_Int32 BytesSend= 0;
+ sal_Int32 BytesToSend= n;
+
+ OSL_ASSERT(pPipe);
+ while (BytesToSend > 0)
+ {
+ sal_Int32 RetVal;
+
+ RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend);
+
+ /* error occured? */
+ 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 occured */
+ sal_Int32 BytesRead= 0;
+ sal_Int32 BytesToRead= n;
+
+ OSL_ASSERT( pPipe );
+ while (BytesToRead > 0)
+ {
+ sal_Int32 RetVal;
+ RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToRead -= RetVal;
+ BytesRead += RetVal;
+ pBuffer= (sal_Char*)pBuffer + RetVal;
+ }
+ return BytesRead;
+}
+
+
diff --git a/sal/osl/unx/process.c b/sal/osl/unx/process.c
new file mode 100644
index 000000000000..300a1446e81a
--- /dev/null
+++ b/sal/osl/unx/process.c
@@ -0,0 +1,1536 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+/*
+ * ToDo:
+ * - cleanup of process status things
+ * - cleanup of process spawning
+ * - cleanup of resource transfer
+ */
+
+#if defined(SOLARIS)
+ // The procfs may only be used without LFS in 32bits.
+# ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+# endif
+#endif
+
+
+#ifdef FREEBSD
+#include <machine/param.h>
+#endif
+
+#include "system.h"
+#if defined(SOLARIS)
+# include <sys/procfs.h>
+#endif
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+
+#ifndef _OSL_CONDITN_H_
+#include <osl/conditn.h>
+#endif
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <osl/signal.h>
+#include <rtl/alloc.h>
+
+#include <grp.h>
+
+#include "procimpl.h"
+#include "sockimpl.h"
+#include "secimpl.h"
+
+
+#define MAX_ARGS 255
+#define MAX_ENVS 255
+
+#if defined(MACOSX) || defined(IORESOURCE_TRANSFER_BSD)
+#define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int))
+#endif
+
+/* implemented in file.c */
+extern oslFileError FileURLToPath( char *, size_t, rtl_uString* );
+extern oslFileHandle osl_createFileHandleFromFD( int fd );
+
+/******************************************************************************
+ *
+ * Data Type Definition
+ *
+ ******************************************************************************/
+
+typedef struct {
+ int m_hPipe;
+ int m_hConn;
+ sal_Char m_Name[PATH_MAX + 1];
+} Pipe;
+
+typedef struct {
+ const sal_Char* m_pszArgs[MAX_ARGS + 1];
+ oslProcessOption m_options;
+ const sal_Char* m_pszDir;
+ sal_Char* m_pszEnv[MAX_ENVS + 1];
+ uid_t m_uid;
+ gid_t m_gid;
+ sal_Char* m_name;
+ oslCondition m_started;
+ oslProcessImpl* m_pProcImpl;
+ oslFileHandle *m_pInputWrite;
+ oslFileHandle *m_pOutputRead;
+ oslFileHandle *m_pErrorRead;
+} ProcessData;
+
+typedef struct _oslPipeImpl {
+ int m_Socket;
+ sal_Char m_Name[PATH_MAX + 1];
+} oslPipeImpl;
+
+
+/******************************************************************************
+ *
+ * Function Declarations
+ *
+ *****************************************************************************/
+
+oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
+ sal_Char *pszArguments[],
+ oslProcessOption Options,
+ oslSecurity Security,
+ sal_Char *pszDirectory,
+ sal_Char *pszEnvironments[],
+ oslProcess *pProcess,
+ oslFileHandle *pInputWrite,
+ oslFileHandle *pOutputRead,
+ oslFileHandle *pErrorRead );
+
+
+oslProcessError SAL_CALL osl_searchPath_impl(
+ const sal_Char* pszName,
+ const sal_Char* pszPath,
+ sal_Char Separator,
+ sal_Char *pszBuffer,
+ sal_uInt32 Max);
+
+
+sal_Bool osl_getFullPath(const sal_Char* pszFilename, sal_Char* pszPath, sal_uInt32 MaxLen);
+
+static oslProcessImpl* ChildList;
+static oslMutex ChildListMutex;
+
+/******************************************************************************
+ Deprecated
+ Old and buggy implementation of osl_searchPath used only by
+ osl_psz_executeProcess.
+ A new implemenation is in file_path_helper.cxx
+ *****************************************************************************/
+
+oslProcessError SAL_CALL osl_searchPath_impl(const sal_Char* pszName, const sal_Char* pszPath,
+ sal_Char Separator, sal_Char *pszBuffer, sal_uInt32 Max)
+{
+ sal_Char path[PATH_MAX + 1];
+ sal_Char *pchr;
+
+ path[0] = '\0';
+
+ OSL_ASSERT(pszName != NULL);
+
+ if ( pszName == 0 )
+ {
+ return osl_Process_E_NotFound;
+ }
+
+ if (pszPath == NULL)
+ pszPath = "PATH";
+
+ if (Separator == '\0')
+ Separator = ':';
+
+
+ if ( (pchr = getenv(pszPath)) != 0 )
+ {
+ sal_Char *pstr;
+
+ while (*pchr != '\0')
+ {
+ pstr = path;
+
+ while ((*pchr != '\0') && (*pchr != Separator))
+ *pstr++ = *pchr++;
+
+ if ((pstr > path) && ((*(pstr - 1) != '/')))
+ *pstr++ = '/';
+
+ *pstr = '\0';
+
+ strcat(path, pszName);
+
+ if (access(path, 0) == 0)
+ {
+ char szRealPathBuf[PATH_MAX] = "";
+
+ if( NULL == realpath(path, szRealPathBuf) || (strlen(szRealPathBuf) >= (sal_uInt32)Max))
+ return osl_Process_E_Unknown;
+
+ strcpy(pszBuffer, path);
+
+ return osl_Process_E_None;
+ }
+
+ if (*pchr == Separator)
+ pchr++;
+ }
+ }
+
+ return osl_Process_E_NotFound;
+}
+
+/******************************************************************************
+ *
+ * New io resource transfer functions
+ *
+ *****************************************************************************/
+
+
+/**********************************************
+ sendFdPipe
+ *********************************************/
+
+static sal_Bool sendFdPipe(int PipeFD, int SocketFD)
+{
+ sal_Bool bRet = sal_False;
+
+ struct iovec iov[1];
+ struct msghdr msg;
+ char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */
+ int nSend;
+ int RetCode=0;
+
+#if defined(IOCHANNEL_TRANSFER_BSD)
+
+ OSL_TRACE("IOCHANNEL_TRANSFER_BSD send");
+/* OSL_TRACE("sending fd %i\n",SocketFD); */
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sizeof(buf);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ msg.msg_accrights = (caddr_t) &SocketFD; /* addr of descriptor */
+ msg.msg_accrightslen = sizeof(int); /* pass 1 descriptor */
+ buf[1] = 0; /* zero status means OK */
+ buf[0] = 0; /* null byte flag to recv_fd() */
+
+#else
+
+ struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN);
+
+ OSL_TRACE("!!!!!! IOCHANNEL_TRANSFER_BSD_RENO send");
+/* OSL_TRACE("sending fd %i\n",SocketFD); */
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sizeof(buf);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t) cmptr;
+ msg.msg_controllen = CONTROLLEN;
+
+ cmptr->cmsg_level = SOL_SOCKET;
+ cmptr->cmsg_type = SCM_RIGHTS;
+ cmptr->cmsg_len = CONTROLLEN;
+ memcpy(CMSG_DATA(cmptr), &SocketFD, sizeof(int));
+
+#endif
+
+ if ( ( nSend = sendmsg(PipeFD, &msg, 0) ) > 0 )
+ {
+ bRet = sal_True;
+ OSL_TRACE("sendFdPipe : send '%i' bytes\n",nSend);
+
+ }
+ else
+ {
+ OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno));
+ }
+
+ nSend=read(PipeFD,&RetCode,sizeof(RetCode));
+
+ if ( nSend > 0 && RetCode == 1 )
+ {
+ OSL_TRACE("sendFdPipe : resource was received\n");
+ }
+ else
+ {
+ OSL_TRACE("sendFdPipe : resource wasn't received\n");
+ }
+
+#if defined(IOCHANNEL_TRANSFER_BSD_RENO)
+ free(cmptr);
+#endif
+
+ return bRet;
+}
+
+/**********************************************
+ receiveFdPipe
+ *********************************************/
+
+static oslSocket receiveFdPipe(int PipeFD)
+{
+ oslSocket pSocket = 0;
+ struct msghdr msghdr;
+ struct iovec iov[1];
+ char buffer[2];
+ sal_Int32 nRead;
+ int newfd=-1;
+ int nRetCode=0;
+/* char *ptr; */
+
+#if defined(IOCHANNEL_TRANSFER_BSD)
+
+ OSL_TRACE("IOCHANNEL_TRANSFER_BSD receive\n");
+
+ iov[0].iov_base = buffer;
+ iov[0].iov_len = sizeof(buffer);
+ msghdr.msg_name = NULL;
+ msghdr.msg_namelen = 0;
+ msghdr.msg_iov = iov;
+ msghdr.msg_iovlen = 1;
+ msghdr.msg_accrights = (caddr_t) &newfd; /* addr of descriptor */
+ msghdr.msg_accrightslen = sizeof(int); /* receive 1 descriptor */
+
+#else
+ struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CONTROLLEN);
+
+ OSL_TRACE(" !!!! IOCHANNEL_TRANSFER_BSD_RENO receive");
+
+ iov[0].iov_base = buffer;
+ iov[0].iov_len = sizeof(buffer);
+ msghdr.msg_name = NULL;
+ msghdr.msg_namelen = 0;
+ msghdr.msg_iov = iov;
+ msghdr.msg_iovlen = 1;
+
+ msghdr.msg_control = (caddr_t) cmptr;
+ msghdr.msg_controllen = CONTROLLEN;
+
+#endif
+
+
+#if defined(IOCHANNEL_TRANSFER_BSD)
+
+ if ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 )
+ {
+ OSL_TRACE("receiveFdPipe : received '%i' bytes\n",nRead);
+ }
+#else
+
+ if ( ( ( nRead = recvmsg(PipeFD, &msghdr, 0) ) > 0 ) &&
+ ( msghdr.msg_controllen == CONTROLLEN ) )
+ {
+ OSL_TRACE("receiveFdPipe : received '%i' bytes\n",nRead);
+ memcpy(&newfd, CMSG_DATA(cmptr), sizeof(int));
+ }
+#endif
+ else
+ {
+ OSL_TRACE("receiveFdPipe : receiving failed (%s)",strerror(errno));
+ }
+
+ if ( newfd >= 0 )
+ {
+ pSocket = __osl_createSocketImpl(newfd);
+ nRetCode=1;
+ OSL_TRACE("received fd %i\n",newfd);
+ }
+
+ OSL_TRACE("receiveFdPipe : writing back %i",nRetCode);
+ nRead=write(PipeFD,&nRetCode,sizeof(nRetCode));
+
+#if defined(IOCHANNEL_TRANSFER_BSD_RENO)
+ free(cmptr);
+#endif
+
+ return pSocket;
+}
+
+/**********************************************
+ osl_sendResourcePipe
+ *********************************************/
+
+sal_Bool osl_sendResourcePipe(oslPipe pPipe, oslSocket pSocket)
+{
+ sal_Bool bRet = sal_False;
+
+ if ( pSocket == 0 || pPipe == 0 )
+ {
+ return sal_False;
+ }
+
+ bRet = sendFdPipe(pPipe->m_Socket,pSocket->m_Socket);
+
+ return bRet;
+}
+
+/**********************************************
+ osl_receiveResourcePipe
+ *********************************************/
+
+oslSocket osl_receiveResourcePipe(oslPipe pPipe)
+{
+ oslSocket pSocket=0;
+
+ if ( pPipe == 0 )
+ {
+ return 0;
+ }
+
+ pSocket = receiveFdPipe(pPipe->m_Socket);
+
+ return (oslSocket) pSocket;
+}
+
+
+
+/******************************************************************************
+ *
+ * Functions for starting a process
+ *
+ *****************************************************************************/
+
+static void ChildStatusProc(void *pData)
+{
+ pid_t pid = -1;
+ int status = 0;
+ int channel[2];
+ ProcessData data;
+ ProcessData *pdata;
+ int stdOutput[2] = { -1, -1 }, stdInput[2] = { -1, -1 }, stdError[2] = { -1, -1 };
+
+ pdata = (ProcessData *)pData;
+
+ /* make a copy of our data, because forking will only copy
+ our local stack of the thread, so the process data will not be accessible
+ in our child process */
+ memcpy(&data, pData, sizeof(data));
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel) == -1)
+ status = errno;
+
+ fcntl(channel[0], F_SETFD, FD_CLOEXEC);
+ fcntl(channel[1], F_SETFD, FD_CLOEXEC);
+
+ /* Create redirected IO pipes */
+ if ( status == 0 && data.m_pInputWrite )
+ if (pipe( stdInput ) == -1)
+ status = errno;
+
+ if ( status == 0 && data.m_pOutputRead )
+ if (pipe( stdOutput ) == -1)
+ status = errno;
+
+ if ( status == 0 && data.m_pErrorRead )
+ if (pipe( stdError ) == -1)
+ status = errno;
+
+ if ( (status == 0) && ((pid = fork()) == 0) )
+ {
+ /* Child */
+ int chstatus = 0;
+ sal_Int32 nWrote;
+
+ if (channel[0] != -1) close(channel[0]);
+
+ if ((data.m_uid != (uid_t)-1) && ((data.m_uid != getuid()) || (data.m_gid != getgid())))
+ {
+ OSL_ASSERT(geteuid() == 0); /* must be root */
+
+ if (! INIT_GROUPS(data.m_name, data.m_gid) || (setuid(data.m_uid) != 0))
+ OSL_TRACE("Failed to change uid and guid, errno=%d (%s)\n", errno, strerror(errno));
+#if defined(LINUX) || defined (FREEBSD)
+ unsetenv("HOME");
+#else
+ putenv("HOME=");
+#endif
+ }
+
+ if (data.m_pszDir)
+ chstatus = chdir(data.m_pszDir);
+
+ if (chstatus == 0 && ((data.m_uid == (uid_t)-1) || ((data.m_uid == getuid()) && (data.m_gid == getgid()))))
+ {
+ int i;
+ for (i = 0; data.m_pszEnv[i] != NULL; i++)
+ {
+ if (strchr(data.m_pszEnv[i], '=') == NULL)
+ {
+ unsetenv(data.m_pszEnv[i]); /*TODO: check error return*/
+ }
+ else
+ {
+ putenv(data.m_pszEnv[i]); /*TODO: check error return*/
+ }
+ }
+
+ OSL_TRACE("ChildStatusProc : starting '%s'",data.m_pszArgs[0]);
+
+ /* Connect std IO to pipe ends */
+
+ /* Write end of stdInput not used in child process */
+ if (stdInput[1] != -1) close( stdInput[1] );
+
+ /* Read end of stdOutput not used in child process */
+ if (stdOutput[0] != -1) close( stdOutput[0] );
+
+ /* Read end of stdError not used in child process */
+ if (stdError[0] != -1) close( stdError[0] );
+
+ /* Redirect pipe ends to std IO */
+
+ if ( stdInput[0] != STDIN_FILENO )
+ {
+ dup2( stdInput[0], STDIN_FILENO );
+ if (stdInput[0] != -1) close( stdInput[0] );
+ }
+
+ if ( stdOutput[1] != STDOUT_FILENO )
+ {
+ dup2( stdOutput[1], STDOUT_FILENO );
+ if (stdOutput[1] != -1) close( stdOutput[1] );
+ }
+
+ if ( stdError[1] != STDERR_FILENO )
+ {
+ dup2( stdError[1], STDERR_FILENO );
+ if (stdError[1] != -1) close( stdError[1] );
+ }
+
+ pid=execv(data.m_pszArgs[0], (sal_Char **)data.m_pszArgs);
+
+ }
+
+ OSL_TRACE("Failed to exec, errno=%d (%s)\n", errno, strerror(errno));
+
+ OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]);
+
+ /* if we reach here, something went wrong */
+ nWrote = write(channel[1], &errno, sizeof(errno));
+ if (nWrote != sizeof(errno))
+ OSL_TRACE("sendFdPipe : sending failed (%s)",strerror(errno));
+
+ if (channel[1] != -1) close(channel[1]);
+
+ _exit(255);
+ }
+ else
+ { /* Parent */
+ int i = -1;
+ if (channel[1] != -1) close(channel[1]);
+
+ /* Close unused pipe ends */
+ if (stdInput[0] != -1) close( stdInput[0] );
+ if (stdOutput[1] != -1) close( stdOutput[1] );
+ if (stdError[1] != -1) close( stdError[1] );
+
+ if (pid > 0)
+ {
+ while (((i = read(channel[0], &status, sizeof(status))) < 0))
+ {
+ if (errno != EINTR)
+ break;
+ }
+ }
+
+ if (channel[0] != -1) close(channel[0]);
+
+ if ((pid > 0) && (i == 0))
+ {
+ pid_t child_pid;
+ osl_acquireMutex(ChildListMutex);
+
+ pdata->m_pProcImpl->m_pid = pid;
+ pdata->m_pProcImpl->m_pnext = ChildList;
+ ChildList = pdata->m_pProcImpl;
+
+ /* Store used pipe ends in data structure */
+
+ if ( pdata->m_pInputWrite )
+ *(pdata->m_pInputWrite) = osl_createFileHandleFromFD( stdInput[1] );
+
+ if ( pdata->m_pOutputRead )
+ *(pdata->m_pOutputRead) = osl_createFileHandleFromFD( stdOutput[0] );
+
+ if ( pdata->m_pErrorRead )
+ *(pdata->m_pErrorRead) = osl_createFileHandleFromFD( stdError[0] );
+
+ osl_releaseMutex(ChildListMutex);
+
+ osl_setCondition(pdata->m_started);
+
+ do
+ {
+ child_pid = waitpid(pid, &status, 0);
+ } while ( 0 > child_pid && EINTR == errno );
+
+ if ( child_pid < 0)
+ {
+ OSL_TRACE("Failed to wait for child process, errno=%d (%s)\n", errno, strerror(errno));
+
+ /*
+ We got an other error than EINTR. Anyway we have to wake up the
+ waiting thread under any circumstances */
+
+ child_pid = pid;
+ }
+
+
+ if ( child_pid > 0 )
+ {
+ oslProcessImpl* pChild;
+
+ osl_acquireMutex(ChildListMutex);
+
+ pChild = ChildList;
+
+ /* check if it is one of our child processes */
+ while (pChild != NULL)
+ {
+ if (pChild->m_pid == child_pid)
+ {
+ if (WIFEXITED(status))
+ pChild->m_status = WEXITSTATUS(status);
+ else
+ pChild->m_status = -1;
+
+ osl_setCondition(pChild->m_terminated);
+ }
+
+ pChild = pChild->m_pnext;
+ }
+
+ osl_releaseMutex(ChildListMutex);
+ }
+ }
+ else
+ {
+ OSL_TRACE("ChildStatusProc : starting '%s' failed",data.m_pszArgs[0]);
+ OSL_TRACE("Failed to launch child process, child reports errno=%d (%s)\n", status, strerror(status));
+
+ /* Close pipe ends */
+ if ( pdata->m_pInputWrite )
+ *pdata->m_pInputWrite = NULL;
+
+ if ( pdata->m_pOutputRead )
+ *pdata->m_pOutputRead = NULL;
+
+ if ( pdata->m_pErrorRead )
+ *pdata->m_pErrorRead = NULL;
+
+ if (stdInput[1] != -1) close( stdInput[1] );
+ if (stdOutput[0] != -1) close( stdOutput[0] );
+ if (stdError[0] != -1) close( stdError[0] );
+
+ //if pid > 0 then a process was created, even if it later failed
+ //e.g. bash searching for a command to execute, and we still
+ //need to clean it up to avoid "defunct" processes
+ if (pid > 0)
+ {
+ pid_t child_pid;
+ do
+ {
+ child_pid = waitpid(pid, &status, 0);
+ } while ( 0 > child_pid && EINTR == errno );
+ }
+
+ /* notify (and unblock) parent thread */
+ osl_setCondition(pdata->m_started);
+ }
+ }
+}
+
+/**********************************************
+ osl_executeProcess_WithRedirectedIO
+ *********************************************/
+
+oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO(
+ rtl_uString *ustrImageName,
+ rtl_uString *ustrArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *ustrWorkDir,
+ rtl_uString *ustrEnvironment[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess,
+ oslFileHandle *pInputWrite,
+ oslFileHandle *pOutputRead,
+ oslFileHandle *pErrorRead
+ )
+{
+
+ oslProcessError Error;
+ sal_Char* pszWorkDir=0;
+ sal_Char** pArguments=0;
+ sal_Char** pEnvironment=0;
+ unsigned int idx;
+
+ char szImagePath[PATH_MAX] = "";
+ char szWorkDir[PATH_MAX] = "";
+
+ if ( ustrImageName && ustrImageName->length )
+ {
+ FileURLToPath( szImagePath, PATH_MAX, ustrImageName );
+ }
+
+ if ( ustrWorkDir != 0 && ustrWorkDir->length )
+ {
+ FileURLToPath( szWorkDir, PATH_MAX, ustrWorkDir );
+ pszWorkDir = szWorkDir;
+ }
+
+ if ( pArguments == 0 && nArguments > 0 )
+ {
+ pArguments = (sal_Char**) malloc( ( nArguments + 2 ) * sizeof(sal_Char*) );
+ }
+
+
+ for ( idx = 0 ; idx < nArguments ; ++idx )
+ {
+ rtl_String* strArg =0;
+
+
+ rtl_uString2String( &strArg,
+ rtl_uString_getStr(ustrArguments[idx]),
+ rtl_uString_getLength(ustrArguments[idx]),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pArguments[idx]=strdup(rtl_string_getStr(strArg));
+ rtl_string_release(strArg);
+ pArguments[idx+1]=0;
+ }
+
+ for ( idx = 0 ; idx < nEnvironmentVars ; ++idx )
+ {
+ rtl_String* strEnv=0;
+
+ if ( pEnvironment == 0 )
+ {
+ pEnvironment = (sal_Char**) malloc( ( nEnvironmentVars + 2 ) * sizeof(sal_Char*) );
+ }
+
+ rtl_uString2String( &strEnv,
+ rtl_uString_getStr(ustrEnvironment[idx]),
+ rtl_uString_getLength(ustrEnvironment[idx]),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pEnvironment[idx]=strdup(rtl_string_getStr(strEnv));
+ rtl_string_release(strEnv);
+ pEnvironment[idx+1]=0;
+ }
+
+
+ Error = osl_psz_executeProcess(szImagePath,
+ pArguments,
+ Options,
+ Security,
+ pszWorkDir,
+ pEnvironment,
+ pProcess,
+ pInputWrite,
+ pOutputRead,
+ pErrorRead
+ );
+
+ if ( pArguments != 0 )
+ {
+ for ( idx = 0 ; idx < nArguments ; ++idx )
+ {
+ if ( pArguments[idx] != 0 )
+ {
+ free(pArguments[idx]);
+ }
+ }
+ free(pArguments);
+ }
+
+ if ( pEnvironment != 0 )
+ {
+ for ( idx = 0 ; idx < nEnvironmentVars ; ++idx )
+ {
+ if ( pEnvironment[idx] != 0 )
+ {
+ free(pEnvironment[idx]);
+ }
+ }
+ free(pEnvironment);
+ }
+
+ return Error;
+}
+
+/**********************************************
+ osl_executeProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_executeProcess(
+ rtl_uString *ustrImageName,
+ rtl_uString *ustrArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *ustrWorkDir,
+ rtl_uString *ustrEnvironment[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess
+ )
+{
+ return osl_executeProcess_WithRedirectedIO(
+ ustrImageName,
+ ustrArguments,
+ nArguments,
+ Options,
+ Security,
+ ustrWorkDir,
+ ustrEnvironment,
+ nEnvironmentVars,
+ pProcess,
+ NULL,
+ NULL,
+ NULL
+ );
+}
+
+/**********************************************
+ osl_psz_executeProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_psz_executeProcess(sal_Char *pszImageName,
+ sal_Char *pszArguments[],
+ oslProcessOption Options,
+ oslSecurity Security,
+ sal_Char *pszDirectory,
+ sal_Char *pszEnvironments[],
+ oslProcess *pProcess,
+ oslFileHandle *pInputWrite,
+ oslFileHandle *pOutputRead,
+ oslFileHandle *pErrorRead
+ )
+{
+ int i;
+ sal_Char path[PATH_MAX + 1];
+ ProcessData Data;
+ oslThread hThread;
+
+ path[0] = '\0';
+
+ memset(&Data,0,sizeof(ProcessData));
+ Data.m_pInputWrite = pInputWrite;
+ Data.m_pOutputRead = pOutputRead;
+ Data.m_pErrorRead = pErrorRead;
+
+ if (pszImageName == NULL)
+ pszImageName = pszArguments[0];
+
+ OSL_ASSERT(pszImageName != NULL);
+
+ if ( pszImageName == 0 )
+ {
+ return osl_Process_E_NotFound;
+ }
+
+ if ((Options & osl_Process_SEARCHPATH) &&
+ (osl_searchPath_impl(pszImageName, NULL, '\0', path, sizeof(path)) == osl_Process_E_None))
+ pszImageName = path;
+
+ Data.m_pszArgs[0] = strdup(pszImageName);
+ Data.m_pszArgs[1] = 0;
+
+ if ( pszArguments != 0 )
+ {
+ for (i = 0; ((i + 2) < MAX_ARGS) && (pszArguments[i] != NULL); i++)
+ Data.m_pszArgs[i+1] = strdup(pszArguments[i]);
+ Data.m_pszArgs[i+2] = NULL;
+ }
+
+ Data.m_options = Options;
+ Data.m_pszDir = (pszDirectory != NULL) ? strdup(pszDirectory) : NULL;
+
+ if (pszEnvironments != NULL)
+ {
+ for (i = 0; ((i + 1) < MAX_ENVS) && (pszEnvironments[i] != NULL); i++)
+ Data.m_pszEnv[i] = strdup(pszEnvironments[i]);
+ Data.m_pszEnv[i+1] = NULL;
+ }
+ else
+ Data.m_pszEnv[0] = NULL;
+
+ if (Security != NULL)
+ {
+ Data.m_uid = ((oslSecurityImpl*)Security)->m_pPasswd.pw_uid;
+ Data.m_gid = ((oslSecurityImpl*)Security)->m_pPasswd.pw_gid;
+ Data.m_name = ((oslSecurityImpl*)Security)->m_pPasswd.pw_name;
+ }
+ else
+ Data.m_uid = (uid_t)-1;
+
+ Data.m_pProcImpl = (oslProcessImpl*) malloc(sizeof(oslProcessImpl));
+ Data.m_pProcImpl->m_pid = 0;
+ Data.m_pProcImpl->m_terminated = osl_createCondition();
+ Data.m_pProcImpl->m_pnext = NULL;
+
+ if (ChildListMutex == NULL)
+ ChildListMutex = osl_createMutex();
+
+ Data.m_started = osl_createCondition();
+
+ hThread = osl_createThread(ChildStatusProc, &Data);
+
+ osl_waitCondition(Data.m_started, NULL);
+ osl_destroyCondition(Data.m_started);
+
+ for (i = 0; Data.m_pszArgs[i] != NULL; i++)
+ free((void *)Data.m_pszArgs[i]);
+
+ for (i = 0; Data.m_pszEnv[i] != NULL; i++)
+ free((void *)Data.m_pszEnv[i]);
+
+ if ( Data.m_pszDir != 0 )
+ {
+ free((void *)Data.m_pszDir);
+ }
+
+ osl_destroyThread(hThread);
+
+ if (Data.m_pProcImpl->m_pid != 0)
+ {
+ *pProcess = Data.m_pProcImpl;
+
+ if (Options & osl_Process_WAIT)
+ osl_joinProcess(*pProcess);
+
+ return osl_Process_E_None;
+ }
+
+ osl_destroyCondition(Data.m_pProcImpl->m_terminated);
+ free(Data.m_pProcImpl);
+
+ return osl_Process_E_Unknown;
+}
+
+
+/******************************************************************************
+ *
+ * Functions for processes
+ *
+ *****************************************************************************/
+
+
+/**********************************************
+ osl_terminateProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
+{
+ if (Process == NULL)
+ return osl_Process_E_Unknown;
+
+ if (kill(((oslProcessImpl*)Process)->m_pid, SIGKILL) != 0)
+ {
+ switch (errno)
+ {
+ case EPERM:
+ return osl_Process_E_NoPermission;
+
+ case ESRCH:
+ return osl_Process_E_NotFound;
+
+ default:
+ return osl_Process_E_Unknown;
+ }
+ }
+
+ return osl_Process_E_None;
+}
+
+/**********************************************
+ osl_getProcess
+ *********************************************/
+
+oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
+{
+ oslProcessImpl *pProcImpl;
+
+ if (kill(Ident, 0) != -1)
+ {
+ oslProcessImpl* pChild;
+
+ if (ChildListMutex == NULL)
+ ChildListMutex = osl_createMutex();
+
+ osl_acquireMutex(ChildListMutex);
+
+ pChild = ChildList;
+
+ /* check if it is one of our child processes */
+ while (pChild != NULL)
+ {
+ if (Ident == (sal_uInt32) pChild->m_pid)
+ break;
+
+ pChild = pChild->m_pnext;
+ }
+
+ pProcImpl = (oslProcessImpl*) malloc(sizeof(oslProcessImpl));
+ pProcImpl->m_pid = Ident;
+ pProcImpl->m_terminated = osl_createCondition();
+
+ if (pChild != NULL)
+ {
+ /* process is a child so insert into list */
+ pProcImpl->m_pnext = pChild->m_pnext;
+ pChild->m_pnext = pProcImpl;
+
+ pProcImpl->m_status = pChild->m_status;
+
+ if (osl_checkCondition(pChild->m_terminated))
+ osl_setCondition(pProcImpl->m_terminated);
+ }
+ else
+ pProcImpl->m_pnext = NULL;
+
+ osl_releaseMutex(ChildListMutex);
+ }
+ else
+ pProcImpl = NULL;
+
+ return (pProcImpl);
+}
+
+/**********************************************
+ osl_freeProcessHandle
+ *********************************************/
+
+void SAL_CALL osl_freeProcessHandle(oslProcess Process)
+{
+ if (Process != NULL)
+ {
+ oslProcessImpl *pChild, *pPrev = NULL;
+
+ OSL_ASSERT(ChildListMutex != NULL);
+
+ if ( ChildListMutex == 0 )
+ {
+ return;
+ }
+
+ osl_acquireMutex(ChildListMutex);
+
+ pChild = ChildList;
+
+ /* remove process from child list */
+ while (pChild != NULL)
+ {
+ if (pChild == (oslProcessImpl*)Process)
+ {
+ if (pPrev != NULL)
+ pPrev->m_pnext = pChild->m_pnext;
+ else
+ ChildList = pChild->m_pnext;
+
+ break;
+ }
+
+ pPrev = pChild;
+ pChild = pChild->m_pnext;
+ }
+
+ osl_releaseMutex(ChildListMutex);
+
+ osl_destroyCondition(((oslProcessImpl*)Process)->m_terminated);
+
+ free(Process);
+ }
+}
+
+#if defined(LINUX)
+struct osl_procStat
+{
+ /* from 'stat' */
+ pid_t pid; /* pid */
+ char command[16]; /* 'argv[0]' */ /* mfe: it all right char comm[16] in kernel! */
+ char state; /* state (running, stopped, ...) */
+ pid_t ppid; /* parent pid */
+ pid_t pgrp; /* parent group */
+ int session; /* session ID */
+ int tty; /* no of tty */
+ pid_t tpgid; /* group of process owning the tty */
+ unsigned long flags; /* flags dunno */
+ unsigned long minflt; /* minor page faults */
+ unsigned long cminflt; /* minor page faults with children */
+ unsigned long majflt; /* major page faults */
+ unsigned long cmajflt; /* major page faults with children */
+ unsigned long utime; /* no of jiffies in user mode */
+ unsigned long stime; /* no of jiffies in kernel mode */
+ unsigned long cutime; /* no of jiffies in user mode with children */
+ unsigned long cstime; /* no of jiffies in kernel mode with children */
+ unsigned long priority; /* nice value + 15 (kernel scheduling prio)*/
+ long nice; /* nice value */
+ long timeout; /* no of jiffies of next process timeout */
+ long itrealvalue; /* no jiffies before next SIGALRM */
+ unsigned long starttime; /* process started this no of jiffies after boot */
+ unsigned long vsize; /* virtual memory size (in bytes) */
+ long rss; /* resident set size (in pages) */
+ unsigned long rss_rlim; /* rss limit (in bytes) */
+ unsigned long startcode; /* address above program text can run */
+ unsigned long endcode; /* address below program text can run */
+ unsigned long startstack; /* address of start of stack */
+ unsigned long kstkesp; /* current value of 'esp' (stack pointer) */
+ unsigned long kstkeip; /* current value of 'eip' (instruction pointer) */
+ /* mfe: Linux > 2.1.7x have more signals (88) */
+/*#ifdef LINUX */
+ char signal[24]; /* pending signals */
+ char blocked[24]; /* blocked signals */
+ char sigignore[24]; /* ignored signals */
+ char sigcatch[24]; /* catched signals */
+/*#else*/
+/* long long signal;*/
+/* long long blocked;*/
+/* long long sigignore;*/
+/* long long sigcatch;*/
+/*#endif */
+ unsigned long wchan; /* 'channel' the process is waiting in */
+ unsigned long nswap; /* ? */
+ unsigned long cnswap; /* ? */
+
+ /* from 'status' */
+ int ruid; /* real uid */
+ int euid; /* effective uid */
+ int suid; /* saved uid */
+ int fuid; /* file access uid */
+ int rgid; /* real gid */
+ int egid; /* effective gid */
+ int sgid; /* saved gid */
+ int fgid; /* file access gid */
+ unsigned long vm_size; /* like vsize but on kb */
+ unsigned long vm_lock; /* locked pages in kb */
+ unsigned long vm_rss; /* like rss but in kb */
+ unsigned long vm_data; /* data size */
+ unsigned long vm_stack; /* stack size */
+ unsigned long vm_exe; /* executable size */
+ unsigned long vm_lib; /* library size */
+};
+
+/**********************************************
+ osl_getProcStat
+ *********************************************/
+
+sal_Bool osl_getProcStat(pid_t pid, struct osl_procStat* procstat)
+{
+ int fd = 0;
+ sal_Bool bRet = sal_False;
+ char name[PATH_MAX + 1];
+ snprintf(name, sizeof(name), "/proc/%u/stat", pid);
+
+ if ((fd = open(name,O_RDONLY)) >=0 )
+ {
+ char* tmp=0;
+ char prstatbuf[512];
+ memset(prstatbuf,0,512);
+ bRet = read(fd,prstatbuf,511) == 511;
+
+ close(fd);
+ /*printf("%s\n\n",prstatbuf);*/
+
+ if (!bRet)
+ return sal_False;
+
+ tmp = strrchr(prstatbuf, ')');
+ *tmp = '\0';
+ memset(procstat->command, 0, sizeof(procstat->command));
+
+ sscanf(prstatbuf, "%d (%15c", &procstat->pid, procstat->command);
+ sscanf(tmp + 2,
+ "%c"
+ "%i %i %i %i %i"
+ "%lu %lu %lu %lu %lu"
+ "%lu %lu %lu %lu"
+ "%lu %li %li %li"
+ "%lu %lu %li %lu"
+ "%lu %lu %lu %lu %lu"
+ "%s %s %s %s"
+ "%lu %lu %lu",
+ &procstat->state,
+ &procstat->ppid, &procstat->pgrp, &procstat->session, &procstat->tty, &procstat->tpgid,
+ &procstat->flags, &procstat->minflt, &procstat->cminflt, &procstat->majflt, &procstat->cmajflt,
+ &procstat->utime, &procstat->stime, &procstat->cutime, &procstat->cstime,
+ &procstat->priority, &procstat->nice, &procstat->timeout, &procstat->itrealvalue,
+ &procstat->starttime, &procstat->vsize, &procstat->rss, &procstat->rss_rlim,
+ &procstat->startcode, &procstat->endcode, &procstat->startstack, &procstat->kstkesp, &procstat->kstkeip,
+ procstat->signal, procstat->blocked, procstat->sigignore, procstat->sigcatch,
+ &procstat->wchan, &procstat->nswap, &procstat->cnswap
+ );
+ }
+ return bRet;
+}
+
+/**********************************************
+ osl_getProcStatus
+ *********************************************/
+
+sal_Bool osl_getProcStatus(pid_t pid, struct osl_procStat* procstat)
+{
+ int fd = 0;
+ char name[PATH_MAX + 1];
+ snprintf(name, sizeof(name), "/proc/%u/status", pid);
+
+ sal_Bool bRet = sal_False;
+
+ if ((fd = open(name,O_RDONLY)) >=0 )
+ {
+ char* tmp=0;
+ char prstatusbuf[512];
+ memset(prstatusbuf,0,512);
+ bRet = read(fd,prstatusbuf,511) == 511;
+
+ close(fd);
+
+ /* printf("\n\n%s\n\n",prstatusbuf);*/
+
+ if (!bRet)
+ return sal_False;
+
+ tmp = strstr(prstatusbuf,"Uid:");
+ if(tmp)
+ {
+ sscanf(tmp,"Uid:\t%d\t%d\t%d\t%d",
+ &procstat->ruid, &procstat->euid, &procstat->suid, &procstat->fuid
+ );
+ }
+
+
+ tmp = strstr(prstatusbuf,"Gid:");
+ if(tmp)
+ {
+ sscanf(tmp,"Gid:\t%d\t%d\t%d\t%d",
+ &procstat->rgid, &procstat->egid, &procstat->sgid, &procstat->fgid
+ );
+ }
+
+ tmp = strstr(prstatusbuf,"VmSize:");
+ if(tmp)
+ {
+ sscanf(tmp,
+ "VmSize: %lu kB\n"
+ "VmLck: %lu kB\n"
+ "VmRSS: %lu kB\n"
+ "VmData: %lu kB\n"
+ "VmStk: %lu kB\n"
+ "VmExe: %lu kB\n"
+ "VmLib: %lu kB\n",
+ &procstat->vm_size, &procstat->vm_lock, &procstat->vm_rss, &procstat->vm_data,
+ &procstat->vm_stack, &procstat->vm_exe, &procstat->vm_lib
+ );
+ }
+
+ tmp = strstr(prstatusbuf,"SigPnd:");
+ if(tmp)
+ {
+ sscanf(tmp, "SigPnd: %s SigBlk: %s SigIgn: %s %*s %s",
+ procstat->signal, procstat->blocked, procstat->sigignore, procstat->sigcatch
+ );
+ }
+ }
+ return bRet;
+}
+
+#endif
+
+/**********************************************
+ osl_getProcessInfo
+ *********************************************/
+
+oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields, oslProcessInfo* pInfo)
+{
+ pid_t pid;
+
+ if (Process == NULL)
+ pid = getpid();
+ else
+ pid = ((oslProcessImpl*)Process)->m_pid;
+
+ if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
+ return osl_Process_E_Unknown;
+
+ pInfo->Fields = 0;
+
+ if (Fields & osl_Process_IDENTIFIER)
+ {
+ pInfo->Ident = pid;
+ pInfo->Fields |= osl_Process_IDENTIFIER;
+ }
+
+ if (Fields & osl_Process_EXITCODE)
+ {
+ if ((Process != NULL) &&
+ osl_checkCondition(((oslProcessImpl*)Process)->m_terminated))
+ {
+ pInfo->Code = ((oslProcessImpl*)Process)->m_status;
+ pInfo->Fields |= osl_Process_EXITCODE;
+ }
+ }
+
+ if (Fields & (osl_Process_HEAPUSAGE | osl_Process_CPUTIMES))
+ {
+
+#if defined(SOLARIS)
+
+ int fd;
+ sal_Char name[PATH_MAX + 1];
+
+ snprintf(name, sizeof(name), "/proc/%u", pid);
+
+ if ((fd = open(name, O_RDONLY)) >= 0)
+ {
+ prstatus_t prstatus;
+
+ if (ioctl(fd, PIOCSTATUS, &prstatus) >= 0)
+ {
+ if (Fields & osl_Process_CPUTIMES)
+ {
+ pInfo->UserTime.Seconds = prstatus.pr_utime.tv_sec;
+ pInfo->UserTime.Nanosec = prstatus.pr_utime.tv_nsec;
+ pInfo->SystemTime.Seconds = prstatus.pr_stime.tv_sec;
+ pInfo->SystemTime.Nanosec = prstatus.pr_stime.tv_nsec;
+
+ pInfo->Fields |= osl_Process_CPUTIMES;
+ }
+
+ if (Fields & osl_Process_HEAPUSAGE)
+ {
+ pInfo->HeapUsage = prstatus.pr_brksize;
+
+ pInfo->Fields |= osl_Process_HEAPUSAGE;
+ }
+
+ close(fd);
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+ }
+ else
+ close(fd);
+ }
+
+#elif defined(HPUX)
+
+ struct pst_status prstatus;
+
+ if (pstat_getproc(&prstatus, sizeof(prstatus), (size_t)0, pid) == 1)
+ {
+ if (Fields & osl_Process_CPUTIMES)
+ {
+ pInfo->UserTime.Seconds = prstatus.pst_utime;
+ pInfo->UserTime.Nanosec = 500000L;
+ pInfo->SystemTime.Seconds = prstatus.pst_stime;
+ pInfo->SystemTime.Nanosec = 500000L;
+
+ pInfo->Fields |= osl_Process_CPUTIMES;
+ }
+
+ if (Fields & osl_Process_HEAPUSAGE)
+ {
+ pInfo->HeapUsage = prstatus.pst_vdsize*PAGESIZE;
+
+ pInfo->Fields |= osl_Process_HEAPUSAGE;
+ }
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+ }
+
+#elif defined(LINUX)
+
+ if ( (Fields & osl_Process_CPUTIMES) || (Fields & osl_Process_HEAPUSAGE) )
+ {
+ struct osl_procStat procstat;
+ memset(&procstat,0,sizeof(procstat));
+
+ if ( (Fields & osl_Process_CPUTIMES) && osl_getProcStat(pid, &procstat) )
+ {
+ /*
+ * mfe:
+ * We calculate only time of the process proper.
+ * Threads are processes, we do not consider their time here!
+ * (For this, cutime and cstime should be used, it seems not
+ * to work in 2.0.36)
+ */
+
+ long clktck;
+ unsigned long hz;
+ unsigned long userseconds;
+ unsigned long systemseconds;
+
+ clktck = sysconf(_SC_CLK_TCK);
+ if (clktck < 0) {
+ return osl_Process_E_Unknown;
+ }
+ hz = (unsigned long) clktck;
+
+ userseconds = procstat.utime/hz;
+ systemseconds = procstat.stime/hz;
+
+ pInfo->UserTime.Seconds = userseconds;
+ pInfo->UserTime.Nanosec = procstat.utime - (userseconds * hz);
+ pInfo->SystemTime.Seconds = systemseconds;
+ pInfo->SystemTime.Nanosec = procstat.stime - (systemseconds * hz);
+
+ pInfo->Fields |= osl_Process_CPUTIMES;
+ }
+
+ if ( (Fields & osl_Process_HEAPUSAGE) && osl_getProcStatus(pid, &procstat) )
+ {
+ /*
+ * mfe:
+ * vm_data (found in status) shows the size of the data segment
+ * it a rough approximation of the core heap size
+ */
+ pInfo->HeapUsage = procstat.vm_data*1024;
+
+ pInfo->Fields |= osl_Process_HEAPUSAGE;
+ }
+ }
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+#endif
+
+ }
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+}
+
+
+/***********************************************
+ helper function for osl_joinProcessWithTimeout
+ **********************************************/
+
+static int is_timeout(const struct timeval* tend)
+{
+ struct timeval tcurrent;
+ gettimeofday(&tcurrent, NULL);
+ return (tcurrent.tv_sec >= tend->tv_sec);
+}
+
+/**********************************************
+ kill(pid, 0) is usefull for checking if a
+ process is still alive, but remember that
+ kill even returns 0 if the process is already
+ a zombie.
+ *********************************************/
+
+static int is_process_dead(pid_t pid)
+{
+ return ((-1 == kill(pid, 0)) && (ESRCH == errno));
+}
+
+/**********************************************
+ osl_joinProcessWithTimeout
+ *********************************************/
+
+oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
+{
+ oslProcessImpl* pChild = ChildList;
+ oslProcessError osl_error = osl_Process_E_None;
+
+ OSL_PRECOND(Process, "osl_joinProcess: Invalid parameter");
+ OSL_ASSERT(ChildListMutex);
+
+ if (NULL == Process || 0 == ChildListMutex)
+ return osl_Process_E_Unknown;
+
+ osl_acquireMutex(ChildListMutex);
+
+ /* check if process is a child of ours */
+ while (pChild != NULL)
+ {
+ if (pChild == (oslProcessImpl*)Process)
+ break;
+
+ pChild = pChild->m_pnext;
+ }
+
+ osl_releaseMutex(ChildListMutex);
+
+ if (pChild != NULL)
+ {
+ oslConditionResult cond_res = osl_waitCondition(pChild->m_terminated, pTimeout);
+
+ if (osl_cond_result_timeout == cond_res)
+ osl_error = osl_Process_E_TimedOut;
+ else if (osl_cond_result_ok != cond_res)
+ osl_error = osl_Process_E_Unknown;
+ }
+ else /* alien process; StatusThread will not be able
+ to set the condition terminated */
+ {
+ pid_t pid = ((oslProcessImpl*)Process)->m_pid;
+
+ if (pTimeout)
+ {
+ int timeout = 0;
+ struct timeval tend;
+
+ gettimeofday(&tend, NULL);
+
+ tend.tv_sec += pTimeout->Seconds;
+
+ while (!is_process_dead(pid) && ((timeout = is_timeout(&tend)) == 0))
+ sleep(1);
+
+ if (timeout)
+ osl_error = osl_Process_E_TimedOut;
+ }
+ else /* infinite */
+ {
+ while (!is_process_dead(pid))
+ sleep(1);
+ }
+ }
+ return osl_error;
+}
+
+/**********************************************
+ osl_joinProcess
+ *********************************************/
+
+oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
+{
+ return osl_joinProcessWithTimeout(Process, NULL);
+}
diff --git a/sal/osl/unx/process_impl.cxx b/sal/osl/unx/process_impl.cxx
new file mode 100644
index 000000000000..e712b6748e7f
--- /dev/null
+++ b/sal/osl/unx/process_impl.cxx
@@ -0,0 +1,412 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "osl/process.h"
+
+#ifndef INCLUDED_LIMITS_H
+#include <limits.h>
+#define INCLUDED_LIMITS_H
+#endif
+
+#ifndef INCLUDED_PTHREAD_H
+#include <pthread.h>
+#define INCLUDED_PTHREAD_H
+#endif
+
+#ifndef INCLUDED_STDLIB_H
+#include <stdlib.h>
+#define INCLUDED_STDLIB_H
+#endif
+
+#ifndef INCLUDED_STRING_H
+#include <string.h>
+#define INCLUDED_STRING_H
+#endif
+#include "osl/diagnose.h"
+#include <osl/file.h>
+#include "osl/module.h"
+#include "osl/thread.h"
+#include "rtl/ustring.hxx"
+
+#ifndef _OSL_FILE_PATH_HELPER_H_
+#include "file_path_helper.h"
+#endif
+
+#ifndef _OSL_UUNXAPI_H_
+#include "uunxapi.h"
+#endif
+
+/***************************************
+ osl_bootstrap_getExecutableFile_Impl().
+
+ @internal
+ @see rtl_bootstrap
+ @see #i37371#
+
+ **************************************/
+
+extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
+ rtl_uString ** ppFileURL
+) SAL_THROW_EXTERN_C();
+
+
+#if defined(MACOSX)
+#include <mach-o/dyld.h>
+
+oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
+ rtl_uString ** ppFileURL
+) SAL_THROW_EXTERN_C()
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ char buffer[PATH_MAX];
+ size_t buflen = sizeof(buffer);
+
+#if __GNUC__ >= 4 && defined(MACOSX)
+ if (_NSGetExecutablePath (buffer, (uint32_t*)&buflen) == 0)
+#else
+ if (_NSGetExecutablePath (buffer, &buflen) == 0)
+#endif
+ {
+ /* Determine absolute path. */
+ char abspath[PATH_MAX];
+ if (realpath (buffer, abspath) != 0)
+ {
+ /* Convert from utf8 to unicode. */
+ rtl_uString * pAbsPath = 0;
+ rtl_string2UString (
+ &(pAbsPath),
+ abspath, rtl_str_getLength (abspath),
+ RTL_TEXTENCODING_UTF8,
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+
+ if (pAbsPath)
+ {
+ /* Convert from path to url. */
+ if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
+ {
+ /* Success. */
+ result = osl_Process_E_None;
+ }
+ rtl_uString_release (pAbsPath);
+ }
+ }
+ }
+
+ return (result);
+}
+
+#elif !defined(NO_DL_FUNCTIONS)
+#include <dlfcn.h>
+
+oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
+ rtl_uString ** ppFileURL
+) SAL_THROW_EXTERN_C()
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ /* Determine address of "main()" function. */
+ void * addr = dlsym (RTLD_DEFAULT, "main");
+ if (addr != 0)
+ {
+ /* Determine module URL. */
+ if (osl_getModuleURLFromAddress (addr, ppFileURL))
+ {
+ /* Success. */
+ result = osl_Process_E_None;
+ }
+ }
+
+ return (result);
+}
+
+#else /* NO_DL_FUNCTIONS */
+
+oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
+ rtl_uString ** ppFileURL
+) SAL_THROW_EXTERN_C()
+{
+ /* Fallback to ordinary osl_getExecutableFile(). */
+ return osl_getExecutableFile (ppFileURL);
+}
+
+#endif /* NO_DL_FUNCTIONS */
+
+/***************************************
+ CommandArgs_Impl.
+ **************************************/
+struct CommandArgs_Impl
+{
+ pthread_mutex_t m_mutex;
+ sal_uInt32 m_nCount;
+ rtl_uString ** m_ppArgs;
+};
+
+static struct CommandArgs_Impl g_command_args =
+{
+ PTHREAD_MUTEX_INITIALIZER,
+ 0,
+ 0
+};
+
+/***************************************
+ osl_getExecutableFile().
+ **************************************/
+oslProcessError SAL_CALL osl_getExecutableFile (rtl_uString ** ppustrFile)
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ pthread_mutex_lock (&(g_command_args.m_mutex));
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > 0)
+ {
+ /* CommandArgs set. Obtain argv[0]. */
+ rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
+ result = osl_Process_E_None;
+ }
+ pthread_mutex_unlock (&(g_command_args.m_mutex));
+
+ return (result);
+}
+
+/***************************************
+ osl_getCommandArgCount().
+ **************************************/
+sal_uInt32 SAL_CALL osl_getCommandArgCount (void)
+{
+ sal_uInt32 result = 0;
+
+ pthread_mutex_lock (&(g_command_args.m_mutex));
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > 0)
+ result = g_command_args.m_nCount - 1;
+ pthread_mutex_unlock (&(g_command_args.m_mutex));
+
+ return (result);
+}
+
+/***************************************
+ osl_getCommandArg().
+ **************************************/
+oslProcessError SAL_CALL osl_getCommandArg (sal_uInt32 nArg, rtl_uString ** strCommandArg)
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ pthread_mutex_lock (&(g_command_args.m_mutex));
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > (nArg + 1))
+ {
+ rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
+ result = osl_Process_E_None;
+ }
+ pthread_mutex_unlock (&(g_command_args.m_mutex));
+
+ return (result);
+}
+
+/***************************************
+ osl_setCommandArgs().
+ **************************************/
+void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
+{
+ OSL_ASSERT(argc > 0);
+ pthread_mutex_lock (&(g_command_args.m_mutex));
+ OSL_ENSURE (g_command_args.m_nCount == 0, "osl_setCommandArgs(): CommandArgs already set.");
+ if (g_command_args.m_nCount == 0)
+ {
+ rtl_uString** ppArgs = (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
+ if (ppArgs != 0)
+ {
+ rtl_TextEncoding encoding = osl_getThreadTextEncoding();
+ for (int i = 0; i < argc; i++)
+ {
+ rtl_string2UString (
+ &(ppArgs[i]),
+ argv[i], rtl_str_getLength (argv[i]), encoding,
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+ }
+ if (ppArgs[0] != 0)
+ {
+ /* see @ osl_getExecutableFile(). */
+ if (rtl_ustr_indexOfChar (rtl_uString_getStr(ppArgs[0]), sal_Unicode('/')) == -1)
+ {
+ const rtl::OUString PATH (RTL_CONSTASCII_USTRINGPARAM("PATH"));
+
+ rtl_uString * pSearchPath = 0;
+ osl_getEnvironment (PATH.pData, &pSearchPath);
+ if (pSearchPath)
+ {
+ rtl_uString * pSearchResult = 0;
+ osl_searchPath (ppArgs[0], pSearchPath, &pSearchResult);
+ if (pSearchResult)
+ {
+ rtl_uString_assign (&(ppArgs[0]), pSearchResult);
+ rtl_uString_release (pSearchResult);
+ }
+ rtl_uString_release (pSearchPath);
+ }
+ }
+
+ rtl_uString * pArg0 = 0;
+ if (realpath_u (ppArgs[0], &pArg0))
+ {
+ osl_getFileURLFromSystemPath (pArg0, &(ppArgs[0]));
+ rtl_uString_release (pArg0);
+ }
+ }
+ g_command_args.m_nCount = argc;
+ g_command_args.m_ppArgs = ppArgs;
+ }
+ }
+ pthread_mutex_unlock (&(g_command_args.m_mutex));
+}
+
+/***************************************
+ osl_getEnvironment().
+ **************************************/
+oslProcessError SAL_CALL osl_getEnvironment(rtl_uString* pustrEnvVar, rtl_uString** ppustrValue)
+{
+ oslProcessError result = osl_Process_E_NotFound;
+ rtl_TextEncoding encoding = osl_getThreadTextEncoding();
+ rtl_String* pstr_env_var = 0;
+
+ OSL_PRECOND(pustrEnvVar, "osl_getEnvironment(): Invalid parameter");
+ OSL_PRECOND(ppustrValue, "osl_getEnvironment(): Invalid parameter");
+
+ rtl_uString2String(
+ &pstr_env_var,
+ rtl_uString_getStr(pustrEnvVar), rtl_uString_getLength(pustrEnvVar), encoding,
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+ if (pstr_env_var != 0)
+ {
+ const char* p_env_var = getenv (rtl_string_getStr (pstr_env_var));
+ if (p_env_var != 0)
+ {
+ rtl_string2UString(
+ ppustrValue,
+ p_env_var, strlen(p_env_var), encoding,
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(*ppustrValue != NULL);
+
+ result = osl_Process_E_None;
+ }
+ rtl_string_release(pstr_env_var);
+ }
+
+ return (result);
+}
+
+/***************************************
+ osl_getProcessWorkingDir().
+ **************************************/
+oslProcessError SAL_CALL osl_getProcessWorkingDir(rtl_uString **ppustrWorkingDir)
+{
+ oslProcessError result = osl_Process_E_Unknown;
+ char buffer[PATH_MAX];
+
+ OSL_PRECOND(ppustrWorkingDir, "osl_getProcessWorkingDir(): Invalid parameter");
+
+ if (getcwd (buffer, sizeof(buffer)) != 0)
+ {
+ rtl_uString* ustrTmp = 0;
+
+ rtl_string2UString(
+ &ustrTmp,
+ buffer, strlen(buffer), osl_getThreadTextEncoding(),
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+ if (ustrTmp != 0)
+ {
+ if (osl_getFileURLFromSystemPath (ustrTmp, ppustrWorkingDir) == osl_File_E_None)
+ result = osl_Process_E_None;
+ rtl_uString_release (ustrTmp);
+ }
+ }
+
+ return (result);
+}
+
+/******************************************************************************
+ *
+ * new functions to set/return the current process locale
+ *
+ *****************************************************************************/
+
+struct ProcessLocale_Impl
+{
+ pthread_mutex_t m_mutex;
+ rtl_Locale * m_pLocale;
+};
+
+static struct ProcessLocale_Impl g_process_locale =
+{
+ PTHREAD_MUTEX_INITIALIZER,
+ 0
+};
+
+extern "C" void _imp_getProcessLocale( rtl_Locale ** );
+extern "C" int _imp_setProcessLocale( rtl_Locale * );
+
+/**********************************************
+ osl_getProcessLocale().
+ *********************************************/
+oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ OSL_PRECOND(ppLocale, "osl_getProcessLocale(): Invalid parameter.");
+
+ pthread_mutex_lock(&(g_process_locale.m_mutex));
+
+ if (g_process_locale.m_pLocale == 0)
+ _imp_getProcessLocale (&(g_process_locale.m_pLocale));
+ *ppLocale = g_process_locale.m_pLocale;
+
+ pthread_mutex_unlock (&(g_process_locale.m_mutex));
+
+ return (osl_Process_E_None);
+}
+
+/**********************************************
+ osl_setProcessLocale().
+ *********************************************/
+oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
+{
+ oslProcessError result = osl_Process_E_Unknown;
+
+ OSL_PRECOND(pLocale, "osl_setProcessLocale(): Invalid parameter.");
+
+ pthread_mutex_lock(&(g_process_locale.m_mutex));
+ if (_imp_setProcessLocale (pLocale) == 0)
+ {
+ g_process_locale.m_pLocale = pLocale;
+ result = osl_Process_E_None;
+ }
+ pthread_mutex_unlock (&(g_process_locale.m_mutex));
+
+ return (result);
+}
diff --git a/sal/osl/unx/procimpl.h b/sal/osl/unx/procimpl.h
new file mode 100644
index 000000000000..1a08d72ffe5a
--- /dev/null
+++ b/sal/osl/unx/procimpl.h
@@ -0,0 +1,50 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_PROCIMPL_H_
+#define _OSL_PROCIMPL_H_
+
+#include <osl/process.h>
+#include <osl/conditn.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _oslProcessImpl {
+ pid_t m_pid;
+ oslCondition m_terminated;
+ int m_status;
+ struct _oslProcessImpl* m_pnext;
+} oslProcessImpl;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sal/osl/unx/profile.c b/sal/osl/unx/profile.c
new file mode 100644
index 000000000000..c77a27543261
--- /dev/null
+++ b/sal/osl/unx/profile.c
@@ -0,0 +1,2221 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/profile.h>
+#include <osl/process.h>
+#include <osl/thread.h>
+#include <rtl/alloc.h>
+#include <osl/util.h>
+
+#define LINES_INI 32
+#define LINES_ADD 10
+#define SECTIONS_INI 5
+#define SECTIONS_ADD 3
+#define ENTRIES_INI 5
+#define ENTRIES_ADD 3
+
+
+#define STR_INI_EXTENSION "rc"
+#define STR_INI_METAHOME "?~"
+#define STR_INI_METASYS "?$"
+#define STR_INI_METACFG "?^"
+#define STR_INI_METAINS "?#"
+
+#define STR_INI_BOOLYES "yes"
+#define STR_INI_BOOLON "on"
+#define STR_INI_BOOLONE "1"
+#define STR_INI_BOOLNO "no"
+#define STR_INI_BOOLOFF "off"
+#define STR_INI_BOOLZERO "0"
+
+#define FLG_USER 0x00FF
+#define FLG_AUTOOPEN 0x0100
+#define FLG_MODIFIED 0x0200
+
+#define SVERSION_LOCATION STR_INI_METACFG
+#define SVERSION_FALLBACK STR_INI_METASYS
+#define SVERSION_NAME "sversion"
+#define SVERSION_SECTION "Versions"
+#define SVERSION_SOFFICE "StarOffice"
+#define SVERSION_PROFILE "sofficerc"
+#define SVERSION_OPTION "userid:"
+#define SVERSION_DIRS { "bin", "program" }
+#define SVERSION_USER "user"
+
+#define DEFAULT_PMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
+
+#define _BUILD_STR_(n) # n
+#define BUILD_STR(n) _BUILD_STR_(n)
+
+
+/*#define DEBUG_OSL_PROFILE*/
+/*#define TRACE_OSL_PROFILE*/
+
+/*****************************************************************************/
+/* Data Type Definition */
+/*****************************************************************************/
+
+typedef time_t osl_TStamp;
+
+typedef enum _osl_TLockMode
+{
+ un_lock, read_lock, write_lock
+} osl_TLockMode;
+
+typedef struct _osl_TFile
+{
+ int m_Handle;
+ sal_Char* m_pReadPtr;
+ sal_Char m_ReadBuf[512];
+ sal_Char* m_pWriteBuf;
+ sal_uInt32 m_nWriteBufLen;
+ sal_uInt32 m_nWriteBufFree;
+} osl_TFile;
+
+typedef struct _osl_TProfileEntry
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+} osl_TProfileEntry;
+
+typedef struct _osl_TProfileSection
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+ sal_uInt32 m_NoEntries;
+ sal_uInt32 m_MaxEntries;
+ osl_TProfileEntry* m_Entries;
+} osl_TProfileSection;
+
+
+/*
+ Profile-data structure hidden behind oslProfile:
+*/
+typedef struct _osl_TProfileImpl
+{
+ sal_uInt32 m_Flags;
+ osl_TFile* m_pFile;
+ osl_TStamp m_Stamp;
+ sal_Char m_FileName[PATH_MAX + 1];
+ sal_uInt32 m_NoLines;
+ sal_uInt32 m_MaxLines;
+ sal_uInt32 m_NoSections;
+ sal_uInt32 m_MaxSections;
+ sal_Char** m_Lines;
+ osl_TProfileSection* m_Sections;
+ pthread_mutex_t m_AccessLock;
+ sal_Bool m_bIsValid;
+} osl_TProfileImpl;
+
+
+/*****************************************************************************/
+/* Static Module Function Declarations */
+/*****************************************************************************/
+
+static osl_TFile* openFileImpl(const sal_Char* pszFilename, oslProfileOption ProfileFlags);
+static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags);
+static sal_Bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
+static sal_Bool OslProfile_rewindFile(osl_TFile* pFile, sal_Bool bTruncate);
+static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile);
+
+static sal_Char* OslProfile_getLine(osl_TFile* pFile);
+static sal_Bool OslProfile_putLine(osl_TFile* pFile, const sal_Char *pszLine);
+static sal_Char* stripBlanks(sal_Char* String, sal_uInt32* pLen);
+static sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line);
+static sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo);
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ sal_Char* Entry, sal_uInt32 Len);
+static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, sal_Char* Entry, sal_uInt32 Len);
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
+static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len);
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
+ const sal_Char* Entry, sal_uInt32 *pNoEntry);
+static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
+static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup);
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable);
+static sal_Bool releaseProfile(osl_TProfileImpl* pProfile);
+
+static sal_Bool writeProfileImpl (osl_TFile* pFile);
+static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
+static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
+static void osl_ProfileGenerateExtension(sal_Char* pszFileName, sal_Char* pszExtension, sal_Char* pszTmpName);
+static oslProfile SAL_CALL osl_psz_openProfile(const sal_Char *pszProfileName, oslProfileOption Flags);
+
+/* implemented in file.c */
+extern oslFileError FileURLToPath( char *, size_t, rtl_uString* );
+
+/*****************************************************************************/
+/* Exported Module Functions */
+/*****************************************************************************/
+oslProfile SAL_CALL osl_openProfile(rtl_uString *ustrProfileName, oslProfileOption Options)
+{
+ char profilePath[PATH_MAX] = "";
+
+ if ( ustrProfileName != 0 && ustrProfileName->buffer[0] != 0 )
+ FileURLToPath( profilePath, PATH_MAX, ustrProfileName );
+
+ return osl_psz_openProfile( profilePath,Options );
+}
+
+
+static oslProfile SAL_CALL osl_psz_openProfile(const sal_Char *pszProfileName, oslProfileOption Flags)
+{
+ osl_TFile* pFile;
+ osl_TProfileImpl* pProfile;
+ sal_Char Filename[PATH_MAX];
+ sal_Bool bRet = sal_False;
+
+ Filename[0] = '\0';
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_openProfile\n");
+#endif
+
+#ifdef DEBUG_OSL_PROFILE
+ Flags=osl_Profile_FLUSHWRITE;
+
+ OSL_TRACE("opening '%s'\n",pszProfileName);
+ if ( Flags == osl_Profile_DEFAULT )
+ {
+ OSL_TRACE("with osl_Profile_DEFAULT\n");
+ }
+ if ( Flags & osl_Profile_SYSTEM )
+ {
+ OSL_TRACE("with osl_Profile_SYSTEM\n");
+ }
+ if ( Flags & osl_Profile_READLOCK )
+ {
+ OSL_TRACE("with osl_Profile_READLOCK\n");
+ }
+ if ( Flags & osl_Profile_WRITELOCK )
+ {
+ OSL_TRACE("with osl_Profile_WRITELOCK\n");
+ }
+ if ( Flags & osl_Profile_FLUSHWRITE )
+ {
+ OSL_TRACE("with osl_Profile_FLUSHWRITE\n");
+ }
+#endif
+
+
+ if ( ( pFile = openFileImpl(pszProfileName, Flags ) ) == NULL )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_openProfile [not opened]\n");
+#endif
+ return (NULL);
+ }
+
+
+ pProfile = (osl_TProfileImpl*)calloc(1, sizeof(osl_TProfileImpl));
+
+ if ( pProfile == 0 )
+ {
+ return 0;
+ }
+
+ pProfile->m_Flags = Flags & FLG_USER;
+
+ if ( Flags & ( osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
+ {
+ pProfile->m_pFile = pFile;
+ }
+
+ pthread_mutex_init(&(pProfile->m_AccessLock),PTHREAD_MUTEXATTR_DEFAULT);
+ pProfile->m_bIsValid=sal_True;
+
+ pProfile->m_Stamp = OslProfile_getFileStamp(pFile);
+ bRet=loadProfile(pFile, pProfile);
+ bRet &= realpath(pszProfileName, pProfile->m_FileName) != NULL;
+ OSL_ASSERT(bRet);
+
+ if (pProfile->m_pFile == NULL)
+ closeFileImpl(pFile,pProfile->m_Flags);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_openProfile [ok]\n");
+#endif
+ return (pProfile);
+}
+
+sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_closeProfile\n");
+#endif
+
+ if ( Profile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [profile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ pthread_mutex_lock(&(pProfile->m_AccessLock));
+
+ if ( pProfile->m_bIsValid == sal_False )
+ {
+ OSL_ASSERT(pProfile->m_bIsValid);
+ pthread_mutex_unlock(&(pProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [not valid]\n");
+#endif
+ return sal_False;
+ }
+
+ pProfile->m_bIsValid=sal_False;
+
+ if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
+ {
+ pProfile = acquireProfile(Profile,sal_True);
+
+ if ( pProfile != 0 )
+ {
+ bRet=storeProfile(pProfile, sal_True);
+ OSL_ASSERT(bRet);
+ }
+ }
+ else
+ {
+ pProfile = acquireProfile(Profile,sal_False);
+ }
+
+
+ if ( pProfile == 0 )
+ {
+ pthread_mutex_unlock(&(pProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [pProfile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (pProfile->m_pFile != NULL)
+ closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
+
+ pProfile->m_pFile = NULL;
+ pProfile->m_FileName[0] = '\0';
+
+ /* release whole profile data types memory */
+ if ( pProfile->m_NoLines > 0)
+ {
+ unsigned int idx=0;
+ if ( pProfile->m_Lines != 0 )
+ {
+ for ( idx = 0 ; idx < pProfile->m_NoLines ; ++idx)
+ {
+ if ( pProfile->m_Lines[idx] != 0 )
+ {
+ free(pProfile->m_Lines[idx]);
+ pProfile->m_Lines[idx]=0;
+ }
+ }
+ free(pProfile->m_Lines);
+ pProfile->m_Lines=0;
+ }
+ if ( pProfile->m_Sections != 0 )
+ {
+ /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
+ for ( idx = 0 ; idx < pProfile->m_NoSections ; ++idx )
+ {
+ if ( pProfile->m_Sections[idx].m_Entries != 0 )
+ {
+ free(pProfile->m_Sections[idx].m_Entries);
+ pProfile->m_Sections[idx].m_Entries=0;
+ }
+ }
+ free(pProfile->m_Sections);
+ pProfile->m_Sections=0;
+ }
+ }
+
+ pthread_mutex_unlock(&(pProfile->m_AccessLock));
+
+ pthread_mutex_destroy(&(pProfile->m_AccessLock));
+
+ free(pProfile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+
+sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*) Profile;
+ osl_TFile* pFile;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_flushProfile()\n");
+#endif
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [pProfile == 0]\n");
+#endif
+ return sal_False;
+ }
+
+ pthread_mutex_lock(&(pProfile->m_AccessLock));
+
+ if ( pProfile->m_bIsValid == sal_False )
+ {
+ OSL_ASSERT(pProfile->m_bIsValid);
+ pthread_mutex_unlock(&(pProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile [not valid]\n");
+#endif
+ return sal_False;
+ }
+
+ pFile = pProfile->m_pFile;
+ if ( !( pFile != 0 && pFile->m_Handle >= 0 ) )
+ {
+ pthread_mutex_unlock(&(pProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [invalid file]\n");
+#endif
+ return sal_False;
+ }
+
+ if ( pProfile->m_Flags & FLG_MODIFIED )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("swapping to storeprofile\n");
+#endif
+ bRet = storeProfile(pProfile,sal_False);
+ OSL_ASSERT(bRet);
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [ok]\n");
+#endif
+ pthread_mutex_unlock(&(pProfile->m_AccessLock));
+ return bRet;
+}
+
+static sal_Bool writeProfileImpl(osl_TFile* pFile)
+{
+ int BytesWritten=0;
+#if OSL_DEBUG_LEVEL > 1
+ unsigned int nLen=0;
+#endif
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileImpl()\n");
+#endif
+
+ if ( !( pFile != 0 && pFile->m_Handle >= 0 ) || ( pFile->m_pWriteBuf == 0 ) )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileImpl() [invalid args]\n");
+#endif
+ return sal_False;
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ nLen=strlen(pFile->m_pWriteBuf);
+ OSL_ASSERT(nLen == (pFile->m_nWriteBufLen - pFile->m_nWriteBufFree));
+#endif
+
+ BytesWritten = write(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);
+
+ if ( BytesWritten <= 0 )
+ {
+ OSL_TRACE("write failed '%s'\n",strerror(errno));
+ return (sal_False);
+ }
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ASSERT(
+ BytesWritten >= 0 && SAL_INT_CAST(unsigned int, BytesWritten) == nLen);
+#endif
+
+ free(pFile->m_pWriteBuf);
+ pFile->m_pWriteBuf=0;
+ pFile->m_nWriteBufLen=0;
+ pFile->m_nWriteBufFree=0;
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileImpl() [ok]\n");
+#endif
+ return sal_True;
+}
+
+
+sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Char* pszString, sal_uInt32 MaxLen,
+ const sal_Char* pszDefault)
+{
+ sal_uInt32 NoEntry;
+ sal_Char* pStr=0;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile=0;
+ osl_TProfileImpl* pTmpProfile=0;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileString\n");
+#endif
+
+ pTmpProfile = (osl_TProfileImpl*) Profile;
+
+ if ( pTmpProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [pTmpProfile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
+
+ if ( pTmpProfile->m_bIsValid == sal_False )
+ {
+ OSL_ASSERT(pProfile->m_bIsValid);
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [not valid]\n");
+#endif
+ return sal_False;
+ }
+
+ pProfile = acquireProfile(Profile, sal_False);
+
+ if ( pProfile == NULL )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [pProfile==0]\n");
+#endif
+ return (sal_False);
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
+ (NoEntry < pSec->m_NoEntries) &&
+ ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
+ '=')) != NULL))
+ {
+ pStr++;
+ }
+ else
+ {
+ pStr=(sal_Char*)pszDefault;
+ }
+
+ if ( pStr != 0 )
+ {
+ pStr = stripBlanks(pStr, NULL);
+ MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
+ pStr = stripBlanks(pStr, &MaxLen);
+ strncpy(pszString, pStr, MaxLen);
+ pszString[MaxLen] = '\0';
+ }
+ }
+ else
+ { /* not implemented */ }
+
+
+ bRet=releaseProfile(pProfile);
+ OSL_ASSERT(bRet);
+
+ if ( pStr == 0 )
+ {
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [pStr==0]\n");
+#endif
+ return sal_False;
+ }
+
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [ok]\n");
+#endif
+
+ return (sal_True);
+}
+
+
+sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Bool Default)
+{
+ sal_Char Line[32];
+ Line[0] = '\0';
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileBool\n");
+#endif
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ if ((strcasecmp(Line, STR_INI_BOOLYES) == 0) ||
+ (strcasecmp(Line, STR_INI_BOOLON) == 0) ||
+ (strcasecmp(Line, STR_INI_BOOLONE) == 0))
+ Default = sal_True;
+ else
+ if ((strcasecmp(Line, STR_INI_BOOLNO) == 0) ||
+ (strcasecmp(Line, STR_INI_BOOLOFF) == 0) ||
+ (strcasecmp(Line, STR_INI_BOOLZERO) == 0))
+ Default = sal_False;
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileBool [ok]\n");
+#endif
+
+ return (Default);
+}
+
+
+sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_uInt32 FirstId, const sal_Char* Strings[],
+ sal_uInt32 Default)
+{
+ sal_uInt32 i;
+ sal_Char Line[256];
+ Line[0] = '\0';
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileIdent\n");
+#endif
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ i = 0;
+ while (Strings[i] != NULL)
+ {
+ if (strcasecmp(Line, Strings[i]) == 0)
+ {
+ Default = i + FirstId;
+ break;
+ }
+ i++;
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileIdent [ok]\n");
+#endif
+ return (Default);
+}
+
+sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ const sal_Char* pszString)
+{
+ sal_uInt32 i;
+ sal_Bool bRet = sal_False;
+ sal_uInt32 NoEntry;
+ sal_Char* pStr;
+ sal_Char* Line = 0;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+ osl_TProfileImpl* pTmpProfile = 0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileString\n");
+#endif
+
+ pTmpProfile = (osl_TProfileImpl*) Profile;
+
+ if ( pTmpProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [pTmpProfile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
+
+ if ( pTmpProfile->m_bIsValid == sal_False )
+ {
+ OSL_ASSERT(pTmpProfile->m_bIsValid);
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [not valid]\n");
+#endif
+ return sal_False;
+ }
+
+ pProfile=acquireProfile(Profile, sal_True);
+
+ if (pProfile == NULL)
+ {
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [pProfile==0]\n");
+#endif
+ return (sal_False);
+ }
+
+ Line = (sal_Char*) malloc(strlen(pszEntry)+strlen(pszString)+48);
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == NULL)
+ {
+ Line[0] = '\0';
+ addLine(pProfile, Line);
+
+ Line[0] = '[';
+ strcpy(&Line[1], pszSection);
+ Line[1 + strlen(pszSection)] = ']';
+ Line[2 + strlen(pszSection)] = '\0';
+
+ if (((pStr = addLine(pProfile, Line)) == NULL) ||
+ (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
+ {
+ bRet=releaseProfile(pProfile);
+ OSL_ASSERT(bRet);
+
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+
+ free(Line);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [not added]\n");
+#endif
+ return (sal_False);
+ }
+
+ pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
+ NoEntry = pSec->m_NoEntries;
+ }
+
+ Line[0] = '\0';
+ strcpy(&Line[0], pszEntry);
+ Line[0 + strlen(pszEntry)] = '=';
+ strcpy(&Line[1 + strlen(pszEntry)], pszString);
+
+ if (NoEntry >= pSec->m_NoEntries)
+ {
+ if (pSec->m_NoEntries > 0)
+ i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
+ else
+ i = pSec->m_Line + 1;
+
+ if (((pStr = insertLine(pProfile, Line, i)) == NULL) ||
+ (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
+ {
+ bRet=releaseProfile(pProfile);
+ OSL_ASSERT(bRet);
+
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+ free(Line);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [not inserted]\n");
+#endif
+ return (sal_False);
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ else
+ {
+ i = pSec->m_Entries[NoEntry].m_Line;
+ free(pProfile->m_Lines[i]);
+ pProfile->m_Lines[i] = strdup(Line);
+ setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else {
+ /* not implemented */
+ }
+
+ bRet = releaseProfile(pProfile);
+ OSL_ASSERT(bRet);
+
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+ if ( Line!= 0 )
+ {
+ free(Line);
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [ok]\n");
+#endif
+
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Bool Value)
+{
+ sal_Bool bRet=sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileBool\n");
+#endif
+
+ if (Value)
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
+ else
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileBool [ok]\n");
+#endif
+
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_uInt32 FirstId, const sal_Char* Strings[],
+ sal_uInt32 Value)
+{
+ int i, n;
+ sal_Bool bRet=sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileIdent\n");
+#endif
+
+ for (n = 0; Strings[n] != NULL; n++);
+
+ if ((i = Value - FirstId) >= n)
+ bRet=sal_False;
+ else
+ bRet = osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileIdent\n");
+#endif
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
+ const sal_Char *pszSection, const sal_Char *pszEntry)
+{
+ sal_uInt32 NoEntry;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+ osl_TProfileImpl* pTmpProfile = 0;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_removeProfileEntry\n");
+#endif
+
+ pTmpProfile = (osl_TProfileImpl*) Profile;
+
+ if ( pTmpProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
+
+ if ( pTmpProfile->m_bIsValid == sal_False )
+ {
+ OSL_ASSERT(pTmpProfile->m_bIsValid);
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [not valid]\n");
+#endif
+ return sal_False;
+ }
+
+
+ pProfile = acquireProfile(Profile, sal_True);
+
+ if (pProfile == NULL)
+ {
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]\n");
+#endif
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
+ (NoEntry < pSec->m_NoEntries))
+ {
+ removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
+ removeEntry(pSec, NoEntry);
+ if (pSec->m_NoEntries == 0)
+ {
+ removeLine(pProfile, pSec->m_Line);
+
+ /* remove any empty separation line */
+ if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
+ removeLine(pProfile, pSec->m_Line - 1);
+
+ removeSection(pProfile, pSec);
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else
+ { /* not implemented */ }
+
+
+ bRet = releaseProfile(pProfile);
+ OSL_ASSERT(bRet);
+
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [ok]\n");
+#endif
+ return bRet;
+}
+
+
+sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile, const sal_Char *pszSection,
+ sal_Char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ sal_uInt32 NoEntry;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+ osl_TProfileImpl* pTmpProfile = 0;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_getProfileSectionEntries\n");
+#endif
+
+ pTmpProfile = (osl_TProfileImpl*) Profile;
+
+ if ( pTmpProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [pTmpProfile==0]\n");
+#endif
+ return sal_False;
+
+ }
+
+ pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
+
+ if ( pTmpProfile->m_bIsValid == sal_False )
+ {
+ OSL_ASSERT(pTmpProfile->m_bIsValid);
+
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [not valid]\n");
+#endif
+
+ return sal_False;
+ }
+
+ pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ {
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [pProfile=0]\n");
+#endif
+
+ return (0);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != NULL)
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
+ n += pSec->m_Entries[i].m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ break;
+
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ n += pSec->m_Entries[i].m_Len + 1;
+
+ n += 1;
+ }
+ }
+ else
+ n = 0;
+ }
+ else {
+ /* not implemented */
+ }
+
+ bRet=releaseProfile(pProfile);
+ OSL_ASSERT(bRet);
+
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [ok]\n");
+#endif
+
+ return (n);
+}
+
+sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile, sal_Char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+ osl_TProfileImpl* pTmpProfile = 0;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_getProfileSections\n");
+#endif
+
+ pTmpProfile = (osl_TProfileImpl*) Profile;
+
+ if ( pTmpProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSections [pTmpProfile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ pthread_mutex_lock(&(pTmpProfile->m_AccessLock));
+
+ if ( pTmpProfile->m_bIsValid == sal_False )
+ {
+ OSL_ASSERT(pTmpProfile->m_bIsValid);
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSections [not valid]\n");
+#endif
+ return sal_False;
+ }
+
+ pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ {
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSections [pProfile==0]\n");
+#endif
+ return (0);
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if ((n + pSec->m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
+ pSec->m_Len);
+ n += pSec->m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ break;
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ n += pProfile->m_Sections[i].m_Len + 1;
+
+ n += 1;
+ }
+ }
+ else
+ { /* not implemented */ }
+
+
+ bRet=releaseProfile(pProfile);
+ OSL_ASSERT(bRet);
+
+ pthread_mutex_unlock(&(pTmpProfile->m_AccessLock));
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSections [ok]\n");
+#endif
+
+ return (n);
+}
+
+/*****************************************************************************/
+/* Static Module Functions */
+/*****************************************************************************/
+
+static osl_TStamp OslProfile_getFileStamp(osl_TFile* pFile)
+{
+ struct stat status;
+
+ if ( (pFile->m_Handle < 0) || (fstat(pFile->m_Handle, &status) < 0) )
+ {
+ return (0);
+ }
+
+
+ return (status.st_mtime);
+}
+
+static sal_Bool OslProfile_lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
+{
+ struct flock lock;
+ /* boring hack, but initializers for static vars must be constant */
+ static sal_Bool bIsInitialized = sal_False;
+ static sal_Bool bLockingDisabled;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In OslProfile_lockFile\n");
+#endif
+
+ if ( !bIsInitialized )
+ {
+ sal_Char* pEnvValue;
+ pEnvValue = getenv( "STAR_PROFILE_LOCKING_DISABLED" );
+
+ if ( pEnvValue == 0 )
+ {
+ bLockingDisabled = sal_False;
+
+ }
+ else
+ {
+ bLockingDisabled = sal_True;
+ }
+
+ bIsInitialized = sal_True;
+ }
+
+ if (pFile->m_Handle < 0)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out OslProfile_lockFile [invalid file handle]\n");
+#endif
+ return (sal_False);
+ }
+
+
+ if ( bLockingDisabled )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out OslProfile_lockFile [locking disabled]\n");
+#endif
+ return (sal_True);
+ }
+
+
+ lock.l_start = 0;
+ lock.l_whence = SEEK_SET;
+ lock.l_len = 0;
+
+ switch (eMode)
+ {
+ case un_lock:
+ lock.l_type = F_UNLCK;
+ break;
+
+ case read_lock:
+ lock.l_type = F_RDLCK;
+ break;
+
+ case write_lock:
+ lock.l_type = F_WRLCK;
+ break;
+ }
+
+#ifndef MACOSX // not MAC OSX
+ if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 )
+#else
+ /* Mac OSX will return ENOTSUP for webdav drives so we should ignore it */
+ if ( fcntl(pFile->m_Handle, F_SETLKW, &lock) == -1 && errno != ENOTSUP )
+#endif /* MACOSX */
+ {
+ OSL_TRACE("fcntl returned -1 (%s)\n",strerror(errno));
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out OslProfile_lockFile [fcntl F_SETLKW]\n");
+#endif
+ return sal_False;
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out OslProfile_lockFile [ok]\n");
+#endif
+ return sal_True;
+}
+
+static osl_TFile* openFileImpl(const sal_Char* pszFilename, oslProfileOption ProfileFlags )
+{
+ int Flags;
+ osl_TFile* pFile = (osl_TFile*) calloc(1, sizeof(osl_TFile));
+ sal_Bool bWriteable = sal_False;
+
+ if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("setting bWriteable to TRUE\n");
+#endif
+ bWriteable=sal_True;
+ }
+
+ if (! bWriteable)
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("opening '%s' read only\n",pszFilename);
+#endif
+
+ pFile->m_Handle = open(pszFilename, O_RDONLY);
+ /* mfe: argghh!!! do not check if the file could be openend */
+ /* default mode expects it that way!!! */
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("opening '%s' read/write\n",pszFilename);
+#endif
+ if (((pFile->m_Handle = open(pszFilename, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PMODE)) < 0) &&
+ ((pFile->m_Handle = open(pszFilename, O_RDWR)) < 0))
+ {
+ free(pFile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out openFileImpl [open read/write]\n");
+#endif
+ return (NULL);
+ }
+ }
+
+ /* set close-on-exec flag */
+ if ((Flags = fcntl(pFile->m_Handle, F_GETFD, 0)) != -1)
+ {
+ Flags |= FD_CLOEXEC;
+ fcntl(pFile->m_Handle, F_SETFD, Flags);
+ }
+
+ pFile->m_pWriteBuf=0;
+ pFile->m_nWriteBufFree=0;
+ pFile->m_nWriteBufLen=0;
+
+ if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("locking '%s' file\n",pszFilename);
+#endif
+ OslProfile_lockFile(pFile, bWriteable ? write_lock : read_lock);
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out openFileImpl [ok]\n");
+#endif
+ return (pFile);
+}
+
+static osl_TStamp closeFileImpl(osl_TFile* pFile, oslProfileOption Flags)
+{
+ osl_TStamp stamp = 0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In closeFileImpl\n");
+#endif
+
+ if ( pFile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out closeFileImpl [pFile == 0]\n");
+#endif
+ return stamp;
+ }
+
+ if ( pFile->m_Handle >= 0 )
+ {
+ stamp = OslProfile_getFileStamp(pFile);
+
+ if ( Flags & (osl_Profile_WRITELOCK | osl_Profile_WRITELOCK ) )
+ {
+ OslProfile_lockFile(pFile, un_lock);
+ }
+
+ close(pFile->m_Handle);
+ pFile->m_Handle = -1;
+ }
+
+
+ if ( pFile->m_pWriteBuf )
+ {
+ free(pFile->m_pWriteBuf);
+ }
+
+ free(pFile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out closeFileImpl [ok]\n");
+#endif
+
+ return(stamp);
+}
+
+static sal_Bool OslProfile_rewindFile(osl_TFile* pFile, sal_Bool bTruncate)
+{
+ sal_Bool bRet = sal_True;
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_OslProfile_rewindFile\n");
+#endif
+
+ if (pFile->m_Handle >= 0)
+ {
+ pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("rewinding\n");
+#endif
+ bRet = (lseek(pFile->m_Handle, SEEK_SET, 0L) == 0L);
+
+ if (bTruncate)
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("truncating\n");
+#endif
+ bRet &= (ftruncate(pFile->m_Handle, 0L) == 0);
+ }
+
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_OslProfile_rewindFile [ok]\n");
+#endif
+ return bRet;
+}
+
+
+static sal_Char* OslProfile_getLine(osl_TFile* pFile)
+{
+ int Max, Free, Bytes, nLineBytes = 0;
+ sal_Char* pChr;
+ sal_Char* pLine = NULL;
+ sal_Char* pNewLine;
+
+ if ( pFile == 0 )
+ {
+ return 0;
+ }
+
+ if (pFile->m_Handle < 0)
+ return NULL;
+
+ do
+ {
+ Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
+
+ if (Bytes <= 1)
+ {
+ /* refill buffer */
+ memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
+ pFile->m_pReadPtr = pFile->m_ReadBuf;
+
+ Free = sizeof(pFile->m_ReadBuf) - Bytes;
+
+ if ((Max = read(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free)) < 0)
+ {
+ OSL_TRACE("read failed '%s'\n",strerror(errno));
+
+ if( pLine )
+ rtl_freeMemory( pLine );
+ pLine = NULL;
+ break;
+ }
+
+ if (Max < Free)
+ {
+ if ((Max == 0) && ! pLine)
+ break;
+
+ pFile->m_ReadBuf[Bytes + Max] = '\0';
+ }
+ }
+
+ for (pChr = pFile->m_pReadPtr;
+ (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
+ (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
+ pChr++);
+
+ Max = pChr - pFile->m_pReadPtr;
+ pNewLine = (sal_Char*) rtl_allocateMemory( nLineBytes + Max + 1 );
+ if( pLine )
+ {
+ memcpy( pNewLine, pLine, nLineBytes );
+ rtl_freeMemory( pLine );
+ }
+ memcpy(pNewLine+nLineBytes, pFile->m_pReadPtr, Max);
+ nLineBytes += Max;
+ pNewLine[ nLineBytes ] = 0;
+ pLine = pNewLine;
+
+ if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
+ {
+ if (*pChr != '\0')
+ {
+ if ((pChr[0] == '\r') && (pChr[1] == '\n'))
+ pChr += 2;
+ else
+ pChr += 1;
+ }
+
+ if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
+ (*pChr == '\0'))
+ pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+ /* setting Max to -1 indicates terminating read loop */
+ Max = -1;
+ }
+
+ pFile->m_pReadPtr = pChr;
+ }
+ while (Max > 0);
+
+ return pLine;
+}
+
+static sal_Bool OslProfile_putLine(osl_TFile* pFile, const sal_Char *pszLine)
+{
+ unsigned int Len = strlen(pszLine);
+
+#ifdef DEBUG_OSL_PROFILE
+ int strLen=0;
+#endif
+
+ if ( pFile == 0 || pFile->m_Handle < 0 )
+ {
+ return (sal_False);
+ }
+
+ if ( pFile->m_pWriteBuf == 0 )
+ {
+ pFile->m_pWriteBuf = (sal_Char*) malloc(Len+3);
+ pFile->m_nWriteBufLen = Len+3;
+ pFile->m_nWriteBufFree = Len+3;
+ }
+ else
+ {
+ if ( pFile->m_nWriteBufFree <= Len + 3 )
+ {
+ sal_Char* pTmp;
+
+ pTmp=(sal_Char*) realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) );
+ if ( pTmp == 0 )
+ {
+ return sal_False;
+ }
+ pFile->m_pWriteBuf = pTmp;
+ pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
+ pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
+ memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
+ }
+ }
+
+
+
+ memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
+#ifdef DEBUG_OSL_PROFILE
+ strLen = strlen(pFile->m_pWriteBuf);
+#endif
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\n';
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\0';
+
+ pFile->m_nWriteBufFree-=Len+1;
+
+ return sal_True;
+}
+
+/* platform specific end */
+
+static sal_Char* stripBlanks(sal_Char* String, sal_uInt32* pLen)
+{
+ if ( ( pLen != NULL ) && ( *pLen != 0 ) )
+ {
+ while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
+ (*pLen)--;
+
+ while ( (*String == ' ') || (*String == '\t') )
+ {
+ String++;
+ (*pLen)--;
+ }
+ }
+ else
+ while ( (*String == ' ') || (*String == '\t') )
+ String++;
+
+ return (String);
+}
+
+static sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
+ memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+ else
+ {
+ unsigned int idx=0;
+ unsigned int oldmax=pProfile->m_MaxLines;
+
+ pProfile->m_MaxLines += LINES_ADD;
+ pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
+ pProfile->m_MaxLines * sizeof(sal_Char *));
+ for ( idx = oldmax ; idx < pProfile->m_MaxLines ; ++idx )
+ {
+ pProfile->m_Lines[idx]=0;
+ }
+ }
+
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return (NULL);
+ }
+
+ }
+
+ if ( pProfile->m_Lines != 0 && pProfile->m_Lines[pProfile->m_NoLines] != 0 )
+ {
+ free(pProfile->m_Lines[pProfile->m_NoLines]);
+ }
+ pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
+
+ return (pProfile->m_Lines[pProfile->m_NoLines - 1]);
+}
+
+static sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
+ memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+ else
+ {
+ pProfile->m_MaxLines += LINES_ADD;
+ pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
+ pProfile->m_MaxLines * sizeof(sal_Char *));
+
+ memset(&pProfile->m_Lines[pProfile->m_NoLines],
+ 0,
+ (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(sal_Char*));
+ }
+
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return (NULL);
+ }
+ }
+
+ LineNo = LineNo > pProfile->m_NoLines ? pProfile->m_NoLines : LineNo;
+
+ if (LineNo < pProfile->m_NoLines)
+ {
+ sal_uInt32 i, n;
+ osl_TProfileSection* pSec;
+
+ memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
+ (pProfile->m_NoLines - LineNo) * sizeof(sal_Char *));
+
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line >= LineNo)
+ pSec->m_Line++;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line >= LineNo)
+ pSec->m_Entries[n].m_Line++;
+ }
+ }
+
+ pProfile->m_NoLines++;
+
+ pProfile->m_Lines[LineNo] = strdup(Line);
+
+ return (pProfile->m_Lines[LineNo]);
+}
+
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
+{
+ if (LineNo < pProfile->m_NoLines)
+ {
+ free(pProfile->m_Lines[LineNo]);
+ pProfile->m_Lines[LineNo]=0;
+ if (pProfile->m_NoLines - LineNo > 1)
+ {
+ sal_uInt32 i, n;
+ osl_TProfileSection* pSec;
+
+ memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
+ (pProfile->m_NoLines - LineNo - 1) * sizeof(sal_Char *));
+
+ memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
+ 0,
+ (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(sal_Char*));
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line > LineNo)
+ pSec->m_Line--;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line > LineNo)
+ pSec->m_Entries[n].m_Line--;
+ }
+ }
+ else
+ {
+ pProfile->m_Lines[LineNo] = 0;
+ }
+
+ pProfile->m_NoLines--;
+ }
+
+ return;
+}
+
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ sal_Char* Entry, sal_uInt32 Len)
+{
+ Entry = stripBlanks(Entry, &Len);
+ pSection->m_Entries[NoEntry].m_Line = Line;
+ pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
+ pSection->m_Entries[NoEntry].m_Len = Len;
+
+ return;
+}
+
+static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, sal_Char* Entry, sal_uInt32 Len)
+{
+ if (pSection != NULL)
+ {
+ if (pSection->m_NoEntries >= pSection->m_MaxEntries)
+ {
+ if (pSection->m_Entries == NULL)
+ {
+ pSection->m_MaxEntries = ENTRIES_INI;
+ pSection->m_Entries = (osl_TProfileEntry *)malloc(
+ pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
+ }
+ else
+ {
+ pSection->m_MaxEntries += ENTRIES_ADD;
+ pSection->m_Entries = (osl_TProfileEntry *)realloc(pSection->m_Entries,
+ pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
+ }
+
+ if (pSection->m_Entries == NULL)
+ {
+ pSection->m_NoEntries = 0;
+ pSection->m_MaxEntries = 0;
+ return (sal_False);
+ }
+ }
+
+ pSection->m_NoEntries++;
+
+ Entry = stripBlanks(Entry, &Len);
+ setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
+ Entry, Len);
+
+ return (sal_True);
+ }
+
+ return (sal_False);
+}
+
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
+{
+ if (NoEntry < pSection->m_NoEntries)
+ {
+ if (pSection->m_NoEntries - NoEntry > 1)
+ {
+ memmove(&pSection->m_Entries[NoEntry],
+ &pSection->m_Entries[NoEntry + 1],
+ (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
+ }
+
+ pSection->m_NoEntries--;
+ }
+
+ return;
+}
+
+static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len)
+{
+ if (pProfile->m_NoSections >= pProfile->m_MaxSections)
+ {
+ if (pProfile->m_Sections == NULL)
+ {
+ pProfile->m_MaxSections = SECTIONS_INI;
+ pProfile->m_Sections = (osl_TProfileSection *)malloc(pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ memset(pProfile->m_Sections,0,pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ }
+ else
+ {
+ unsigned int idx=0;
+ unsigned int oldmax=pProfile->m_MaxSections;
+
+ pProfile->m_MaxSections += SECTIONS_ADD;
+ pProfile->m_Sections = (osl_TProfileSection *)realloc(pProfile->m_Sections,
+ pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ for ( idx = oldmax ; idx < pProfile->m_MaxSections ; ++idx )
+ {
+ pProfile->m_Sections[idx].m_Entries=0;
+ }
+ }
+
+ if (pProfile->m_Sections == NULL)
+ {
+ pProfile->m_NoSections = 0;
+ pProfile->m_MaxSections = 0;
+ return (sal_False);
+ }
+ }
+
+ pProfile->m_NoSections++;
+
+ if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != 0 )
+ {
+ free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
+ }
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = NULL;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
+
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
+
+ return (sal_True);
+}
+
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
+{
+ sal_uInt32 Section;
+
+ if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
+ {
+ free (pSection->m_Entries);
+ pSection->m_Entries=0;
+ if (pProfile->m_NoSections - Section > 1)
+ {
+ memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
+ (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
+
+ memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
+ 0,
+ (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = 0;
+ }
+ else
+ {
+ pSection->m_Entries = 0;
+ }
+
+ pProfile->m_NoSections--;
+ }
+
+ return;
+}
+
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
+ const sal_Char* Entry, sal_uInt32 *pNoEntry)
+{
+static sal_uInt32 Sect = 0;
+ sal_uInt32 i, n;
+ sal_uInt32 Len;
+ const sal_Char* pStr;
+ osl_TProfileSection* pSec=0;
+
+ Len = strlen(Section);
+
+ n = Sect;
+
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ n %= pProfile->m_NoSections;
+ pSec = &pProfile->m_Sections[n];
+ if ((Len == pSec->m_Len) &&
+ (strncasecmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
+ == 0))
+ break;
+ n++;
+ }
+
+ Sect = n;
+
+ if (i < pProfile->m_NoSections)
+ {
+ Len = strlen(Entry);
+
+ *pNoEntry = pSec->m_NoEntries;
+
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset];
+ if ((Len == pSec->m_Entries[i].m_Len) &&
+ (strncasecmp(Entry, pStr, pSec->m_Entries[i].m_Len)
+ == 0))
+ {
+ *pNoEntry = i;
+ break;
+ }
+ }
+ }
+ else
+ pSec = NULL;
+
+ return (pSec);
+}
+
+static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
+{
+ sal_uInt32 i;
+ sal_Char* pStr;
+ sal_Char* pChar;
+
+ sal_Char* pLine;
+ sal_Char* bWasAdded = NULL;
+
+ pProfile->m_NoLines = 0;
+ pProfile->m_NoSections = 0;
+
+ if ( pFile == 0 )
+ {
+ return sal_False;
+ }
+
+ if ( pProfile == 0 )
+ {
+ return sal_False;
+ }
+
+ OSL_VERIFY(OslProfile_rewindFile(pFile, sal_False));
+
+ while ( ( pLine=OslProfile_getLine(pFile) ) != 0 )
+ {
+ bWasAdded = addLine( pProfile, pLine );
+ rtl_freeMemory( pLine );
+ OSL_ASSERT(bWasAdded);
+ if ( ! bWasAdded )
+ return (sal_False);
+ }
+
+ for (i = 0; i < pProfile->m_NoLines; i++)
+ {
+ pStr = (sal_Char *)stripBlanks(pProfile->m_Lines[i], NULL);
+
+ if ((*pStr == '\0') || (*pStr == ';'))
+ continue;
+
+ if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == NULL) ||
+ ((pChar - pStr) <= 2))
+ {
+ /* insert entry */
+
+ if (pProfile->m_NoSections < 1)
+ continue;
+
+ if ((pChar = strchr(pStr, '=')) == NULL)
+ pChar = pStr + strlen(pStr);
+
+ if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
+ i, pStr, pChar - pStr))
+ {
+ OSL_ASSERT(0);
+ continue;
+ }
+
+ }
+ else
+ {
+ /* new section */
+
+ if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
+ {
+ OSL_ASSERT(0);
+ continue;
+ }
+
+ }
+ }
+
+ return (sal_True);
+}
+
+static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup)
+{
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In storeProfile\n");
+#endif
+
+ if (pProfile->m_Lines != NULL)
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ {
+ sal_uInt32 i;
+
+ osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
+
+ if ( pTmpFile == 0 )
+ {
+ return sal_False;
+ }
+
+ OSL_VERIFY(OslProfile_rewindFile(pTmpFile, sal_True));
+
+ for ( i = 0 ; i < pProfile->m_NoLines ; i++ )
+ {
+ OSL_VERIFY(OslProfile_putLine(pTmpFile, pProfile->m_Lines[i]));
+ }
+
+ if ( ! writeProfileImpl(pTmpFile) )
+ {
+ if ( pTmpFile->m_pWriteBuf != 0 )
+ {
+ free(pTmpFile->m_pWriteBuf);
+ }
+
+ pTmpFile->m_pWriteBuf=0;
+ pTmpFile->m_nWriteBufLen=0;
+ pTmpFile->m_nWriteBufFree=0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out storeProfile [not flushed]\n");
+#endif
+ closeFileImpl(pTmpFile,pProfile->m_Flags);
+
+ return sal_False;
+ }
+
+ pProfile->m_Flags &= ~FLG_MODIFIED;
+
+ closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
+ closeFileImpl(pTmpFile,pProfile->m_Flags);
+
+ osl_ProfileSwapProfileNames(pProfile);
+
+ pProfile->m_pFile = openFileImpl(pProfile->m_FileName,pProfile->m_Flags);
+
+ }
+
+ if (bCleanup)
+ {
+ while (pProfile->m_NoLines > 0)
+ removeLine(pProfile, pProfile->m_NoLines - 1);
+
+ free(pProfile->m_Lines);
+ pProfile->m_Lines = NULL;
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+
+ while (pProfile->m_NoSections > 0)
+ removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
+
+ free(pProfile->m_Sections);
+ pProfile->m_Sections = NULL;
+ pProfile->m_NoSections = 0;
+ pProfile->m_MaxSections = 0;
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out storeProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+
+static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
+{
+ osl_TFile* pFile=0;
+ sal_Char* pszExtension = "tmp";
+ sal_Char pszTmpName[PATH_MAX];
+ oslProfileOption PFlags=0;
+
+ pszTmpName[0] = '\0';
+
+ /* generate tmp profilename */
+ osl_ProfileGenerateExtension(pProfile->m_FileName,pszExtension,pszTmpName);
+
+ if ( pszTmpName[0] == 0 )
+ {
+ return 0;
+ }
+
+ if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) )
+ {
+ PFlags |= osl_Profile_WRITELOCK;
+ }
+
+ /* open this file */
+ pFile = openFileImpl(pszTmpName,pProfile->m_Flags | PFlags);
+
+
+ /* return new pFile */
+ return pFile;
+}
+
+static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
+{
+ sal_Bool bRet = sal_False;
+
+ sal_Char pszBakFile[PATH_MAX];
+ sal_Char pszTmpFile[PATH_MAX];
+ sal_Char pszIniFile[PATH_MAX];
+
+ pszBakFile[0] = '\0';
+ pszTmpFile[0] = '\0';
+ pszIniFile[0] = '\0';
+
+ osl_ProfileGenerateExtension(pProfile->m_FileName,"bak",pszBakFile);
+
+ strcpy(pszIniFile,pProfile->m_FileName);
+
+ osl_ProfileGenerateExtension(pProfile->m_FileName,"tmp",pszTmpFile);
+
+ /* unlink bak */
+ unlink( pszBakFile );
+
+ /* rename ini bak */
+ rename( pszIniFile, pszBakFile );
+
+ /* rename tmp ini */
+ rename( pszTmpFile, pszIniFile );
+
+ return bRet;
+}
+
+
+static void osl_ProfileGenerateExtension(sal_Char* pszFileName, sal_Char* pszExtension, sal_Char* pszTmpName)
+{
+
+ strcpy(pszTmpName,pszFileName);
+ strcat(pszTmpName,".");
+ strcat(pszTmpName,pszExtension);
+
+ return;
+}
+
+
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
+ oslProfileOption PFlags=0;
+ sal_Bool bRet=sal_False;
+
+ if ( bWriteable )
+ {
+ PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
+ }
+ else
+ {
+ PFlags = osl_Profile_DEFAULT;
+ }
+
+
+ if (pProfile == NULL)
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("AUTOOPEN MODE\n");
+#endif
+
+ if ( ( pProfile = (osl_TProfileImpl*) osl_openProfile(0, PFlags ) ) != NULL )
+ {
+ pProfile->m_Flags |= FLG_AUTOOPEN;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("try to acquire\n");
+#endif
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
+ {
+ osl_TStamp Stamp;
+
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("Profile acquire DEFAULT MODE\n");
+#endif
+ if (! (pProfile->m_pFile = openFileImpl(pProfile->m_FileName, pProfile->m_Flags | PFlags )))
+ return NULL;
+
+ Stamp = OslProfile_getFileStamp(pProfile->m_pFile);
+
+ if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
+ {
+ pProfile->m_Stamp = Stamp;
+
+ bRet=loadProfile(pProfile->m_pFile, pProfile);
+ OSL_ASSERT(bRet);
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("Profile acquire READ/WRITELOCK MODE\n");
+#endif
+ /* A readlock file could not be written */
+ if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
+ {
+ return (NULL);
+ }
+ }
+ }
+ }
+
+ return (pProfile);
+}
+
+static sal_Bool releaseProfile(osl_TProfileImpl* pProfile)
+{
+ sal_Bool bRet=sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In releaseProfile\n");
+#endif
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [profile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (pProfile->m_Flags & FLG_AUTOOPEN)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [AUTOOPEN]\n");
+#endif
+ return (osl_closeProfile((oslProfile)pProfile));
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("DEFAULT MODE\n");
+#endif
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE )))
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ {
+ bRet=storeProfile(pProfile, sal_False);
+ OSL_ASSERT(bRet);
+ }
+
+
+ closeFileImpl(pProfile->m_pFile,pProfile->m_Flags);
+ pProfile->m_pFile = NULL;
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [ok]\n");
+#endif
+ return (sal_True);
+}
diff --git a/sal/osl/unx/salinit.cxx b/sal/osl/unx/salinit.cxx
new file mode 100644
index 000000000000..7090a381235c
--- /dev/null
+++ b/sal/osl/unx/salinit.cxx
@@ -0,0 +1,43 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sal.hxx"
+#include "sal/config.h"
+
+#include "osl/process.h"
+#include "sal/main.h"
+#include "sal/types.h"
+
+extern "C" {
+
+void SAL_CALL sal_detail_initialize(int argc, char ** argv) {
+ osl_setCommandArgs(argc, argv);
+}
+
+void SAL_CALL sal_detail_deinitialize() {}
+
+}
diff --git a/sal/osl/unx/secimpl.h b/sal/osl/unx/secimpl.h
new file mode 100644
index 000000000000..1d8f2aaa9419
--- /dev/null
+++ b/sal/osl/unx/secimpl.h
@@ -0,0 +1,47 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_SECURITYIMPL_H_
+#define _OSL_SECURITYIMPL_H_
+
+#include <pwd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _oslSecurityImpl {
+ struct passwd m_pPasswd;
+ char m_buffer[1]; /* should be a C99 flexible array member */
+} oslSecurityImpl;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sal/osl/unx/security.c b/sal/osl/unx/security.c
new file mode 100644
index 000000000000..d08326e65ebe
--- /dev/null
+++ b/sal/osl/unx/security.c
@@ -0,0 +1,862 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <stddef.h>
+
+/* Solaris 8 has no C99 stdint.h, and Solaris generally seems not to miss it for
+ SIZE_MAX: */
+#if !defined __SUNPRO_C
+#include <stdint.h>
+#endif
+
+#include "system.h"
+
+#include <osl/security.h>
+#include <osl/diagnose.h>
+
+#include "osl/thread.h"
+#include "osl/file.h"
+
+#if defined LINUX || defined SOLARIS
+#include <crypt.h>
+#endif
+
+#include "secimpl.h"
+
+#ifndef NOPAM
+#ifndef PAM_BINARY_MSG
+#define PAM_BINARY_MSG 6
+#endif
+#endif
+
+static oslSecurityError SAL_CALL
+osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
+ oslSecurity* pSecurity);
+sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax);
+static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax);
+static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
+static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax);
+
+static sal_Bool sysconf_SC_GETPW_R_SIZE_MAX(size_t * value) {
+#if defined _SC_GETPW_R_SIZE_MAX
+ long m;
+ errno = 0;
+ m = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (m == -1) {
+ /* _SC_GETPW_R_SIZE_MAX has no limit; some platforms like certain
+ FreeBSD versions support sysconf(_SC_GETPW_R_SIZE_MAX) in a broken
+ way and always set EINVAL, so be resilient here: */
+ return sal_False;
+ } else {
+ OSL_ASSERT(m >= 0 && (unsigned long) m < SIZE_MAX);
+ *value = (size_t) m;
+ return sal_True;
+ }
+#else
+ /* some platforms like Mac OS X 1.3 do not define _SC_GETPW_R_SIZE_MAX: */
+ return sal_False;
+#endif
+}
+
+static oslSecurityImpl * growSecurityImpl(
+ oslSecurityImpl * impl, size_t * bufSize)
+{
+ size_t n = 0;
+ oslSecurityImpl * p = NULL;
+ if (impl == NULL) {
+ if (!sysconf_SC_GETPW_R_SIZE_MAX(&n)) {
+ /* choose something sensible (the callers of growSecurityImpl will
+ detect it if the allocated buffer is too small: */
+ n = 1024;
+ }
+ } else if (*bufSize <= SIZE_MAX / 2) {
+ n = 2 * *bufSize;
+ }
+ if (n != 0) {
+ if (n <= SIZE_MAX - offsetof(oslSecurityImpl, m_buffer)) {
+ *bufSize = n;
+ n += offsetof(oslSecurityImpl, m_buffer);
+ } else {
+ *bufSize = SIZE_MAX - offsetof(oslSecurityImpl, m_buffer);
+ n = SIZE_MAX;
+ }
+ p = realloc(impl, n);
+ }
+ if (p == NULL) {
+ free(impl);
+ }
+ return p;
+}
+
+static void deleteSecurityImpl(oslSecurityImpl * impl) {
+ free(impl);
+}
+
+oslSecurity SAL_CALL osl_getCurrentSecurity()
+{
+ size_t n = 0;
+ oslSecurityImpl * p = NULL;
+ for (;;) {
+ struct passwd * found;
+ p = growSecurityImpl(p, &n);
+ if (p == NULL) {
+ return NULL;
+ }
+ switch (getpwuid_r(getuid(), &p->m_pPasswd, p->m_buffer, n, &found)) {
+ case ERANGE:
+ break;
+ case 0:
+ if (found != NULL) {
+ return p;
+ }
+ /* fall through */
+ default:
+ deleteSecurityImpl(p);
+ return NULL;
+ }
+ }
+}
+
+
+#if defined LINUX && !defined NOPAM
+
+/*
+ *
+ * osl Routines for Pluggable Authentication Modules (PAM)
+ * tested with Linux-PAM 0.66 on Redhat-6.0 and
+ * Linux-PAM 0.64 on RedHat-5.2,
+ * XXX Will probably not run on PAM 0.59 or prior, since
+ * number of pam_response* responses has changed
+ *
+ */
+
+#include <security/pam_appl.h>
+
+typedef struct {
+ char* name;
+ char* password;
+} sal_PamData;
+
+typedef struct {
+ int (*pam_start)(const char *service_name, const char *user,
+ const struct pam_conv *pam_conversation,
+ pam_handle_t **pamh);
+ int (*pam_end) (pam_handle_t *pamh, int pam_status);
+ int (*pam_authenticate) (pam_handle_t *pamh, int flags);
+ int (*pam_acct_mgmt) (pam_handle_t *pamh, int flags);
+} sal_PamModule;
+
+/*
+ * Implement a pam-conversation callback-routine,
+ * it just supply name and password instead of prompting the user.
+ * I guess that echo-off means 'ask for password' and echo-on means
+ * 'ask for user-name'. In fact I've never been asked anything else
+ * than the password
+ * XXX Please notice that if a pam-module does ask anything else, we
+ * are completely lost, and a pam-module is free to do so
+ * XXX
+ */
+
+static int
+osl_PamConversation (int num_msg, const struct pam_message **msgm,
+ struct pam_response **response, void *appdata_ptr)
+{
+ int i;
+ sal_Bool error;
+ sal_PamData *pam_data;
+ struct pam_response *p_reply;
+
+ /* resource initialization */
+ pam_data = (sal_PamData*) appdata_ptr;
+ p_reply = (struct pam_response *) calloc( num_msg,
+ sizeof(struct pam_response));
+ if ( p_reply == NULL || pam_data == NULL )
+ {
+ if ( p_reply != NULL )
+ free ( p_reply );
+ *response = NULL;
+ return PAM_CONV_ERR;
+ }
+
+ /* pseudo dialog */
+ error = sal_False;
+ for ( i = 0; i < num_msg ; i++ )
+ {
+ switch ( msgm[ i ]->msg_style )
+ {
+ case PAM_PROMPT_ECHO_OFF:
+ p_reply[ i ].resp_retcode = 0;
+ p_reply[ i ].resp = strdup( pam_data->password );
+ break;
+ case PAM_PROMPT_ECHO_ON:
+ p_reply[ i ].resp_retcode = 0;
+ p_reply[ i ].resp = strdup( pam_data->name );
+ break;
+ case PAM_ERROR_MSG:
+ case PAM_TEXT_INFO:
+ case PAM_BINARY_PROMPT:
+ case PAM_BINARY_MSG:
+ p_reply[ i ].resp_retcode = 0;
+ p_reply[ i ].resp = NULL;
+ break;
+ default:
+ error = sal_True;
+ break;
+ }
+ }
+
+ /* free resources on error */
+ if ( error )
+ {
+ for ( i = 0; i < num_msg ; i++ )
+ if ( p_reply[ i ].resp )
+ {
+ memset ( p_reply[ i ].resp, 0,
+ strlen( p_reply[ i ].resp ) );
+ free ( p_reply[ i ].resp );
+ }
+ free ( p_reply );
+
+ *response = NULL;
+ return PAM_CONV_ERR;
+ }
+
+ /* well done */
+ *response = p_reply;
+ return PAM_SUCCESS;
+}
+
+#ifndef PAM_LINK
+/*
+ * avoid linking against libpam.so, since it is not available on all systems,
+ * instead load-on-call, returns structure which holds pointer to
+ * pam-functions,
+ * library is never closed in case of success
+ */
+
+static sal_PamModule* osl_getPAM()
+{
+ static sal_PamModule *pam_module = NULL;
+ static sal_Bool load_once = sal_False;
+
+ if ( !load_once )
+ {
+ /* get library-handle. cannot use osl-module, since
+ RTLD_GLOBAL is required for PAM-0.64 RH 5.2
+ (but not for PAM-0.66 RH 6.0) */
+ void *pam_hdl;
+
+ pam_hdl = dlopen( "libpam.so.0", RTLD_GLOBAL | RTLD_LAZY );
+
+ if ( pam_hdl != NULL )
+ pam_module = (sal_PamModule*)calloc( 1, sizeof(sal_PamModule) );
+
+ /* load functions */
+ if ( pam_module != NULL )
+ {
+ pam_module->pam_acct_mgmt = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_acct_mgmt" );
+ pam_module->pam_authenticate
+ = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_authenticate" );
+ pam_module->pam_end = (int (*)(pam_handle_t *, int)) dlsym ( pam_hdl, "pam_end" );
+ pam_module->pam_start = (int (*)(const char *, const char *, const struct pam_conv *, pam_handle_t **)) dlsym ( pam_hdl, "pam_start" );
+
+ /* free resources, if not completely successful */
+ if ( (pam_module->pam_start == NULL)
+ || (pam_module->pam_end == NULL)
+ || (pam_module->pam_authenticate == NULL)
+ || (pam_module->pam_acct_mgmt == NULL) )
+ {
+ free( pam_module );
+ pam_module = NULL;
+ dlclose( pam_hdl );
+ }
+ }
+
+ /* never try again */
+ load_once = sal_True;
+ }
+
+ return pam_module;
+}
+#endif
+
+/*
+ * User Identification using PAM
+ */
+
+static sal_Bool
+osl_PamAuthentification( const sal_Char* name, const sal_Char* password )
+{
+ sal_Bool success = sal_False;
+
+#ifndef PAM_LINK
+ sal_PamModule* pam_module;
+
+ pam_module = osl_getPAM();
+ if ( pam_module != NULL )
+ {
+#endif
+ pam_handle_t *pam_handle = NULL;
+ struct pam_conv pam_conversation;
+ sal_PamData pam_data;
+
+ int return_value;
+
+ pam_data.name = (char*) name;
+ pam_data.password = (char*) password;
+
+ pam_conversation.conv = osl_PamConversation;
+ pam_conversation.appdata_ptr = (void*)(&pam_data);
+
+#ifndef PAM_LINK
+ return_value = pam_module->pam_start( "su", name,
+ &pam_conversation, &pam_handle);
+#else
+ return_value = pam_start( "su", name,
+ &pam_conversation, &pam_handle);
+#endif
+ if (return_value == PAM_SUCCESS )
+#ifndef PAM_LINK
+ return_value = pam_module->pam_authenticate(pam_handle, 0);
+#else
+ return_value = pam_authenticate(pam_handle, 0);
+#endif
+ if (return_value == PAM_SUCCESS )
+#ifndef PAM_LINK
+ return_value = pam_module->pam_acct_mgmt(pam_handle, 0);
+ pam_module->pam_end( pam_handle, return_value );
+#else
+ return_value = pam_acct_mgmt(pam_handle, 0);
+ pam_end( pam_handle, return_value );
+#endif
+
+ success = (sal_Bool)(return_value == PAM_SUCCESS);
+#ifndef PAM_LINK
+ }
+#endif
+
+ return success;
+}
+
+
+#ifndef CRYPT_LINK
+/* dummy crypt, matches the interface of
+ crypt() but does not encrypt at all */
+static const sal_Char* SAL_CALL
+osl_noCrypt ( const sal_Char *key, const sal_Char *salt )
+{
+ (void) salt; /* unused */
+ return key;
+}
+
+/* load-on-call crypt library and crypt symbol */
+static void* SAL_CALL
+osl_getCrypt()
+{
+ static char* (*crypt_sym)(const char*, const char*) = NULL;
+ static sal_Bool load_once = sal_False;
+
+ if ( !load_once )
+ {
+ void * crypt_library;
+
+ crypt_library = dlopen( "libcrypt.so.1", RTLD_GLOBAL | RTLD_LAZY ); /* never closed */
+ if ( crypt_library != NULL )
+ crypt_sym = (char* (*)(const char *, const char *)) dlsym(crypt_library, "crypt" );
+ if ( crypt_sym == NULL ) /* no libcrypt or libcrypt without crypt */
+ crypt_sym = (char* (*)(const char *, const char *)) &osl_noCrypt;
+
+ load_once = sal_True;
+ }
+
+ return (void*)crypt_sym;
+}
+
+/* replacement for crypt function for password encryption, uses either
+ strong encryption of dlopen'ed libcrypt.so.1 or dummy implementation
+ with no encryption. Objective target is to avoid linking against
+ libcrypt (not available on caldera open linux 2.2 #63822#) */
+static sal_Char* SAL_CALL
+osl_dynamicCrypt ( const sal_Char *key, const sal_Char *salt )
+{
+ char* (*dynamic_crypt)(char *, char *);
+
+ dynamic_crypt = (char * (*)(char *, char *)) osl_getCrypt();
+
+ return dynamic_crypt( (sal_Char*)key, (sal_Char*)salt );
+}
+#endif
+
+/*
+ * compare an encrypted and an unencrypted password for equality
+ * returns true if passwords are equal, false otherwise
+ * Note: uses crypt() and a mutex instead of crypt_r() since crypt_r needs
+ * more than 128KByte of external buffer for struct crypt_data
+ */
+
+static sal_Bool SAL_CALL
+osl_equalPasswords ( const sal_Char *pEncryptedPassword, const sal_Char *pPlainPassword )
+{
+ static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+ sal_Bool success;
+ sal_Char salt[3];
+ sal_Char *encrypted_plain;
+
+ salt[0] = pEncryptedPassword[0];
+ salt[1] = pEncryptedPassword[1];
+ salt[2] = '\0';
+
+ pthread_mutex_lock(&crypt_mutex);
+
+#ifndef CRYPT_LINK
+ encrypted_plain = (sal_Char *)osl_dynamicCrypt( pPlainPassword, salt );
+#else
+ encrypted_plain = (sal_Char *)crypt( pPlainPassword, salt );
+#endif
+ success = (sal_Bool) (strcmp(pEncryptedPassword, encrypted_plain) == 0);
+
+ pthread_mutex_unlock(&crypt_mutex);
+
+ return success;
+}
+
+#endif /* defined LINUX && !defined NOPAM */
+oslSecurityError SAL_CALL osl_loginUser(
+ rtl_uString *ustrUserName,
+ rtl_uString *ustrPassword,
+ oslSecurity *pSecurity
+ )
+{
+ oslSecurityError Error;
+ rtl_String* strUserName=0;
+ rtl_String* strPassword=0;
+ sal_Char* pszUserName=0;
+ sal_Char* pszPassword=0;
+
+ if ( ustrUserName != 0 )
+ {
+
+ rtl_uString2String( &strUserName,
+ rtl_uString_getStr(ustrUserName),
+ rtl_uString_getLength(ustrUserName),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszUserName = rtl_string_getStr(strUserName);
+ }
+
+
+ if ( ustrPassword != 0 )
+ {
+ rtl_uString2String( &strPassword,
+ rtl_uString_getStr(ustrPassword),
+ rtl_uString_getLength(ustrPassword),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszPassword = rtl_string_getStr(strPassword);
+ }
+
+
+ Error=osl_psz_loginUser(pszUserName,pszPassword,pSecurity);
+
+ if ( strUserName != 0 )
+ {
+ rtl_string_release(strUserName);
+ }
+
+ if ( strPassword)
+ {
+ rtl_string_release(strPassword);
+ }
+
+
+ return Error;
+}
+
+
+static oslSecurityError SAL_CALL
+osl_psz_loginUser(const sal_Char* pszUserName, const sal_Char* pszPasswd,
+ oslSecurity* pSecurity)
+{
+#if defined NETBSD || defined SCO || defined AIX || defined FREEBSD || \
+ defined MACOSX
+
+ return osl_Security_E_None;
+
+#else
+
+ oslSecurityError nError = osl_Security_E_Unknown;
+ oslSecurityImpl * p = NULL;
+ if (pszUserName != NULL && pszPasswd != NULL && pSecurity != NULL) {
+ /* get nis or normal password, should succeed for any known user, but
+ perhaps the password is wrong (i.e. 'x') if shadow passwords are in
+ use or authentication must be done by PAM */
+ size_t n = 0;
+ int err = 0;
+ struct passwd * found = NULL;
+ for (;;) {
+ p = growSecurityImpl(p, &n);
+ if (p == NULL) {
+ break;
+ }
+ err = getpwnam_r(
+ pszUserName, &p->m_pPasswd, p->m_buffer, n, &found);
+ if (err != ERANGE) {
+ break;
+ }
+ }
+ if (p != NULL && err == 0) {
+ if (found == NULL) {
+ nError = osl_Security_E_UserUnknown;
+ } else {
+#if defined LINUX && !defined NOPAM
+ /* only root is able to read the /etc/shadow passwd, a normal
+ user even can't read his own encrypted passwd */
+ if (osl_equalPasswords(p->m_pPasswd.pw_passwd, pszPasswd) ||
+ osl_PamAuthentification(pszUserName, pszPasswd))
+ {
+ nError = osl_Security_E_None;
+ } else {
+ char buffer[1024];
+ struct spwd result_buf;
+ struct spwd * pShadowPasswd;
+ buffer[0] = '\0';
+ if (getspnam_r(
+ pszUserName, &result_buf, buffer, sizeof buffer,
+ &pShadowPasswd) == 0 &&
+ pShadowPasswd != NULL)
+ {
+ nError =
+ osl_equalPasswords(
+ pShadowPasswd->sp_pwdp, pszPasswd)
+ ? osl_Security_E_None
+ : osl_Security_E_WrongPassword;
+ } else if (getuid() == 0) {
+ /* mfe: Try to verify the root-password via nis */
+ if (getspnam_r(
+ "root", &result_buf, buffer, sizeof buffer,
+ &pShadowPasswd) == 0 &&
+ pShadowPasswd != NULL &&
+ osl_equalPasswords(
+ pShadowPasswd->sp_pwdp, pszPasswd))
+ {
+ nError = osl_Security_E_None;
+ } else {
+ /* mfe: we can't get via nis (glibc2.0.x has bug in
+ getspnam_r) we try it with the normal getspnam */
+ static pthread_mutex_t pwmutex =
+ PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock(&pwmutex);
+ pShadowPasswd = getspnam("root");
+ pthread_mutex_unlock(&pwmutex);
+ nError =
+ ((pShadowPasswd != NULL &&
+ osl_equalPasswords(
+ pShadowPasswd->sp_pwdp, pszPasswd)) ||
+ osl_PamAuthentification("root", pszPasswd))
+ ? osl_Security_E_None
+ : osl_Security_E_WrongPassword;
+ }
+ }
+ }
+#else
+ char buffer[1024];
+ struct spwd spwdStruct;
+ buffer[0] = '\0';
+#ifndef NEW_SHADOW_API
+ if (getspnam_r(pszUserName, &spwdStruct, buffer, sizeof buffer) != NULL)
+#else
+ if (getspnam_r(pszUserName, &spwdStruct, buffer, sizeof buffer, NULL) == 0)
+#endif
+ {
+ char salt[3];
+ char * cryptPasswd;
+ strncpy(salt, spwdStruct.sp_pwdp, 2);
+ salt[2] = '\0';
+ cryptPasswd = (char *) crypt(pszPasswd, salt);
+ if (strcmp(spwdStruct.sp_pwdp, cryptPasswd) == 0) {
+ nError = osl_Security_E_None;
+ } else if (getuid() == 0 &&
+#ifndef NEW_SHADOW_API
+ (getspnam_r("root", &spwdStruct, buffer, sizeof buffer) != NULL))
+#else
+ (getspnam_r("root", &spwdStruct, buffer, sizeof buffer, NULL) == 0))
+#endif
+ {
+ /* if current process is running as root, allow to logon
+ as any other user */
+ strncpy(salt, spwdStruct.sp_pwdp, 2);
+ salt[2] = '\0';
+ cryptPasswd = (char *) crypt(pszPasswd, salt);
+ if (strcmp(spwdStruct.sp_pwdp, cryptPasswd) == 0) {
+ nError = osl_Security_E_None;
+ }
+ } else {
+ nError = osl_Security_E_WrongPassword;
+ }
+ }
+#endif
+ }
+ }
+ }
+ if (nError == osl_Security_E_None) {
+ *pSecurity = p;
+ } else {
+ deleteSecurityImpl(p);
+ *pSecurity = NULL;
+ }
+ return nError;
+
+#endif
+}
+
+oslSecurityError SAL_CALL osl_loginUserOnFileServer(
+ rtl_uString *strUserName,
+ rtl_uString *strPasswd,
+ rtl_uString *strFileServer,
+ oslSecurity *pSecurity
+ )
+{
+ (void) strUserName; /* unused */
+ (void) strPasswd; /* unused */
+ (void) strFileServer; /* unused */
+ (void) pSecurity; /* unused */
+ return osl_Security_E_UserUnknown;
+}
+
+
+sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **ustrIdent)
+{
+ sal_Bool bRet=sal_False;
+ sal_Char pszIdent[1024];
+
+ pszIdent[0] = '\0';
+
+ bRet = osl_psz_getUserIdent(Security,pszIdent,sizeof(pszIdent));
+
+ rtl_string2UString( ustrIdent, pszIdent, rtl_str_getLength( pszIdent ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*ustrIdent != NULL);
+
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_psz_getUserIdent(oslSecurity Security, sal_Char *pszIdent, sal_uInt32 nMax)
+{
+ sal_Char buffer[32];
+ sal_Int32 nChr;
+
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
+
+ if (pSecImpl == NULL)
+ return sal_False;
+
+ nChr = snprintf(buffer, sizeof(buffer), "%u", pSecImpl->m_pPasswd.pw_uid);
+ if ( nChr < 0 || SAL_INT_CAST(sal_uInt32, nChr) >= sizeof(buffer)
+ || SAL_INT_CAST(sal_uInt32, nChr) >= nMax )
+ return sal_False; /* leave *pszIdent unmodified in case of failure */
+
+ memcpy(pszIdent, buffer, nChr+1);
+ return sal_True;
+}
+
+sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **ustrName)
+{
+ sal_Bool bRet=sal_False;
+ sal_Char pszName[1024];
+
+ pszName[0] = '\0';
+
+ bRet = osl_psz_getUserName(Security,pszName,sizeof(pszName));
+
+ rtl_string2UString( ustrName, pszName, rtl_str_getLength( pszName ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*ustrName != NULL);
+
+ return bRet;
+}
+
+
+
+static sal_Bool SAL_CALL osl_psz_getUserName(oslSecurity Security, sal_Char* pszName, sal_uInt32 nMax)
+{
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
+
+ if (pSecImpl == NULL)
+ return sal_False;
+
+ strncpy(pszName, pSecImpl->m_pPasswd.pw_name, nMax);
+
+ return sal_True;
+}
+
+sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
+{
+ sal_Bool bRet=sal_False;
+ sal_Char pszDirectory[PATH_MAX];
+
+ pszDirectory[0] = '\0';
+
+ bRet = osl_psz_getHomeDir(Security,pszDirectory,sizeof(pszDirectory));
+
+ if ( bRet == sal_True )
+ {
+ rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pustrDirectory != NULL);
+ osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
+ }
+
+ return bRet;
+}
+
+
+static sal_Bool SAL_CALL osl_psz_getHomeDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
+{
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
+
+ if (pSecImpl == NULL)
+ return sal_False;
+
+ /* if current user, check also environment for HOME */
+ if (getuid() == pSecImpl->m_pPasswd.pw_uid)
+ {
+ sal_Char *pStr = NULL;
+#ifdef SOLARIS
+ char buffer[8192];
+
+ struct passwd pwd;
+ struct passwd *ppwd;
+
+#ifdef _POSIX_PTHREAD_SEMANTICS
+ if ( 0 != getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &ppwd ) )
+ ppwd = NULL;
+#else
+ ppwd = getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer) );
+#endif
+
+ if ( ppwd )
+ pStr = ppwd->pw_dir;
+#else
+ pStr = getenv("HOME");
+#endif
+
+ if ((pStr != NULL) && (strlen(pStr) > 0) &&
+ (access(pStr, 0) == 0))
+ strncpy(pszDirectory, pStr, nMax);
+ else
+ strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
+ }
+ else
+ strncpy(pszDirectory, pSecImpl->m_pPasswd.pw_dir, nMax);
+
+ return sal_True;
+}
+
+sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
+{
+ sal_Bool bRet = sal_False;
+ sal_Char pszDirectory[PATH_MAX];
+
+ pszDirectory[0] = '\0';
+
+ bRet = osl_psz_getConfigDir(Security,pszDirectory,sizeof(pszDirectory));
+
+ if ( bRet == sal_True )
+ {
+ rtl_string2UString( pustrDirectory, pszDirectory, rtl_str_getLength( pszDirectory ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pustrDirectory != NULL);
+ osl_getFileURLFromSystemPath( *pustrDirectory, pustrDirectory );
+ }
+
+ return bRet;
+}
+
+#ifndef MACOSX
+
+static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
+{
+ sal_Char *pStr = getenv("XDG_CONFIG_HOME");
+
+ if ((pStr == NULL) || (strlen(pStr) == 0) ||
+ (access(pStr, 0) != 0))
+ return (osl_psz_getHomeDir(Security, pszDirectory, nMax));
+
+ strncpy(pszDirectory, pStr, nMax);
+ return sal_True;
+}
+
+#else
+
+/*
+ * FIXME: rewrite to use more flexible
+ * NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)
+ * as soon as we can bumb the baseline to Tiger (for NSApplicationSupportDirectory) and have
+ * support for Objective-C in the build environment
+ */
+
+#define MACOSX_CONFIG_DIR "/Library/Application Support"
+static sal_Bool SAL_CALL osl_psz_getConfigDir(oslSecurity Security, sal_Char* pszDirectory, sal_uInt32 nMax)
+{
+ if( osl_psz_getHomeDir(Security, pszDirectory, nMax - sizeof(MACOSX_CONFIG_DIR) + 1) )
+ {
+ strcat( pszDirectory, MACOSX_CONFIG_DIR );
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+#endif
+
+sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
+{
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl *)Security;
+
+ if (pSecImpl == NULL)
+ return sal_False;
+
+ if (pSecImpl->m_pPasswd.pw_uid != 0)
+ return (sal_False);
+
+ return (sal_True);
+}
+
+void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
+{
+ deleteSecurityImpl(Security);
+}
+
+
+sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
+{
+ (void) Security; /* unused */
+ return sal_False;
+}
+
+void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
+{
+ (void) Security; /* unused */
+}
diff --git a/sal/osl/unx/semaphor.c b/sal/osl/unx/semaphor.c
new file mode 100644
index 000000000000..c514b2dacff6
--- /dev/null
+++ b/sal/osl/unx/semaphor.c
@@ -0,0 +1,314 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/semaphor.h>
+#include <osl/diagnose.h>
+
+#ifndef OSL_USE_SYS_V_SEMAPHORE
+
+/* This is the (default) POSIX thread-local semaphore variant */
+
+/*
+ Implemetation notes:
+ The void* represented by oslSemaphore is used
+ as a pointer to an sem_t struct
+*/
+
+/*****************************************************************************/
+/* osl_createSemaphore */
+/*****************************************************************************/
+
+oslSemaphore SAL_CALL osl_createSemaphore(sal_uInt32 initialCount)
+{
+ int ret = 0;
+ oslSemaphore Semaphore;
+
+ Semaphore= malloc(sizeof(sem_t));
+
+ OSL_ASSERT(Semaphore); /* ptr valid? */
+
+ if ( Semaphore == 0 )
+ {
+ return 0;
+ }
+
+ /* unnamed semaphore, not shared between processes */
+
+ ret= sem_init((sem_t*)Semaphore, 0, initialCount);
+
+ /* create failed? */
+ if (ret != 0)
+ {
+ OSL_TRACE("osl_createSemaphore failed. Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+
+ free(Semaphore);
+ Semaphore = NULL;
+ }
+
+ return Semaphore;
+}
+
+/*****************************************************************************/
+/* osl_destroySemaphore */
+/*****************************************************************************/
+void SAL_CALL osl_destroySemaphore(oslSemaphore Semaphore)
+{
+ if(Semaphore) /* ptr valid? */
+ {
+ sem_destroy((sem_t*)Semaphore);
+ free(Semaphore);
+ }
+}
+
+/*****************************************************************************/
+/* osl_acquireSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_acquireSemaphore(oslSemaphore Semaphore) {
+
+ OSL_ASSERT(Semaphore != 0); /* abort in debug mode */
+
+ if (Semaphore != 0) /* be tolerant in release mode */
+ {
+ return (sem_wait((sem_t*)Semaphore) == 0);
+ }
+
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_tryToAcquireSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_tryToAcquireSemaphore(oslSemaphore Semaphore) {
+
+ OSL_ASSERT(Semaphore != 0); /* abort in debug mode */
+ if (Semaphore != 0) /* be tolerant in release mode */
+ {
+ return (sem_trywait((sem_t*)Semaphore) == 0);
+ }
+
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_releaseSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_releaseSemaphore(oslSemaphore Semaphore) {
+
+ OSL_ASSERT(Semaphore != 0); /* abort in debug mode */
+
+ if (Semaphore != 0) /* be tolerant in release mode */
+ {
+ return (sem_post((sem_t*)Semaphore) == 0);
+ }
+
+ return sal_False;
+}
+
+#else /* OSL_USE_SYS_V_SEMAPHORE */
+
+/*******************************************************************************/
+
+/* This is the SYS V private semaphore variant */
+
+/*
+ Implemetation notes:
+ The void* represented by oslSemaphore is used
+ as a pointer to an osl_TSemImpl struct
+*/
+
+
+#if defined(NETBSD)
+union semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
+ u_short *array; /* array for GETALL & SETALL */
+};
+#endif
+
+typedef struct _osl_TSemImpl
+{
+ int m_Id;
+
+} osl_TSemImpl;
+
+/*****************************************************************************/
+/* osl_createSemaphore */
+/*****************************************************************************/
+oslSemaphore SAL_CALL osl_createSemaphore(sal_uInt32 initialCount)
+{
+ union semun arg;
+
+ oslSemaphore Semaphore;
+ osl_TSemImpl* pSem;
+
+ Semaphore= malloc(sizeof(osl_TSemImpl));
+ OSL_POSTCOND(Semaphore, "malloc failed\n"); /* ptr valid? */
+
+ pSem= (osl_TSemImpl*)Semaphore;
+
+
+ /* unnamed (private) semaphore */
+
+ pSem->m_Id= semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
+
+
+ /* create failed? */
+ if (pSem->m_Id < 0)
+ {
+ OSL_TRACE("osl_createSemaphore failed (semget). Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+
+ free(Semaphore);
+ return 0;
+ }
+
+ /* set initial count */
+
+ arg.val= initialCount;
+
+ if(semctl(pSem->m_Id, 0, SETVAL, arg) < 0)
+ {
+ OSL_TRACE("osl_createSemaphore failed (semctl(SETVAL)). Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+
+ if(semctl(pSem->m_Id, 0, IPC_RMID, arg) < 0)
+ {
+ OSL_TRACE("semctl(IPC_RMID) failed. Errno: %d; %s\n", errno, strerror(errno));
+ }
+
+ free(Semaphore);
+ return 0;
+ }
+
+
+ return Semaphore;
+}
+
+/*****************************************************************************/
+/* osl_destroySemaphore */
+/*****************************************************************************/
+void SAL_CALL osl_destroySemaphore(oslSemaphore Semaphore) {
+
+ if(Semaphore) /* ptr valid? */
+ {
+ union semun arg;
+
+ osl_TSemImpl* pSem= (osl_TSemImpl*)Semaphore;
+
+ if(semctl(pSem->m_Id, 0, IPC_RMID, arg) < 0)
+
+ {
+ OSL_TRACE("osl_destroySemaphore failed. (semctl(IPC_RMID)). Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+ }
+
+ free(Semaphore);
+ }
+}
+
+/*****************************************************************************/
+/* osl_acquireSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_acquireSemaphore(oslSemaphore Semaphore) {
+
+ /* abort in debug mode */
+ OSL_PRECOND(Semaphore != 0, "Semaphore not created\n");
+
+
+ if (Semaphore != 0) /* be tolerant in release mode */
+ {
+ struct sembuf op;
+ osl_TSemImpl* pSem= (osl_TSemImpl*)Semaphore;
+
+ op.sem_num= 0;
+ op.sem_op= -1;
+ op.sem_flg= SEM_UNDO;
+
+ return semop(pSem->m_Id, &op, 1) >= 0;
+
+ }
+
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_tryToAcquireSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_tryToAcquireSemaphore(oslSemaphore Semaphore) {
+
+ /* abort in debug mode */
+ OSL_PRECOND(Semaphore != 0, "Semaphore not created\n");
+
+ if (Semaphore != 0) /* be tolerant in release mode */
+ {
+ struct sembuf op;
+ osl_TSemImpl* pSem= (osl_TSemImpl*)Semaphore;
+
+ op.sem_num= 0;
+ op.sem_op= -1;
+ op.sem_flg= SEM_UNDO | IPC_NOWAIT;
+
+ return semop(pSem->m_Id, &op, 1) >= 0;
+ }
+
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_releaseSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_releaseSemaphore(oslSemaphore Semaphore)
+{
+
+ /* abort in debug mode */
+ OSL_PRECOND(Semaphore != 0, "Semaphore not created\n");
+
+ if (Semaphore != 0) /* be tolerant in release mode */
+ {
+ struct sembuf op;
+ osl_TSemImpl* pSem= (osl_TSemImpl*)Semaphore;
+
+ op.sem_num= 0;
+ op.sem_op= 1;
+ op.sem_flg= SEM_UNDO;
+
+ return semop(pSem->m_Id, &op, 1) >= 0;
+ }
+
+ return sal_False;
+}
+
+#endif /* OSL_USE_SYS_V_SEMAPHORE */
+
diff --git a/sal/osl/unx/signal.c b/sal/osl/unx/signal.c
new file mode 100644
index 000000000000..5563375d9567
--- /dev/null
+++ b/sal/osl/unx/signal.c
@@ -0,0 +1,1093 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+/* system headers */
+#include "system.h"
+
+#define MAX_STACK_FRAMES 256
+
+#if defined( MACOSX )
+
+#if defined( INTEL )
+#include "backtrace.h"
+#define INCLUDE_BACKTRACE
+#define STACKTYPE "MacOsX_X86"
+#endif /* INTEL */
+
+#endif /* MACOSX */
+
+#ifdef LINUX
+#include <execinfo.h>
+#include <link.h>
+#define INCLUDE_BACKTRACE
+#define STACKTYPE "Linux"
+#endif
+
+#ifdef SOLARIS
+
+#include "backtrace.h"
+#define INCLUDE_BACKTRACE
+
+#if defined( SPARC )
+#define STACKTYPE "Solaris_Sparc"
+#elif defined( INTEL )
+#define STACKTYPE "Solaris_X86"
+#else
+#define STACKTYPE "Solaris_Unknown"
+#endif
+
+#endif /* defined SOLARIS */
+
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <osl/signal.h>
+#include <osl/process.h>
+#include <osl/thread.h>
+#include <rtl/bootstrap.h>
+#include <rtl/digest.h>
+
+#include "file_path_helper.h"
+
+#define ACT_IGNORE 1
+#define ACT_EXIT 2
+#define ACT_SYSTEM 3
+#define ACT_HIDE 4
+#ifdef SAL_ENABLE_CRASH_REPORT
+# define ACT_ABORT 5
+#else
+# define ACT_ABORT ACT_SYSTEM
+#endif
+
+#define MAX_PATH_LEN 2048
+
+typedef struct _oslSignalHandlerImpl
+{
+ oslSignalHandlerFunction Handler;
+ void* pData;
+ struct _oslSignalHandlerImpl* pNext;
+} oslSignalHandlerImpl;
+
+static struct SignalAction
+{
+ int Signal;
+ int Action;
+ void (*Handler)(int);
+} Signals[] =
+{
+ { SIGHUP, ACT_IGNORE, NULL }, /* hangup */
+ { SIGINT, ACT_EXIT, NULL }, /* interrupt (rubout) */
+ { SIGQUIT, ACT_EXIT, NULL }, /* quit (ASCII FS) */
+ { SIGILL, ACT_SYSTEM, NULL }, /* illegal instruction (not reset when caught) */
+/* changed from ACT_ABOUT to ACT_SYSTEM to try and get collector to run*/
+ { SIGTRAP, ACT_ABORT, NULL }, /* trace trap (not reset when caught) */
+#if ( SIGIOT != SIGABRT )
+ { SIGIOT, ACT_ABORT, NULL }, /* IOT instruction */
+#endif
+ { SIGABRT, ACT_ABORT, NULL }, /* used by abort, replace SIGIOT in the future */
+#ifdef SIGEMT
+ { SIGEMT, ACT_SYSTEM, NULL }, /* EMT instruction */
+/* changed from ACT_ABORT to ACT_SYSTEM to remove handler*/
+/* SIGEMT may also be used by the profiler - so it is probably not a good
+plan to have the new handler use this signal*/
+#endif
+ { SIGFPE, ACT_ABORT, NULL }, /* floating point exception */
+ { SIGKILL, ACT_SYSTEM, NULL }, /* kill (cannot be caught or ignored) */
+ { SIGBUS, ACT_ABORT, NULL }, /* bus error */
+ { SIGSEGV, ACT_ABORT, NULL }, /* segmentation violation */
+#ifdef SIGSYS
+ { SIGSYS, ACT_ABORT, NULL }, /* bad argument to system call */
+#endif
+ { SIGPIPE, ACT_HIDE, NULL }, /* write on a pipe with no one to read it */
+ { SIGALRM, ACT_EXIT, NULL }, /* alarm clock */
+ { SIGTERM, ACT_EXIT, NULL }, /* software termination signal from kill */
+ { SIGUSR1, ACT_SYSTEM, NULL }, /* user defined signal 1 */
+ { SIGUSR2, ACT_SYSTEM, NULL }, /* user defined signal 2 */
+ { SIGCHLD, ACT_SYSTEM, NULL }, /* child status change */
+#ifdef SIGPWR
+ { SIGPWR, ACT_IGNORE, NULL }, /* power-fail restart */
+#endif
+ { SIGWINCH, ACT_IGNORE, NULL }, /* window size change */
+ { SIGURG, ACT_EXIT, NULL }, /* urgent socket condition */
+#ifdef SIGPOLL
+ { SIGPOLL, ACT_EXIT, NULL }, /* pollable event occured */
+#endif
+ { SIGSTOP, ACT_SYSTEM, NULL }, /* stop (cannot be caught or ignored) */
+ { SIGTSTP, ACT_SYSTEM, NULL }, /* user stop requested from tty */
+ { SIGCONT, ACT_SYSTEM, NULL }, /* stopped process has been continued */
+ { SIGTTIN, ACT_SYSTEM, NULL }, /* background tty read attempted */
+ { SIGTTOU, ACT_SYSTEM, NULL }, /* background tty write attempted */
+ { SIGVTALRM, ACT_EXIT, NULL }, /* virtual timer expired */
+ { SIGPROF, ACT_SYSTEM, NULL }, /* profiling timer expired */
+/*Change from ACT_EXIT to ACT_SYSTEM for SIGPROF is so that profiling signals do
+not get taken by the new handler - the new handler does not pass on context
+information which causes 'collect' to crash. This is a way of avoiding
+what looks like a bug in the new handler*/
+ { SIGXCPU, ACT_ABORT, NULL }, /* exceeded cpu limit */
+ { SIGXFSZ, ACT_ABORT, NULL } /* exceeded file size limit */
+};
+const int NoSignals = sizeof(Signals) / sizeof(struct SignalAction);
+
+static sal_Bool bErrorReportingEnabled = sal_True;
+static sal_Bool bInitSignal = sal_False;
+static oslMutex SignalListMutex;
+static oslSignalHandlerImpl* SignalList;
+static sal_Bool bDoHardKill = sal_False;
+static sal_Bool bSetSEGVHandler = sal_False;
+static sal_Bool bSetWINCHHandler = sal_False;
+static sal_Bool bSetILLHandler = sal_False;
+
+static void SignalHandlerFunction(int);
+
+static void getExecutableName_Impl (rtl_String ** ppstrProgName)
+{
+ rtl_uString * ustrProgFile = 0;
+ osl_getExecutableFile (&ustrProgFile);
+ if (ustrProgFile)
+ {
+ rtl_uString * ustrProgName = 0;
+ osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile, &ustrProgName);
+ if (ustrProgName != 0)
+ {
+ rtl_uString2String (
+ ppstrProgName,
+ rtl_uString_getStr (ustrProgName), rtl_uString_getLength (ustrProgName),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+ rtl_uString_release (ustrProgName);
+ }
+ rtl_uString_release (ustrProgFile);
+ }
+}
+
+static sal_Bool is_soffice_Impl (void)
+{
+ sal_Int32 idx = -1;
+ rtl_String * strProgName = 0;
+
+ getExecutableName_Impl (&strProgName);
+ if (strProgName)
+ {
+ idx = rtl_str_indexOfStr (rtl_string_getStr (strProgName), "soffice");
+ rtl_string_release (strProgName);
+ }
+ return (idx != -1);
+}
+
+static sal_Bool InitSignal()
+{
+ int i;
+ struct sigaction act;
+ struct sigaction oact;
+ sigset_t unset;
+
+ if (is_soffice_Impl())
+ {
+ sal_uInt32 argi;
+ sal_uInt32 argc;
+ rtl_uString *ustrCommandArg = 0;
+
+ argc = osl_getCommandArgCount();
+ for ( argi = 0; argi < argc; argi++ )
+ {
+ if (osl_Process_E_None == osl_getCommandArg (argi, &ustrCommandArg))
+ {
+ if (0 == rtl_ustr_ascii_compare (rtl_uString_getStr (ustrCommandArg), "-bean"))
+ {
+ bDoHardKill = sal_True;
+ break;
+ }
+ }
+ }
+ if (ustrCommandArg)
+ {
+ rtl_uString_release (ustrCommandArg);
+ ustrCommandArg = 0;
+ }
+
+ // WORKAROUND FOR SEGV HANDLER CONFLICT
+ //
+ // the java jit needs SIGSEGV for proper work
+ // and we need SIGSEGV for the office crashguard
+ //
+ // TEMPORARY SOLUTION:
+ // the office sets the signal handler during startup
+ // java can than overwrite it, if needed
+ bSetSEGVHandler = sal_True;
+
+ // WORKAROUND FOR WINCH HANDLER (SEE ABOVE)
+ bSetWINCHHandler = sal_True;
+
+ // WORKAROUND FOR ILLEGAL INSTRUCTION HANDLER (SEE ABOVE)
+ bSetILLHandler = sal_True;
+ }
+
+ SignalListMutex = osl_createMutex();
+
+ act.sa_handler = SignalHandlerFunction;
+ act.sa_flags = SA_RESTART;
+
+ sigfillset(&(act.sa_mask));
+
+ /* Initialize the rest of the signals */
+ for (i = 0; i < NoSignals; i++)
+ {
+ /* hack: stomcatd is attaching JavaVM wich dont work with an sigaction(SEGV) */
+ if ((bSetSEGVHandler || Signals[i].Signal != SIGSEGV)
+ && (bSetWINCHHandler || Signals[i].Signal != SIGWINCH)
+ && (bSetILLHandler || Signals[i].Signal != SIGILL))
+ {
+ if (Signals[i].Action != ACT_SYSTEM)
+ {
+ if (Signals[i].Action == ACT_HIDE)
+ {
+ struct sigaction ign;
+
+ ign.sa_handler = SIG_IGN;
+ ign.sa_flags = 0;
+ sigemptyset(&ign.sa_mask);
+
+ if (sigaction(Signals[i].Signal, &ign, &oact) == 0)
+ Signals[i].Handler = oact.sa_handler;
+ else
+ Signals[i].Handler = SIG_DFL;
+ }
+ else
+ if (sigaction(Signals[i].Signal, &act, &oact) == 0)
+ Signals[i].Handler = oact.sa_handler;
+ else
+ Signals[i].Handler = SIG_DFL;
+ }
+ }
+ }
+
+ /* Clear signal mask inherited from parent process (on Mac OS X, upon a
+ crash soffice re-execs itself from within the signal handler, so the
+ second soffice would have the guilty signal blocked and would freeze upon
+ encountering a similar crash again): */
+ if (sigemptyset(&unset) < 0 ||
+ pthread_sigmask(SIG_SETMASK, &unset, NULL) < 0)
+ {
+ OSL_TRACE("sigemptyset or pthread_sigmask failed");
+ }
+
+ return sal_True;
+}
+
+static sal_Bool DeInitSignal()
+{
+ int i;
+ struct sigaction act;
+
+ act.sa_flags = 0;
+ sigemptyset(&(act.sa_mask));
+
+ /* Initialize the rest of the signals */
+ for (i = NoSignals - 1; i >= 0; i--)
+ if (Signals[i].Action != ACT_SYSTEM)
+ {
+ act.sa_handler = Signals[i].Handler;
+
+ sigaction(Signals[i].Signal, &act, NULL);
+ }
+
+ osl_destroyMutex(SignalListMutex);
+
+ return sal_False;
+}
+
+#if defined (SAL_ENABLE_CRASH_REPORT) && defined(INCLUDE_BACKTRACE)
+
+/*****************************************************************************/
+/* Generate MD5 checksum */
+/*****************************************************************************/
+
+static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
+{
+ sal_uInt32 nBytesProcessed = 0;
+
+ FILE *fp = fopen( filename, "r" );
+
+ if ( fp )
+ {
+ rtlDigest digest = rtl_digest_createMD5();
+
+ if ( digest )
+ {
+ size_t nBytesRead;
+ sal_uInt8 buffer[4096];
+ rtlDigestError error = rtl_Digest_E_None;
+
+ while ( rtl_Digest_E_None == error &&
+ 0 != (nBytesRead = fread( buffer, 1, sizeof(buffer), fp )) )
+ {
+ error = rtl_digest_updateMD5( digest, buffer, nBytesRead );
+ nBytesProcessed += nBytesRead;
+ }
+
+ if ( rtl_Digest_E_None == error )
+ {
+ error = rtl_digest_getMD5( digest, pChecksum, nChecksumLen );
+ }
+
+ if ( rtl_Digest_E_None != error )
+ nBytesProcessed = 0;
+
+ rtl_digest_destroyMD5( digest );
+ }
+
+ fclose( fp );
+ }
+
+ return nBytesProcessed;
+}
+
+/*****************************************************************************/
+/* Call crash reporter */
+/*****************************************************************************/
+
+/* Helper function to encode and write a string to a stream */
+
+static int fputs_xml( const char *string, FILE *stream )
+{
+ int result = 0;
+
+ while ( result >= 0 && *string )
+ {
+ switch( *string )
+ {
+ case '&':
+ result = fputs( "&amp;", stream );
+ break;
+ case '<':
+ result = fputs( "&lt;", stream );
+ break;
+ case '>':
+ result = fputs( "&gt;", stream );
+ break;
+ default:
+ result = fputc( *string, stream );
+ break;
+ }
+
+ string++;
+ }
+
+ return result;
+}
+#endif
+
+/* Create intermediate files and run crash reporter */
+
+#define REPORTENV_PARAM "-crashreportenv:"
+
+#if defined SAL_ENABLE_CRASH_REPORT && defined INCLUDE_BACKTRACE && \
+ defined LINUX
+
+typedef struct
+{
+ const char *name;
+ ElfW(Off) offset;
+} dynamic_entry;
+
+static int
+callback(struct dl_phdr_info *info, size_t size, void *data)
+{
+ const ElfW(Phdr) *pDynamic = NULL;
+
+ if (size == sizeof(struct dl_phdr_info))
+ {
+ int i;
+ for (i = 0; i < info->dlpi_phnum; ++i)
+ {
+ if (info->dlpi_phdr[i].p_type == PT_DYNAMIC)
+ {
+ pDynamic = &(info->dlpi_phdr[i]);
+ break;
+ }
+ }
+ }
+
+ if (pDynamic)
+ {
+ char buffer[100];
+ int len;
+ char exe[PATH_MAX];
+ const char *dsoname = info->dlpi_name;
+
+ dynamic_entry* entry = (dynamic_entry*)data;
+
+ if (strcmp(dsoname, "") == 0)
+ {
+ snprintf(buffer, sizeof(buffer), "/proc/%d/exe", getpid());
+ if ((len = readlink(buffer, exe, PATH_MAX)) != -1)
+ {
+ exe[len] = '\0';
+ dsoname = exe;
+ }
+ }
+
+ if (strcmp(dsoname, entry->name) == 0)
+ {
+ entry->offset = pDynamic->p_offset;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Get the location of the .dynamic section offset for the given elf file.
+ * i.e. same as the "Offset" value shown for DYNAMIC from readelf -l foo
+ *
+ * We want to know this value so that if the binaries have been modifed
+ * by prelink then we can still process the call stack on server side
+ * by comparing this value to that of an "un-prelinked but known to be
+ * otherwise equivalent" version of those binaries and adjust the call
+ * stack addresses by the differences between .dynamic addresses so as
+ * to be able to map the prelinked addresses back to the unprelinked
+ * addresses
+ *
+ * cmc@openoffice.org
+ */
+static ElfW(Off)
+dynamic_section_offset(const char *name)
+{
+ dynamic_entry entry;
+
+ entry.name = name;
+ entry.offset = 0;
+
+ dl_iterate_phdr(callback, &entry);
+
+ return entry.offset;
+}
+#endif
+
+static int ReportCrash( int Signal )
+{
+#ifdef SAL_ENABLE_CRASH_REPORT
+ static sal_Bool bCrashReporterExecuted = sal_False;
+ sal_Bool bAutoCrashReport = sal_False;
+
+ sal_uInt32 argi;
+ sal_uInt32 argc;
+ rtl_uString *ustrCommandArg = NULL;
+
+ if ( !bErrorReportingEnabled )
+ return -1;
+
+ argc = osl_getCommandArgCount();
+
+ for ( argi = 0; argi < argc; argi++ )
+ {
+ if ( osl_Process_E_None == osl_getCommandArg( argi, &ustrCommandArg ) )
+ {
+ if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg ), "-nocrashreport" ) )
+ {
+ rtl_uString_release( ustrCommandArg );
+ return -1;
+ }
+ else if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg ), "-autocrashreport" ) )
+ {
+ bAutoCrashReport = sal_True;
+ }
+ else if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength(
+ rtl_uString_getStr( ustrCommandArg ), rtl_uString_getLength( ustrCommandArg ),
+ REPORTENV_PARAM, strlen(REPORTENV_PARAM) )
+ )
+ {
+ rtl_uString *ustrEnvironment = NULL;
+ rtl_String *strEnv = NULL;
+
+ rtl_uString_newFromStr( &ustrEnvironment, rtl_uString_getStr( ustrCommandArg ) + strlen(REPORTENV_PARAM) );
+
+ if ( ustrEnvironment )
+ {
+ rtl_uString2String(
+ &strEnv,
+ rtl_uString_getStr( ustrEnvironment ), rtl_uString_getLength( ustrEnvironment ),
+ osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
+ );
+
+ if ( strEnv )
+ {
+ putenv( rtl_string_getStr( strEnv ) );
+ rtl_string_release( strEnv );
+ }
+
+ rtl_uString_release( ustrEnvironment );
+ }
+
+ }
+
+ }
+ }
+
+ if ( ustrCommandArg )
+ rtl_uString_release( ustrCommandArg );
+
+ if ( !bCrashReporterExecuted )
+ {
+ int i;
+ /* struct sigaction act; */
+
+ for (i = 0; i < NoSignals; i++)
+ {
+ if (Signals[i].Signal == Signal && Signals[i].Action == ACT_ABORT )
+ {
+ int ret;
+ char szShellCmd[512] = { '\0' };
+ char *pXMLTempName = NULL;
+ char *pStackTempName = NULL;
+ char *pChecksumTempName = NULL;
+
+#ifdef INCLUDE_BACKTRACE
+ char szXMLTempNameBuffer[L_tmpnam];
+ char szChecksumTempNameBuffer[L_tmpnam];
+ char szStackTempNameBuffer[L_tmpnam];
+
+ void *stackframes[MAX_STACK_FRAMES];
+ int iFrame;
+ int nFrames = backtrace( stackframes, sizeof(stackframes)/sizeof(stackframes[0]));
+
+ FILE *xmlout = NULL, *stackout = NULL, *checksumout = NULL;
+ int fdxml, fdstk, fdchksum;
+
+ strncpy( szXMLTempNameBuffer, P_tmpdir, sizeof(szXMLTempNameBuffer) );
+ strncat( szXMLTempNameBuffer, "/crxmlXXXXXX", sizeof(szXMLTempNameBuffer) );
+
+ strncpy( szStackTempNameBuffer, P_tmpdir, sizeof(szStackTempNameBuffer) );
+ strncat( szStackTempNameBuffer, "/crstkXXXXXX", sizeof(szStackTempNameBuffer) );
+
+ strncpy( szChecksumTempNameBuffer, P_tmpdir, sizeof(szChecksumTempNameBuffer) );
+ strncat( szChecksumTempNameBuffer, "/crchkXXXXXX", sizeof(szChecksumTempNameBuffer) );
+
+ fdxml = mkstemp(szXMLTempNameBuffer);
+ fdstk = mkstemp(szStackTempNameBuffer);
+ fdchksum = mkstemp(szChecksumTempNameBuffer);
+
+ xmlout = fdopen( fdxml , "w" );
+ stackout = fdopen( fdstk , "w" );
+ checksumout = fdopen( fdchksum, "w" );
+
+ pXMLTempName = szXMLTempNameBuffer;
+ pStackTempName = szStackTempNameBuffer;
+ pChecksumTempName = szChecksumTempNameBuffer;
+
+
+ if ( xmlout && stackout && checksumout )
+ {
+ fprintf( xmlout, "<errormail:Stack type=\"%s\">\n", STACKTYPE );
+
+ fprintf( checksumout, "<errormail:Checksums type=\"MD5\">\n" );
+
+ for ( iFrame = 0; iFrame < nFrames; iFrame++ )
+ {
+ Dl_info dl_info;
+
+ fprintf( stackout, "0x%" SAL_PRIxUINTPTR ":",
+ SAL_INT_CAST(sal_uIntPtr, stackframes[iFrame]) );
+
+ fprintf( xmlout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%" SAL_PRIxUINTPTR "\"",
+ iFrame,
+ SAL_INT_CAST(sal_uIntPtr, stackframes[iFrame])
+ );
+
+ memset( &dl_info, 0, sizeof(dl_info) );
+
+ /* dladdr may fail */
+ if ( dladdr( stackframes[iFrame], &dl_info) )
+ {
+ const char *dli_fname = NULL;
+ char *dli_fdir = NULL;
+ char szDirectory[PATH_MAX];
+ char szCanonicDirectory[PATH_MAX];
+
+ /* Don't expect that dladdr filled all members of dl_info */
+
+ dli_fname = dl_info.dli_fname ? strrchr( dl_info.dli_fname, '/' ) : NULL;
+ if ( dli_fname )
+ {
+ ++dli_fname;
+ memcpy( szDirectory, dl_info.dli_fname, dli_fname - dl_info.dli_fname );
+ szDirectory[dli_fname - dl_info.dli_fname] = 0;
+
+ dli_fdir = realpath( szDirectory, szCanonicDirectory ) ? szCanonicDirectory : szDirectory;
+
+ if ( *dli_fdir && dli_fdir[ strlen(dli_fdir) - 1 ] != '/' )
+ strcat( dli_fdir, "/" );
+ }
+ else
+ dli_fname = dl_info.dli_fname;
+
+ /* create checksum of library on stack */
+ if ( dli_fname )
+ {
+ sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5];
+
+ sal_uInt32 nBytesProcessed = calc_md5_checksum(
+ dl_info.dli_fname, checksum, sizeof(checksum) );
+ if ( nBytesProcessed )
+ {
+ int j;
+
+ fprintf( checksumout, "<errormail:Checksum sum=\"0x" );
+ for ( j = 0; j < 16; fprintf( checksumout, "%02X", checksum[j++] ) );
+ fprintf( checksumout,
+ "\" bytes=\"%lu\" file=\"%s\"/>\n",
+ SAL_INT_CAST(
+ unsigned long, nBytesProcessed),
+ dli_fname );
+ }
+ }
+
+ if ( dl_info.dli_fbase && dl_info.dli_fname )
+ {
+#ifdef LINUX
+ ElfW(Off) dynamic_offset = dynamic_section_offset(dl_info.dli_fname);
+ fprintf( stackout, " 0x%" SAL_PRI_SIZET "x:", dynamic_offset);
+#endif
+
+ fprintf( stackout, " %s + 0x%" SAL_PRI_PTRDIFFT "x",
+ dl_info.dli_fname,
+ (char*)stackframes[iFrame] - (char*)dl_info.dli_fbase
+ );
+
+ fprintf( xmlout, " rel=\"0x%" SAL_PRI_PTRDIFFT "x\"", (char *)stackframes[iFrame] - (char *)dl_info.dli_fbase );
+ if ( dli_fname )
+ fprintf( xmlout, " name=\"%s\"", dli_fname );
+
+ if ( dli_fdir )
+ fprintf( xmlout, " path=\"%s\"", dli_fdir );
+
+#ifdef LINUX
+ fprintf( xmlout, " dynamicoffset=\"0x%" SAL_PRI_SIZET "x\"", dynamic_offset );
+#endif
+ }
+ else
+ fprintf( stackout, " ????????" );
+
+ if ( dl_info.dli_sname && dl_info.dli_saddr )
+ {
+ fputs( " (", stackout );
+ fputs_xml( dl_info.dli_sname, stackout );
+ fprintf( stackout, " + 0x%" SAL_PRI_PTRDIFFT "x)",
+ (char*)stackframes[iFrame] - (char*)dl_info.dli_saddr );
+
+ fputs( " ordinal=\"", xmlout );
+ fputs_xml( dl_info.dli_sname, xmlout );
+ fprintf( xmlout, "+0x%" SAL_PRI_PTRDIFFT "x\"",
+ (char *)stackframes[iFrame] - (char *)dl_info.dli_saddr );
+ }
+
+ }
+ else /* dladdr failed */
+ {
+ fprintf( stackout, " ????????" );
+ }
+
+ fprintf( stackout, "\n" );
+ fprintf( xmlout, "/>\n" );
+
+ }
+
+ fprintf( xmlout, "</errormail:Stack>\n" );
+ fprintf( checksumout, "</errormail:Checksums>\n" );
+ }
+ else
+ {
+ pXMLTempName = NULL;
+ pStackTempName = NULL;
+ pChecksumTempName = NULL;
+ }
+
+ if ( stackout )
+ fclose( stackout );
+ if ( xmlout )
+ fclose( xmlout );
+ if ( checksumout )
+ fclose( checksumout );
+
+ if ( pXMLTempName && pChecksumTempName && pStackTempName )
+#endif /* INCLUDE_BACKTRACE */
+ {
+ rtl_uString * crashrep_url = NULL;
+ rtl_uString * crashrep_path = NULL;
+ rtl_String * crashrep_path_system = NULL;
+ rtl_string2UString(
+ &crashrep_url,
+ RTL_CONSTASCII_USTRINGPARAM(
+ "$BRAND_BASE_DIR/program/crashrep"),
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+ rtl_bootstrap_expandMacros(&crashrep_url);
+ osl_getSystemPathFromFileURL(crashrep_url, &crashrep_path);
+ rtl_uString2String(
+ &crashrep_path_system,
+ rtl_uString_getStr(crashrep_path),
+ rtl_uString_getLength(crashrep_path),
+ osl_getThreadTextEncoding(),
+ (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR));
+ rtl_uString_release(crashrep_url);
+ rtl_uString_release(crashrep_path);
+#if defined INCLUDE_BACKTRACE && (defined LINUX || defined MACOSX)
+ snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]),
+ "%s -p %d -s %d -xml %s -chksum %s -stack %s -noui%s",
+ rtl_string_getStr(crashrep_path_system),
+ getpid(),
+ Signal,
+ pXMLTempName,
+ pChecksumTempName,
+ pStackTempName,
+ bAutoCrashReport ? " -send" : "" );
+#elif defined INCLUDE_BACKTRACE && defined SOLARIS
+ snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]),
+ "%s -p %d -s %d -xml %s -chksum %s -noui%s",
+ rtl_string_getStr(crashrep_path_system),
+ getpid(),
+ Signal,
+ pXMLTempName,
+ pChecksumTempName,
+ bAutoCrashReport ? " -send" : "" );
+#else
+ snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]),
+ "%s -p %d -s %d -noui%s",
+ rtl_string_getStr(crashrep_path_system),
+ getpid(), Signal, bAutoCrashReport ? " -send" : "" );
+#endif
+ rtl_string_release(crashrep_path_system);
+ }
+
+ ret = szShellCmd[0] == '\0' ? -1 : system( szShellCmd );
+
+ if ( pXMLTempName )
+ unlink( pXMLTempName );
+
+ if ( pStackTempName )
+ unlink( pStackTempName );
+
+ if ( pChecksumTempName )
+ unlink( pChecksumTempName );
+
+ if ( -1 != ret )
+ {
+ bCrashReporterExecuted = sal_True;
+ return 1;
+ }
+ else
+ return -1;
+
+ }
+ }
+
+ return 0;
+ }
+
+ return 1;
+#else /* defined SAL_ENABLE_CRASH_REPORT */
+ /* the utility crash_report is not build, so do the same as when
+ the option -nocrashreport is used */
+ (void) Signal; // avoid warnings
+ return -1;
+#endif /* defined SAL_ENABLE_CRASH_REPORT */
+}
+
+static void PrintStack( int sig )
+{
+#if ! defined(MACOSX) || defined(INCLUDE_BACKTRACE)
+ void *buffer[MAX_STACK_FRAMES];
+ int size = backtrace( buffer, sizeof(buffer) / sizeof(buffer[0]) );
+#endif
+
+ fprintf( stderr, "\n\nFatal exception: Signal %d\n", sig );
+
+#if defined(MACOSX) && ! defined(INCLUDE_BACKTRACE)
+ fprintf( stderr, "Please turn on Enable Crash Reporting and\nAutomatic Display of Crashlogs in the Console application\n" );
+#else
+ if ( size > 0 )
+ {
+ fputs( "Stack:\n", stderr );
+ backtrace_symbols_fd( buffer, size, fileno(stderr) );
+ }
+#endif
+}
+
+static oslSignalAction CallSignalHandler(oslSignalInfo *pInfo)
+{
+ oslSignalHandlerImpl* pHandler = SignalList;
+ oslSignalAction Action = osl_Signal_ActCallNextHdl;
+
+ while (pHandler != NULL)
+ {
+ if ((Action = pHandler->Handler(pHandler->pData, pInfo))
+ != osl_Signal_ActCallNextHdl)
+ break;
+
+ pHandler = pHandler->pNext;
+ }
+
+ return Action;
+}
+
+void CallSystemHandler(int Signal)
+{
+ int i;
+ struct sigaction act;
+
+ for (i = 0; i < NoSignals; i++)
+ {
+ if (Signals[i].Signal == Signal)
+ break;
+ }
+
+ if (i < NoSignals)
+ {
+ if ((Signals[i].Handler == NULL) ||
+ (Signals[i].Handler == SIG_DFL) ||
+ (Signals[i].Handler == SIG_IGN) ||
+ (Signals[i].Handler == SIG_ERR))
+ {
+ switch (Signals[i].Action)
+ {
+ case ACT_EXIT: /* terminate */
+ /* prevent dumping core on exit() */
+ _exit(255);
+ break;
+
+ case ACT_ABORT: /* terminate witch core dump */
+ ReportCrash( Signal );
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigemptyset(&(act.sa_mask));
+ sigaction(SIGABRT, &act, NULL);
+ PrintStack( Signal );
+ abort();
+ break;
+
+ case ACT_IGNORE: /* ignore */
+ break;
+
+ default: /* should never happen */
+ OSL_ASSERT(0);
+ }
+ }
+ else
+ (*Signals[i].Handler)(Signal);
+ }
+}
+
+
+/*****************************************************************************/
+/* SignalHandlerFunction */
+/*****************************************************************************/
+void SignalHandlerFunction(int Signal)
+{
+ oslSignalInfo Info;
+ struct sigaction act;
+
+ Info.UserSignal = Signal;
+ Info.UserData = NULL;
+
+ switch (Signal)
+ {
+ case SIGBUS:
+ case SIGILL:
+ case SIGSEGV:
+ case SIGIOT:
+#if ( SIGIOT != SIGABRT )
+ case SIGABRT:
+#endif
+ Info.Signal = osl_Signal_AccessViolation;
+ break;
+
+ case -1:
+ Info.Signal = osl_Signal_IntegerDivideByZero;
+ break;
+
+ case SIGFPE:
+ Info.Signal = osl_Signal_FloatDivideByZero;
+ break;
+
+ case SIGINT:
+ case SIGTERM:
+ case SIGQUIT:
+ case SIGHUP:
+ Info.Signal = osl_Signal_Terminate;
+ break;
+
+ default:
+ Info.Signal = osl_Signal_System;
+ break;
+ }
+
+ ReportCrash( Signal );
+
+ /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+ if (bDoHardKill && (Info.Signal == osl_Signal_AccessViolation))
+ _exit(255);
+ /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+
+
+ switch (CallSignalHandler(&Info))
+ {
+ case osl_Signal_ActCallNextHdl:
+ CallSystemHandler(Signal);
+ break;
+
+ case osl_Signal_ActAbortApp:
+ ReportCrash( Signal );
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigemptyset(&(act.sa_mask));
+ sigaction(SIGABRT, &act, NULL);
+ PrintStack( Signal );
+ abort();
+ break;
+
+ case osl_Signal_ActKillApp:
+ /* prevent dumping core on exit() */
+ _exit(255);
+ break;
+ default:
+ break;
+ }
+}
+
+/*****************************************************************************/
+/* osl_addSignalHandler */
+/*****************************************************************************/
+oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData)
+{
+ oslSignalHandlerImpl* pHandler;
+
+ OSL_ASSERT(Handler != NULL);
+ if ( Handler == 0 )
+ {
+ return 0;
+ }
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ pHandler = (oslSignalHandlerImpl*) calloc(1, sizeof(oslSignalHandlerImpl));
+
+ if (pHandler != NULL)
+ {
+ pHandler->Handler = Handler;
+ pHandler->pData = pData;
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler->pNext = SignalList;
+ SignalList = pHandler;
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (pHandler);
+ }
+
+ return (NULL);
+}
+
+/*****************************************************************************/
+/* osl_removeSignalHandler */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler)
+{
+ oslSignalHandlerImpl *pHandler, *pPrevious = NULL;
+
+ OSL_ASSERT(Handler != NULL);
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler = SignalList;
+
+ while (pHandler != NULL)
+ {
+ if (pHandler == Handler)
+ {
+ if (pPrevious)
+ pPrevious->pNext = pHandler->pNext;
+ else
+ SignalList = pHandler->pNext;
+
+ osl_releaseMutex(SignalListMutex);
+
+ if (SignalList == NULL)
+ bInitSignal = DeInitSignal();
+
+ free(pHandler);
+
+ return (sal_True);
+ }
+
+ pPrevious = pHandler;
+ pHandler = pHandler->pNext;
+ }
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (sal_False);
+}
+
+/*****************************************************************************/
+/* osl_raiseSignal */
+/*****************************************************************************/
+oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData)
+{
+ oslSignalInfo Info;
+ oslSignalAction Action;
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ Info.Signal = osl_Signal_User;
+ Info.UserSignal = UserSignal;
+ Info.UserData = UserData;
+
+ Action = CallSignalHandler(&Info);
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (Action);
+}
+
+/*****************************************************************************/
+/* osl_setErrorReporting */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable )
+{
+ sal_Bool bOld = bErrorReportingEnabled;
+ bErrorReportingEnabled = bEnable;
+
+ return bOld;
+}
diff --git a/sal/osl/unx/socket.c b/sal/osl/unx/socket.c
new file mode 100644
index 000000000000..c8faf6c028f5
--- /dev/null
+++ b/sal/osl/unx/socket.c
@@ -0,0 +1,3062 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/socket.h>
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <osl/signal.h>
+
+#include <rtl/alloc.h>
+
+#include <ctype.h>
+#include <sal/types.h>
+
+#include "sockimpl.h"
+
+
+/* defines for poll */
+#ifdef HAVE_POLL_H
+#undef HAVE_POLL_H
+#endif
+
+#if defined(LINUX) || defined(NETBSD) || defined ( FREEBSD ) || defined (MACOSX)
+#include <sys/poll.h>
+#define HAVE_POLL_H
+#endif /* HAVE_POLL_H */
+
+#if defined(SOLARIS)
+#include <poll.h>
+#define HAVE_POLL_H
+#endif /* SOLARIS */
+
+#ifndef HAVE_POLL_H
+#define POLLIN 0x0001
+#define POLLOUT 0x0002
+#define POLLPRI 0x0004
+#endif /* HAVE_POLL_H */
+
+
+/* defines for shutdown */
+#define SD_RECEIVE 0
+#define SD_SEND 1
+#define SD_BOTH 2
+
+
+/*
+ oslSocketAddr is a pointer to a Berkeley struct sockaddr.
+ I refrained from using sockaddr_in because of possible further
+ extensions of this socket-interface (IP-NG?).
+ The intention was to hide all Berkeley data-structures from
+ direct access past the osl-interface.
+
+ The current implementation is internet (IP) centered. All
+ the constructor-functions (osl_create...) take parameters
+ that will probably make sense only in the IP-environment
+ (e.g. because of using the dotted-address-format).
+
+ If the interface will be extended to host other protocol-
+ families, I expect no externally visible changes in the
+ existing functions. You'll probably need only new
+ constructor-functions who take the different address
+ formats into consideration (maybe a long dotted address
+ or whatever).
+*/
+
+/* _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr */
+/* are the same! I don't like it very much but see no other easy way to */
+/* conceal the struct sockaddr from the eyes of the user. */
+
+
+#define OSL_INVALID_SOCKET -1
+#define OSL_SOCKET_ERROR -1
+
+
+/* Buffer size for gethostbyname */
+#define MAX_HOSTBUFFER_SIZE 2048
+
+/*****************************************************************************/
+/* enum oslAddrFamily */
+/*****************************************************************************/
+
+/* map */
+static unsigned long FamilyMap[]= {
+ AF_INET, /* osl_Socket_FamilyInet */
+ AF_IPX, /* osl_Socket_FamilyIpx */
+ 0 /* osl_Socket_FamilyInvalid */
+};
+
+/* reverse map */
+static oslAddrFamily osl_AddrFamilyFromNative(sal_uInt32 nativeType)
+{
+ oslAddrFamily i= (oslAddrFamily)0;
+
+ while(i != osl_Socket_FamilyInvalid)
+ {
+ if(FamilyMap[i] == nativeType)
+ return i;
+ i = (oslAddrFamily) ( i + 1 );
+ }
+
+ return i;
+}
+
+/* macros */
+#define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y)
+#define FAMILY_TO_NATIVE(x) (short)FamilyMap[x]
+
+/*****************************************************************************/
+/* enum oslProtocol */
+/*****************************************************************************/
+
+/* map */
+static sal_uInt32 ProtocolMap[]= {
+ 0, /* osl_Socket_ProtocolIp */
+ NSPROTO_IPX, /* osl_Socket_ProtocolIpx */
+ NSPROTO_SPX, /* osl_Socket_ProtocolSpx */
+ NSPROTO_SPXII, /* osl_Socket_ProtocolSpxII */
+ 0 /* osl_Socket_ProtocolInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslProtocol osl_ProtocolFromNative(sal_uInt32 nativeType)
+{
+ oslProtocol i= (oslProtocol)0;
+
+ while(i != osl_Socket_ProtocolInvalid)
+ {
+ if(ProtocolMap[i] == nativeType)
+ return i;
+ i = (oslProtocol) ( i + 1);
+ }
+
+ return i;
+}
+*/
+
+/* macros */
+#define PROTOCOL_FROM_NATIVE(y) osl_ProtocolFromNative(y)
+#define PROTOCOL_TO_NATIVE(x) ProtocolMap[x]
+
+
+/*****************************************************************************/
+/* enum oslSocketType */
+/*****************************************************************************/
+
+/* map */
+static sal_uInt32 TypeMap[]= {
+ SOCK_STREAM, /* osl_Socket_TypeStream */
+ SOCK_DGRAM, /* osl_Socket_TypeDgram */
+ SOCK_RAW, /* osl_Socket_TypeRaw */
+ SOCK_RDM, /* osl_Socket_TypeRdm */
+ SOCK_SEQPACKET, /* osl_Socket_TypeSeqPacket */
+ 0 /* osl_Socket_TypeInvalid */
+};
+
+/* reverse map */
+static oslSocketType osl_SocketTypeFromNative(sal_uInt32 nativeType)
+{
+ oslSocketType i= (oslSocketType)0;
+
+ while(i != osl_Socket_TypeInvalid)
+ {
+ if(TypeMap[i] == nativeType)
+ return i;
+ i = (oslSocketType)(i + 1);
+ }
+
+ return i;
+}
+
+/* macros */
+#define TYPE_TO_NATIVE(x) TypeMap[x]
+#define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y)
+
+
+/*****************************************************************************/
+/* enum oslSocketOption */
+/*****************************************************************************/
+
+/* map */
+static sal_uInt32 OptionMap[]= {
+ SO_DEBUG, /* osl_Socket_OptionDebug */
+ SO_ACCEPTCONN, /* osl_Socket_OptionAcceptConn */
+ SO_REUSEADDR, /* osl_Socket_OptionReuseAddr */
+ SO_KEEPALIVE, /* osl_Socket_OptionKeepAlive */
+ SO_DONTROUTE, /* osl_Socket_OptionDontRoute */
+ SO_BROADCAST, /* osl_Socket_OptionBroadcast */
+ SO_USELOOPBACK, /* osl_Socket_OptionUseLoopback */
+ SO_LINGER, /* osl_Socket_OptionLinger */
+ SO_OOBINLINE, /* osl_Socket_OptionOOBinLine */
+ SO_SNDBUF, /* osl_Socket_OptionSndBuf */
+ SO_RCVBUF, /* osl_Socket_OptionRcvBuf */
+ SO_SNDLOWAT, /* osl_Socket_OptionSndLowat */
+ SO_RCVLOWAT, /* osl_Socket_OptionRcvLowat */
+ SO_SNDTIMEO, /* osl_Socket_OptionSndTimeo */
+ SO_RCVTIMEO, /* osl_Socket_OptionRcvTimeo */
+ SO_ERROR, /* osl_Socket_OptionError */
+ SO_TYPE, /* osl_Socket_OptionType */
+ TCP_NODELAY, /* osl_Socket_OptionTcpNoDelay */
+ 0 /* osl_Socket_OptionInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketOption osl_SocketOptionFromNative(sal_uInt32 nativeType)
+{
+ oslSocketOption i= (oslSocketOption)0;
+
+ while(i != osl_Socket_OptionInvalid)
+ {
+ if(OptionMap[i] == nativeType)
+ return i;
+ i = (oslSocketOption) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+/* macros */
+#define OPTION_TO_NATIVE(x) OptionMap[x]
+#define OPTION_FROM_NATIVE(y) osl_SocketOptionFromNative(y)
+
+
+/*****************************************************************************/
+/* enum oslSocketOptionLevel */
+/*****************************************************************************/
+
+static sal_uInt32 OptionLevelMap[]= {
+ SOL_SOCKET, /* osl_Socket_LevelSocket */
+ IPPROTO_TCP, /* osl_Socket_LevelTcp */
+ 0 /* osl_Socket_LevelInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketOptionLevel osl_SocketOptionLevelFromNative(sal_uInt32 nativeType)
+{
+ oslSocketOptionLevel i= (oslSocketOptionLevel)0;
+
+ while(i != osl_Socket_LevelInvalid)
+ {
+ if(OptionLevelMap[i] == nativeType)
+ return i;
+ i = (oslSocketOptionLevel) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+/* macros */
+#define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x]
+#define OPTION_LEVEL_FROM_NATIVE(y) osl_SocketOptionLevelFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketMsgFlag */
+/*****************************************************************************/
+
+static sal_uInt32 SocketMsgFlagMap[]= {
+ 0, /* osl_Socket_MsgNormal */
+ MSG_OOB, /* osl_Socket_MsgOOB */
+ MSG_PEEK, /* osl_Socket_MsgPeek */
+ MSG_DONTROUTE, /* osl_Socket_MsgDontRoute */
+ MSG_MAXIOVLEN, /* osl_Socket_MsgMaxIOVLen */
+ 0 /* osl_Socket_MsgInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketMsgFlag osl_SocketMsgFlagFromNative(sal_uInt32 nativeType)
+{
+ oslSocketMsgFlag i= (oslSocketMsgFlag)0;
+
+ while(i != osl_Socket_MsgInvalid)
+ {
+ if(SocketMsgFlagMap[i] == nativeType)
+ return i;
+ i = (oslSocketMsgFlag) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+
+/* macros */
+#define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x]
+#define MSG_FLAG_FROM_NATIVE(y) osl_SocketMsgFlagFromNative(y)
+
+
+/*****************************************************************************/
+/* enum oslSocketDirection */
+/*****************************************************************************/
+
+static sal_uInt32 SocketDirection[]= {
+ SD_RECEIVE, /* osl_Socket_DirRead */
+ SD_SEND, /* osl_Socket_DirWrite */
+ SD_BOTH, /* osl_Socket_DirReadWrite */
+ 0 /* osl_Socket_DirInvalid */
+};
+
+/* reverse map */
+/* mfe: NOT USED
+static oslSocketDirection osl_SocketDirectionFromNative(sal_uInt32 nativeType)
+{
+ oslSocketDirection i= (oslSocketDirection)0;
+
+ while(i != osl_Socket_DirInvalid)
+ {
+ if(SocketDirection[i] == nativeType)
+ return i;
+ i = (oslSocketDirection) ( i + 1 );
+ }
+
+ return i;
+}
+*/
+
+/* macros */
+#define DIRECTION_TO_NATIVE(x) SocketDirection[x]
+#define DIRECTION_FROM_NATIVE(y) osl_SocketDirectionFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketError */
+/*****************************************************************************/
+
+static struct
+{
+ int errcode;
+ oslSocketError error;
+} SocketError[]= {
+ { 0, osl_Socket_E_None }, /* no error */
+ { ENOTSOCK, osl_Socket_E_NotSocket }, /* Socket operation on non-socket */
+ { EDESTADDRREQ, osl_Socket_E_DestAddrReq }, /* Destination address required */
+ { EMSGSIZE, osl_Socket_E_MsgSize }, /* Message too long */
+ { EPROTOTYPE, osl_Socket_E_Prototype }, /* Protocol wrong type for socket */
+ { ENOPROTOOPT, osl_Socket_E_NoProtocol }, /* Protocol not available */
+ { EPROTONOSUPPORT, osl_Socket_E_ProtocolNoSupport }, /* Protocol not supported */
+ { ESOCKTNOSUPPORT, osl_Socket_E_TypeNoSupport }, /* Socket type not supported */
+ { EOPNOTSUPP, osl_Socket_E_OpNotSupport }, /* Operation not supported on socket */
+ { EPFNOSUPPORT, osl_Socket_E_PfNoSupport }, /* Protocol family not supported */
+ { EAFNOSUPPORT, osl_Socket_E_AfNoSupport }, /* Address family not supported by */
+ /* protocol family */
+ { EADDRINUSE, osl_Socket_E_AddrInUse }, /* Address already in use */
+ { EADDRNOTAVAIL, osl_Socket_E_AddrNotAvail }, /* Can't assign requested address */
+ { ENETDOWN, osl_Socket_E_NetDown }, /* Network is down */
+ { ENETUNREACH, osl_Socket_E_NetUnreachable }, /* Network is unreachable */
+ { ENETRESET, osl_Socket_E_NetReset }, /* Network dropped connection because */
+ /* of reset */
+ { ECONNABORTED, osl_Socket_E_ConnAborted }, /* Software caused connection abort */
+ { ECONNRESET, osl_Socket_E_ConnReset }, /* Connection reset by peer */
+ { ENOBUFS, osl_Socket_E_NoBufferSpace }, /* No buffer space available */
+ { EISCONN, osl_Socket_E_IsConnected }, /* Socket is already connected */
+ { ENOTCONN, osl_Socket_E_NotConnected }, /* Socket is not connected */
+ { ESHUTDOWN, osl_Socket_E_Shutdown }, /* Can't send after socket shutdown */
+ { ETOOMANYREFS, osl_Socket_E_TooManyRefs }, /* Too many references: can't splice */
+ { ETIMEDOUT, osl_Socket_E_TimedOut }, /* Connection timed out */
+ { ECONNREFUSED, osl_Socket_E_ConnRefused }, /* Connection refused */
+ { EHOSTDOWN, osl_Socket_E_HostDown }, /* Host is down */
+ { EHOSTUNREACH, osl_Socket_E_HostUnreachable }, /* No route to host */
+ { EWOULDBLOCK, osl_Socket_E_WouldBlock }, /* call would block on non-blocking socket */
+ { EALREADY, osl_Socket_E_Already }, /* operation already in progress */
+ { EINPROGRESS, osl_Socket_E_InProgress }, /* operation now in progress */
+ { EAGAIN, osl_Socket_E_WouldBlock }, /* same as EWOULDBLOCK */
+ { -1, osl_Socket_E_InvalidError }
+};
+
+/* map */
+/* mfe: NOT USED
+static int osl_NativeFromSocketError(oslSocketError errorCode)
+{
+ int i = 0;
+
+ while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
+ (SocketError[i].error != errorCode)) i++;
+
+ return SocketError[i].errcode;
+}
+*/
+
+/* reverse map */
+static oslSocketError osl_SocketErrorFromNative(int nativeType)
+{
+ int i = 0;
+
+ while ((SocketError[i].error != osl_Socket_E_InvalidError) &&
+ (SocketError[i].errcode != nativeType)) i++;
+
+ return SocketError[i].error;
+}
+
+/* macros */
+#define ERROR_TO_NATIVE(x) osl_NativeFromSocketError(x)
+#define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y)
+
+/*****************************************************************************/
+/* local function prototypes */
+/*****************************************************************************/
+
+oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
+ const sal_Char* pszDottedAddr, sal_Int32 Port);
+
+oslSocketAddr SAL_CALL osl_psz_createIpxSocketAddr (
+ const sal_Char NetNumber[4],
+ const sal_Char NodeNumber[6],
+ sal_uInt32 SocketNumber);
+
+oslHostAddr SAL_CALL osl_psz_createHostAddr (
+ const sal_Char *pszHostname, const oslSocketAddr Addr);
+
+oslHostAddr SAL_CALL osl_psz_createHostAddrByName (
+ const sal_Char *pszHostname);
+
+const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (
+ const oslHostAddr Addr);
+
+oslSocketResult SAL_CALL osl_psz_getLocalHostname (
+ sal_Char *pBuffer, sal_uInt32 nBufLen);
+
+oslSocketAddr SAL_CALL osl_psz_resolveHostname (
+ const sal_Char* pszHostname);
+
+sal_Int32 SAL_CALL osl_psz_getServicePort (
+ const sal_Char* pszServicename, const sal_Char* pszProtocol);
+
+oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr (
+ oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
+
+oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr (
+ oslSocketAddr Addr, sal_Char *pBuffer, sal_uInt32 BufferSize);
+
+void SAL_CALL osl_psz_getLastSocketErrorDescription (
+ oslSocket Socket, sal_Char* pBuffer, sal_uInt32 BufferSize);
+
+/*****************************************************************************/
+/* osl_create/destroy-SocketImpl */
+/*****************************************************************************/
+
+#if OSL_DEBUG_LEVEL > 1
+static sal_uInt32 g_nSocketImpl = 0;
+static sal_uInt32 g_nSocketAddr = 0;
+
+/* sorry, must be implemented otherwise */
+#if 0
+struct LeakWarning
+{
+ ~LeakWarning()
+ {
+ if( g_nSocketImpl )
+ OSL_TRACE( "sal_socket: %d socket instances leak\n" , g_nSocketImpl );
+ if( g_nSocketAddr )
+ OSL_TRACE( "sal_socket: %d socket address instances leak\n" , g_nSocketAddr );
+ }
+};
+LeakWarning socketWarning;
+#endif
+
+#endif /* OSL_DEBUG_LEVEL */
+
+
+oslSocket __osl_createSocketImpl(int Socket)
+{
+ oslSocket pSocket;
+
+ pSocket = (oslSocket)calloc(1, sizeof(struct oslSocketImpl));
+
+ pSocket->m_Socket = Socket;
+ pSocket->m_nLastError = 0;
+ pSocket->m_CloseCallback = 0;
+ pSocket->m_CallbackArg = 0;
+ pSocket->m_nRefCount = 1;
+
+#if defined(LINUX)
+ pSocket->m_bIsAccepting = sal_False;
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketImpl ++;
+#endif
+ return pSocket;
+}
+
+void __osl_destroySocketImpl(oslSocket Socket)
+{
+ if ( Socket != NULL)
+ free((struct oslSocketImpl *) Socket);
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketImpl --;
+#endif
+}
+
+static oslSocketAddr __osl_createSocketAddr( )
+{
+ oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl ));
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketAddr ++;
+#endif
+ return pAddr;
+}
+
+static oslSocketAddr __osl_createSocketAddrWithFamily(
+ oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr )
+{
+ oslSocketAddr pAddr;
+
+ OSL_ASSERT( family == osl_Socket_FamilyInet );
+
+ pAddr = __osl_createSocketAddr();
+ switch( family )
+ {
+ case osl_Socket_FamilyInet:
+ {
+ struct sockaddr_in* pInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet);
+ pInetAddr->sin_addr.s_addr = nAddr;
+ pInetAddr->sin_port = (sal_uInt16)(port&0xffff);
+ break;
+ }
+ default:
+ pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family);
+ }
+ return pAddr;
+}
+
+static oslSocketAddr __osl_createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr )
+{
+ oslSocketAddr pAddr = __osl_createSocketAddr();
+ memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( struct sockaddr ) );
+ return pAddr;
+}
+
+static void __osl_destroySocketAddr( oslSocketAddr addr )
+{
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketAddr --;
+#endif
+ rtl_freeMemory( addr );
+}
+
+/*****************************************************************************/
+/* osl_createEmptySocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family)
+{
+ oslSocketAddr pAddr = 0;
+
+ /* is it an internet-Addr? */
+ if (Family == osl_Socket_FamilyInet)
+ {
+ pAddr = __osl_createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) );
+ }
+ else
+ {
+ pAddr = __osl_createSocketAddrWithFamily( Family , 0 , 0 );
+ }
+
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_copySocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr)
+{
+ oslSocketAddr pCopy = 0;
+ if (Addr)
+ {
+ pCopy = __osl_createSocketAddr();
+
+ if (pCopy)
+ memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr));
+ }
+ return pCopy;
+}
+
+/*****************************************************************************/
+/* osl_isEqualSocketAddr */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isEqualSocketAddr (
+ oslSocketAddr Addr1,
+ oslSocketAddr Addr2)
+{
+ struct sockaddr* pAddr1= &(Addr1->m_sockaddr);
+ struct sockaddr* pAddr2= &(Addr2->m_sockaddr);
+
+ OSL_ASSERT(pAddr1);
+ OSL_ASSERT(pAddr2);
+
+ if (pAddr1->sa_family == pAddr2->sa_family)
+ {
+ switch (pAddr1->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in* pInetAddr1= (struct sockaddr_in*)pAddr1;
+ struct sockaddr_in* pInetAddr2= (struct sockaddr_in*)pAddr2;
+
+ if ((pInetAddr1->sin_family == pInetAddr2->sin_family) &&
+ (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) &&
+ (pInetAddr1->sin_port == pInetAddr2->sin_port))
+ return (sal_True);
+ }
+
+ default:
+ {
+ return (memcmp(pAddr1, Addr2, sizeof(struct sockaddr)) == 0);
+ }
+ }
+ }
+
+ return (sal_False);
+}
+
+/*****************************************************************************/
+/* osl_createInetBroadcastAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createInetBroadcastAddr (
+ rtl_uString *strDottedAddr,
+ sal_Int32 Port)
+{
+ sal_uInt32 nAddr = OSL_INADDR_NONE;
+ oslSocketAddr pAddr;
+
+ if (strDottedAddr && strDottedAddr->length)
+ {
+ /* Dotted host address for limited broadcast */
+ rtl_String *pDottedAddr = NULL;
+
+ rtl_uString2String (
+ &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ nAddr = inet_addr (pDottedAddr->buffer);
+ rtl_string_release (pDottedAddr);
+ }
+
+ if (nAddr != OSL_INADDR_NONE)
+ {
+ /* Limited broadcast */
+ nAddr = ntohl(nAddr);
+ if (IN_CLASSA(nAddr))
+ {
+ nAddr &= IN_CLASSA_NET;
+ nAddr |= IN_CLASSA_HOST;
+ }
+ else if (IN_CLASSB(nAddr))
+ {
+ nAddr &= IN_CLASSB_NET;
+ nAddr |= IN_CLASSB_HOST;
+ }
+ else if (IN_CLASSC(nAddr))
+ {
+ nAddr &= IN_CLASSC_NET;
+ nAddr |= IN_CLASSC_HOST;
+ }
+ else
+ {
+ /* No broadcast in class D */
+ return ((oslSocketAddr)NULL);
+ }
+ nAddr = htonl(nAddr);
+ }
+
+ pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port), nAddr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createInetSocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createInetSocketAddr (
+ rtl_uString *ustrDottedAddr,
+ sal_Int32 Port)
+{
+ rtl_String* strDottedAddr=0;
+ oslSocketAddr Addr;
+ sal_Char* pszDottedAddr=0;
+
+ if ( ustrDottedAddr != 0 )
+ {
+ rtl_uString2String( &strDottedAddr,
+ rtl_uString_getStr(ustrDottedAddr),
+ rtl_uString_getLength(ustrDottedAddr),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+ pszDottedAddr = rtl_string_getStr(strDottedAddr);
+ }
+
+
+ Addr = osl_psz_createInetSocketAddr(pszDottedAddr, Port);
+
+ if ( strDottedAddr != 0 )
+ {
+ rtl_string_release(strDottedAddr);
+ }
+
+ return Addr;
+}
+
+oslSocketAddr SAL_CALL osl_psz_createInetSocketAddr (
+ const sal_Char* pszDottedAddr,
+ sal_Int32 Port)
+{
+ oslSocketAddr pAddr = 0;
+ sal_Int32 Addr = inet_addr(pszDottedAddr);
+ if(Addr != -1)
+ {
+ /* valid dotted addr */
+ pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons(Port) , Addr );
+ }
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_setAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq )
+{
+ oslSocketResult res = osl_Socket_Error;
+
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( pByteSeq );
+
+ if( pAddr && pByteSeq )
+ {
+ struct sockaddr_in * pSystemInetAddr;
+
+ OSL_ASSERT( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) );
+ OSL_ASSERT( pByteSeq->nElements == 4 );
+
+ pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
+ memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 );
+ res = osl_Socket_Ok;
+ }
+ return res;
+}
+
+/*****************************************************************************/
+/* osl_getAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq )
+{
+ oslSocketResult res = osl_Socket_Error;
+
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( ppByteSeq );
+
+ if( pAddr && ppByteSeq )
+ {
+ struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
+ rtl_byte_sequence_constructFromArray( ppByteSeq , (sal_Int8 *) &(pSystemInetAddr->sin_addr),4);
+ res = osl_Socket_Ok;
+ }
+ return res;
+}
+
+
+/*****************************************************************************/
+/* _osl_getFullQualifiedDomainName */
+/*****************************************************************************/
+
+/** try to figure out a full-qualified hostname, by adding the current domain
+ as given by the domainname program to the given hostname.
+ This function MUST NOT call gethostbyname since pHostName allready points
+ to data returned by gethostname and would be garbled: use gethostname_r
+ instead!
+ */
+
+/* wrap around different interfaces to reentrant gethostbyname */
+static struct hostent* _osl_gethostbyname_r (
+ const char *name, struct hostent *result,
+ char *buffer, int buflen, int *h_errnop)
+{
+#if defined(LINUX) || (defined(FREEBSD) && (__FreeBSD_version >= 601103))
+ struct hostent *__result; /* will be the same as result */
+ int __error;
+ __error = gethostbyname_r (name, result, buffer, buflen,
+ &__result, h_errnop);
+ return __error ? NULL : __result ;
+#else
+ return gethostbyname_r( name, result, buffer, buflen, h_errnop);
+#endif
+}
+
+static sal_Bool _osl_getDomainName (sal_Char *buffer, sal_Int32 bufsiz)
+{
+ sal_Bool result;
+ int p[2];
+
+ result = sal_False;
+ if (pipe (p) == 0)
+ {
+ pid_t pid;
+ int nStatus;
+
+ pid = fork();
+ if (pid == 0)
+ {
+ char *argv[] =
+ {
+ "/bin/domainname",
+ NULL
+ };
+
+ close (p[0]);
+ dup2 (p[1], 1);
+ close (p[1]);
+
+ execv ("/bin/domainname", argv);
+ // arriving here means exec failed
+ _exit(-1);
+ }
+ else if (pid > 0)
+ {
+ sal_Int32 k = 0, n = bufsiz;
+
+ close (p[1]);
+ if ((k = read (p[0], buffer, n - 1)) > 0)
+ {
+ buffer[k] = 0;
+ if (buffer[k - 1] == '\n')
+ buffer[k - 1] = 0;
+ result = sal_True;
+ }
+ close (p[0]);
+ waitpid (pid, &nStatus, 0);
+ }
+ else
+ {
+ close (p[0]);
+ close (p[1]);
+ }
+ }
+ return (result);
+}
+
+static sal_Char* _osl_getFullQualifiedDomainName (const sal_Char *pHostName)
+{
+# define DOMAINNAME_LENGTH 512
+ sal_uInt32 nLengthOfHostName;
+ static sal_uInt32 nLengthOfDomainName = 0;
+ static sal_Char *pDomainName = NULL;
+
+ sal_Char *pFullQualifiedName;
+#if 0 /* OBSOLETE */
+ FILE *pPipeToDomainnameExe;
+#endif /* OBSOLETE */
+
+ /* get a '\0' terminated domainname */
+
+ /* read default domainname default from environment */
+ if (nLengthOfDomainName == 0)
+ {
+ sal_Char *pEnvDomain;
+
+ pEnvDomain = getenv ("STAR_OVERRIDE_DOMAINNAME");
+ if (pEnvDomain)
+ {
+ pDomainName = strdup (pEnvDomain);
+ nLengthOfDomainName = strlen (pDomainName);
+ }
+ }
+
+#if 1 /* NEW */
+ if (nLengthOfDomainName == 0)
+ {
+ sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ];
+
+ pDomainNameBuffer[0] = '\0';
+
+ if (_osl_getDomainName (pDomainNameBuffer, DOMAINNAME_LENGTH))
+ {
+ pDomainName = strdup (pDomainNameBuffer);
+ nLengthOfDomainName = strlen (pDomainName);
+ }
+ }
+
+#endif /* NEW */
+#if 0 /* OBSOLETE */
+#ifdef SCO
+
+ /* call 'domainname > /usr/tmp/some-tmp-file', since
+ popen read pclose do block or core-dump,
+ (even the pipe-stuff that comes with pthreads) */
+ if (nLengthOfDomainName == 0)
+ {
+ sal_Char tmp_name[ L_tmpnam ];
+ FILE *tmp_file;
+ sal_Char domain_call [ L_tmpnam + 16 ] = "domainname > ";
+
+ tmp_name[0] = '\0';
+
+ tmpnam ( tmp_name );
+ strcat ( domain_call, tmp_name );
+ if ( (system ( domain_call ) == 0)
+ && ((tmp_file = fopen( tmp_name, "r" )) != NULL ) )
+ {
+ sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ];
+
+ pDomainNameBuffer[0] = '\0';
+
+ if ( fgets ( pDomainNameBuffer, DOMAINNAME_LENGTH, tmp_file ) )
+ {
+ pDomainName = strdup( pDomainNameBuffer );
+ nLengthOfDomainName = strlen( pDomainName );
+ if ( ( nLengthOfDomainName > 0 )
+ && ( pDomainName[ nLengthOfDomainName - 1] == '\n' ) )
+ pDomainName[ --nLengthOfDomainName ] = '\0';
+ }
+ fclose ( tmp_file );
+ }
+ unlink( tmp_name );
+ }
+
+#else /* !SCO */
+
+ /* read the domainname from pipe to the program domainname */
+ if ( (nLengthOfDomainName == 0)
+ && (pPipeToDomainnameExe = popen( "domainname", "r")) )
+ {
+ sal_Char c;
+ sal_Char pDomainNameBuffer[ DOMAINNAME_LENGTH ];
+ sal_Char *pDomainNamePointer;
+
+ pDomainNameBuffer[0] = '\0';
+
+ pDomainNamePointer = pDomainNameBuffer;
+ while ( ((c = getc( pPipeToDomainnameExe )) != EOF)
+ && (nLengthOfDomainName < (DOMAINNAME_LENGTH - 1)) )
+ {
+ if (! isspace(c))
+ {
+ nLengthOfDomainName++ ;
+ *pDomainNamePointer++ = (sal_Char)c;
+ }
+ }
+ *pDomainNamePointer = '\0';
+ pDomainName = strdup( pDomainNameBuffer );
+
+ pclose( pPipeToDomainnameExe );
+ }
+
+#endif /* !SCO */
+#endif /* OBSOLETE */
+
+ /* compose hostname and domainname */
+ nLengthOfHostName = strlen( pHostName );
+ pFullQualifiedName = (sal_Char*) malloc( (nLengthOfHostName + 1
+ + nLengthOfDomainName + 1) * sizeof(sal_Char) );
+ memcpy( pFullQualifiedName, pHostName,
+ (nLengthOfHostName + 1) * sizeof(sal_Char) );
+
+ if ( nLengthOfDomainName > 0 )
+ {
+ /* fqdn = hostname + '.' + domainname + '\0' */
+ pFullQualifiedName[ nLengthOfHostName ] = '.';
+ memcpy( pFullQualifiedName + nLengthOfHostName + 1, pDomainName,
+ nLengthOfDomainName + 1 );
+ }
+
+ /* check whether full-qualified name and hostname point to the same host
+ * should almost always be true */
+ if ( nLengthOfDomainName > 0 )
+ {
+ struct hostent *pQualifiedHostByName;
+ struct hostent *pHostByName;
+ sal_Bool bHostsAreEqual;
+
+ /* buffer for calls to reentrant version of gethostbyname */
+ struct hostent aHostByName, aQualifiedHostByName;
+ sal_Char pHostBuffer[ MAX_HOSTBUFFER_SIZE ];
+ sal_Char pQualifiedHostBuffer[ MAX_HOSTBUFFER_SIZE ];
+ int nErrorNo;
+
+ pHostBuffer[0] = '\0';
+ pQualifiedHostBuffer[0] = '\0';
+
+ /* get list of addresses */
+ pQualifiedHostByName = _osl_gethostbyname_r (
+ pFullQualifiedName,
+ &aQualifiedHostByName, pQualifiedHostBuffer,
+ sizeof(pQualifiedHostBuffer), &nErrorNo );
+ pHostByName = _osl_gethostbyname_r (
+ pHostName,
+ &aHostByName, pHostBuffer,
+ sizeof(pHostBuffer), &nErrorNo );
+
+ /* compare addresses */
+ bHostsAreEqual = sal_False;
+ if ( pQualifiedHostByName && pHostByName )
+ {
+ sal_Char **p, **q;
+ struct in_addr in;
+
+ /* lists are expected to be (very) short */
+ for ( p = pQualifiedHostByName->h_addr_list; *p != NULL; p++ )
+ {
+ for ( q = pHostByName->h_addr_list; *q != NULL; q++ )
+ {
+ /* in.s_addr may be in_addr_t or uint32_t or heaven knows */
+ if ( memcmp( *p, *q, sizeof(in.s_addr) ) == 0 )
+ {
+ bHostsAreEqual = sal_True;
+ break;
+ }
+ }
+ if ( bHostsAreEqual )
+ break;
+ }
+ }
+
+ /* very strange case, but have to believe it: reduce the
+ * full qualified name to the unqualified host name */
+ if ( !bHostsAreEqual )
+ {
+ OSL_TRACE("_osl_getFullQualifiedDomainName: "
+ "suspect FQDN: %s\n", pFullQualifiedName);
+
+ pFullQualifiedName[ nLengthOfHostName ] = '\0';
+ pFullQualifiedName = (sal_Char*)realloc ( pFullQualifiedName,
+ (nLengthOfHostName + 1) * sizeof( sal_Char ));
+ }
+ }
+
+ /* always return a hostname looked up as carefully as possible
+ * this string must be freed by the caller */
+ return pFullQualifiedName;
+}
+
+/*****************************************************************************/
+/* _osl_isFullQualifiedDomainName */
+/*****************************************************************************/
+static sal_Bool _osl_isFullQualifiedDomainName (const sal_Char *pHostName)
+{
+ /* a FQDN (aka 'hostname.domain.top_level_domain' )
+ * is a name which contains a dot '.' in it ( would
+ * match as well for 'hostname.' but is good enough
+ * for now )*/
+ return (sal_Bool)( strchr( pHostName, (int)'.' ) != NULL );
+}
+
+/*****************************************************************************/
+/* oslHostAddr */
+/*****************************************************************************/
+struct oslHostAddrImpl
+{
+ sal_Char *pHostName;
+ oslSocketAddr pSockAddr;
+};
+
+static oslHostAddr _osl_hostentToHostAddr (const struct hostent *he)
+{
+ oslHostAddr pAddr= NULL;
+ oslSocketAddr pSockAddr = 0;
+
+ sal_Char *cn;
+
+ if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL))
+ return ((oslHostAddr)NULL);
+
+ if (_osl_isFullQualifiedDomainName(he->h_name))
+ {
+ cn= (sal_Char *)malloc(strlen (he->h_name) + 1);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+
+ strcpy(cn, he->h_name);
+ }
+ else
+ {
+ cn =_osl_getFullQualifiedDomainName (he->h_name);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+ }
+
+ pSockAddr = __osl_createSocketAddr();
+ OSL_ASSERT(pSockAddr);
+ if (pSockAddr == NULL)
+ {
+ free(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pSockAddr->m_sockaddr.sa_family= he->h_addrtype;
+ if (pSockAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ struct sockaddr_in *sin= (struct sockaddr_in *)&(pSockAddr->m_sockaddr);
+ memcpy (
+ &(sin->sin_addr.s_addr),
+ he->h_addr_list[0],
+ he->h_length);
+ }
+ else
+ {
+ /* unknown address family */
+ /* future extensions for new families might be implemented here */
+
+ OSL_TRACE("_osl_hostentToHostAddr: unknown address family.\n");
+ OSL_ASSERT(sal_False);
+
+ __osl_destroySocketAddr( pSockAddr );
+ free (cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
+ OSL_ASSERT(pAddr);
+ if (pAddr == NULL)
+ {
+ __osl_destroySocketAddr( pSockAddr );
+ free (cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr->pHostName= cn;
+ pAddr->pSockAddr= pSockAddr;
+
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddr (
+ rtl_uString *ustrHostname,
+ const oslSocketAddr Addr)
+{
+ oslHostAddr HostAddr;
+ rtl_String* strHostname=0;
+ sal_Char* pszHostName=0;
+
+ if ( ustrHostname != 0 )
+ {
+ rtl_uString2String( &strHostname,
+ rtl_uString_getStr(ustrHostname),
+ rtl_uString_getLength(ustrHostname),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszHostName = rtl_string_getStr(strHostname);
+ }
+
+ HostAddr = osl_psz_createHostAddr(pszHostName,Addr);
+
+ if ( strHostname != 0 )
+ {
+ rtl_string_release(strHostname);
+ }
+
+
+ return HostAddr;
+}
+
+oslHostAddr SAL_CALL osl_psz_createHostAddr (
+ const sal_Char *pszHostname,
+ const oslSocketAddr pAddr)
+{
+ oslHostAddr pHostAddr;
+ sal_Char *cn;
+
+ OSL_ASSERT(pszHostname && pAddr);
+ if ((pszHostname == NULL) || (pAddr == NULL))
+ return ((oslHostAddr)NULL);
+
+ cn = (sal_Char *)malloc(strlen (pszHostname) + 1);
+ OSL_ASSERT(cn);
+ if (cn == NULL)
+ return ((oslHostAddr)NULL);
+
+ strcpy (cn, pszHostname);
+
+ pHostAddr= (oslHostAddr) malloc(sizeof(struct oslHostAddrImpl));
+ OSL_ASSERT(pHostAddr);
+ if (pAddr == NULL)
+ {
+ free (cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pHostAddr->pHostName= cn;
+ pHostAddr->pSockAddr= osl_copySocketAddr( pAddr );
+
+ return pHostAddr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByName */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *ustrHostname)
+{
+ oslHostAddr HostAddr;
+ rtl_String* strHostname=0;
+ sal_Char* pszHostName=0;
+
+ if ( ustrHostname != 0 )
+ {
+ rtl_uString2String( &strHostname,
+ rtl_uString_getStr(ustrHostname),
+ rtl_uString_getLength(ustrHostname),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszHostName=rtl_string_getStr(strHostname);
+ }
+
+ HostAddr = osl_psz_createHostAddrByName(pszHostName);
+
+ if ( strHostname != 0 )
+ {
+ rtl_string_release(strHostname);
+ }
+
+ return HostAddr;
+}
+
+oslHostAddr SAL_CALL osl_psz_createHostAddrByName (const sal_Char *pszHostname)
+{
+ struct hostent *he;
+ oslHostAddr addr;
+
+ static oslMutex mutex = NULL;
+
+ if (mutex == NULL)
+ mutex = osl_createMutex();
+
+ osl_acquireMutex(mutex);
+
+ he = gethostbyname((sal_Char *)pszHostname);
+ addr = _osl_hostentToHostAddr (he);
+
+ osl_releaseMutex(mutex);
+
+ return addr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByAddr (const oslSocketAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr == NULL)
+ return ((oslHostAddr)NULL);
+
+ if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ const struct sockaddr_in *sin= (const struct sockaddr_in *)&(pAddr->m_sockaddr);
+ struct hostent *he;
+
+ if (sin->sin_addr.s_addr == htonl(INADDR_ANY))
+ return ((oslHostAddr)NULL);
+
+ he= gethostbyaddr((sal_Char *)&(sin->sin_addr),
+ sizeof (sin->sin_addr),
+ sin->sin_family);
+ return _osl_hostentToHostAddr (he);
+ }
+
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_copyHostAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_copyHostAddr (const oslHostAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return osl_psz_createHostAddr (pAddr->pHostName, pAddr->pSockAddr);
+ else
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_getHostnameOfHostAddr (
+ const oslHostAddr Addr,
+ rtl_uString **ustrHostname)
+{
+ const sal_Char* pHostname=0;
+
+ pHostname = osl_psz_getHostnameOfHostAddr(Addr);
+
+ rtl_uString_newFromAscii (ustrHostname, pHostname);
+
+ return;
+}
+
+const sal_Char* SAL_CALL osl_psz_getHostnameOfHostAddr (const oslHostAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return pAddr->pHostName;
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_getSocketAddrOfHostAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr (const oslHostAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return ((oslSocketAddr)(pAddr->pSockAddr));
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_destroyHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_destroyHostAddr (oslHostAddr pAddr)
+{
+ if (pAddr)
+ {
+ if (pAddr->pHostName)
+ free (pAddr->pHostName);
+ if (pAddr->pSockAddr)
+ osl_destroySocketAddr (pAddr->pSockAddr);
+ free (pAddr);
+ }
+}
+
+/*****************************************************************************/
+/* osl_getLocalHostname */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getLocalHostname(rtl_uString **ustrLocalHostname)
+{
+ oslSocketResult Result;
+ sal_Char pszHostname[1024];
+
+ pszHostname[0] = '\0';
+
+ Result = osl_psz_getLocalHostname(pszHostname,sizeof(pszHostname));
+
+ rtl_uString_newFromAscii(ustrLocalHostname,pszHostname);
+
+ return Result;
+}
+
+oslSocketResult SAL_CALL osl_psz_getLocalHostname (
+ sal_Char *pBuffer, sal_uInt32 nBufLen)
+{
+ static sal_Char LocalHostname[256] = "";
+
+ if (strlen(LocalHostname) == 0)
+ {
+ const sal_Char *pStr;
+
+#ifdef SYSV
+ struct utsname uts;
+
+ if (uname(&uts) < 0)
+ return osl_Socket_Error;
+
+ if ((strlen(uts.nodename) + 1) > nBufLen)
+ return osl_Socket_Error;
+
+ strncpy(LocalHostname, uts.nodename, sizeof( LocalHostname ));
+#else /* BSD compatible */
+
+ if (gethostname(LocalHostname, sizeof(LocalHostname)-1) != 0)
+ return osl_Socket_Error;
+ LocalHostname[sizeof(LocalHostname)-1] = 0;
+#endif /* SYSV */
+
+ /* check if we have an FQDN */
+ if (strchr(LocalHostname, '.') == NULL)
+ {
+ oslHostAddr Addr;
+
+ /* no, determine it via dns */
+ Addr = osl_psz_createHostAddrByName(LocalHostname);
+
+ if ((pStr = osl_psz_getHostnameOfHostAddr(Addr)) != NULL)
+ {
+#if 0 /* OBSOLETE */
+ sal_Char* pChr;
+#endif /* OBSOLETE */
+ strcpy(LocalHostname, pStr);
+
+#if 0 /* OBSOLETE */
+ /* already done by _osl_getFullQualifiedDomainName() with
+ much better heuristics, so this may be contraproductive */
+
+ /* no FQDN, last try append domain name */
+ if ((pChr = strchr(LocalHostname, '.')) == NULL)
+ {
+ FILE *fp;
+
+ pChr = &LocalHostname[strlen(LocalHostname)];
+
+ if ( (fp = popen("domainname", "r")) != 0 )
+ {
+ int c;
+
+ *pChr++ = '.';
+
+ while ((c = getc(fp)) != EOF)
+ {
+ if (! isspace(c))
+ *pChr++ = (sal_Char)c;
+ }
+
+ *pChr = '\0';
+
+ fclose(fp);
+ }
+ else
+ LocalHostname[0] = '\0';
+ }
+#endif /* OBSOLETE */
+
+ }
+ osl_destroyHostAddr(Addr);
+ }
+ }
+
+ if (strlen(LocalHostname) > 0)
+ {
+ strncpy(pBuffer, LocalHostname, nBufLen);
+ pBuffer[nBufLen - 1] = '\0';
+
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_resolveHostname */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString *ustrHostname)
+{
+ oslSocketAddr Addr;
+ rtl_String* strHostname=0;
+ sal_Char* pszHostName=0;
+
+ if ( ustrHostname != 0 )
+ {
+ rtl_uString2String( &strHostname,
+ rtl_uString_getStr(ustrHostname),
+ rtl_uString_getLength(ustrHostname),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszHostName = rtl_string_getStr(strHostname);
+ }
+
+
+ Addr = osl_psz_resolveHostname(pszHostName);
+
+ if ( strHostname != 0 )
+ {
+ rtl_string_release(strHostname);
+ }
+
+
+ return Addr;
+}
+
+
+oslSocketAddr SAL_CALL osl_psz_resolveHostname(const sal_Char* pszHostname)
+{
+ struct oslHostAddrImpl *pAddr = (oslHostAddr)osl_psz_createHostAddrByName(pszHostname);
+
+ if (pAddr)
+ {
+ oslSocketAddr SockAddr = osl_copySocketAddr(pAddr->pSockAddr);
+
+ osl_destroyHostAddr(pAddr);
+
+ return (SockAddr);
+ }
+
+ return ((oslSocketAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_getServicePort */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getServicePort(rtl_uString *ustrServicename, rtl_uString *ustrProtocol)
+{
+ sal_Int32 nPort;
+ rtl_String* strServicename=0;
+ rtl_String* strProtocol=0;
+ sal_Char* pszServiceName=0;
+ sal_Char* pszProtocol=0;
+
+ if ( ustrServicename != 0 )
+ {
+ rtl_uString2String( &strServicename,
+ rtl_uString_getStr(ustrServicename),
+ rtl_uString_getLength(ustrServicename),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszServiceName = rtl_string_getStr(strServicename);
+ }
+
+ if ( ustrProtocol != 0 )
+ {
+ rtl_uString2String( &strProtocol,
+ rtl_uString_getStr(ustrProtocol),
+ rtl_uString_getLength(ustrProtocol),
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ pszProtocol = rtl_string_getStr(strProtocol);
+ }
+
+ nPort = osl_psz_getServicePort(pszServiceName,pszProtocol);
+
+ if ( strServicename != 0 )
+ {
+ rtl_string_release(strServicename);
+ }
+
+ if ( strProtocol != 0 )
+ {
+ rtl_string_release(strProtocol);
+ }
+
+
+ return nPort;
+}
+
+
+sal_Int32 SAL_CALL osl_psz_getServicePort(const sal_Char* pszServicename,
+ const sal_Char* pszProtocol)
+{
+ struct servent* ps;
+
+ ps= getservbyname(pszServicename, pszProtocol);
+
+ if (ps != 0)
+ return ntohs(ps->s_port);
+
+ return OSL_INVALID_PORT;
+}
+
+/*****************************************************************************/
+/* osl_destroySocketAddr */
+/*****************************************************************************/
+void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr)
+{
+ __osl_destroySocketAddr( pAddr );
+}
+
+/*****************************************************************************/
+/* osl_getFamilyOfSocketAddr */
+/*****************************************************************************/
+oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+
+ if (pAddr)
+ return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family);
+ else
+ return osl_Socket_FamilyInvalid;
+}
+
+/*****************************************************************************/
+/* osl_getInetPortOfSocketAddr */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr)
+{
+ OSL_ASSERT(pAddr);
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ return ntohs(pSystemInetAddr->sin_port);
+ }
+ return OSL_INVALID_PORT;
+}
+
+/*****************************************************************************/
+/* osl_setInetPortOfSocketAddr */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setInetPortOfSocketAddr(oslSocketAddr pAddr, sal_Int32 Port)
+{
+ OSL_ASSERT(pAddr);
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+ if ( pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ pSystemInetAddr->sin_port= htons((short)Port);
+ return sal_True;
+ }
+ }
+
+ /* this is not a inet-addr => can't set port */
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrHostname)
+{
+ oslSocketResult Result;
+ sal_Char pszHostname[1024];
+
+ pszHostname[0] = '\0';
+
+ Result = osl_psz_getHostnameOfSocketAddr(Addr,pszHostname,sizeof(pszHostname));
+
+ rtl_uString_newFromAscii(ustrHostname,pszHostname);
+
+ return Result;
+}
+
+
+oslSocketResult SAL_CALL osl_psz_getHostnameOfSocketAddr(oslSocketAddr pAddr,
+ sal_Char *pBuffer, sal_uInt32 BufferSize)
+{
+ oslHostAddr pHostAddr= (oslHostAddr )osl_createHostAddrByAddr(pAddr);
+
+ if (pHostAddr)
+ {
+ strncpy(pBuffer, pHostAddr->pHostName, BufferSize);
+
+ pBuffer[BufferSize - 1] = '\0';
+
+ osl_destroyHostAddr(pHostAddr);
+
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_getDottedInetAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr(oslSocketAddr Addr, rtl_uString **ustrDottedInetAddr)
+{
+ oslSocketResult Result;
+ sal_Char pszDottedInetAddr[1024];
+
+ pszDottedInetAddr[0] = '\0';
+
+ Result = osl_psz_getDottedInetAddrOfSocketAddr(Addr,pszDottedInetAddr,sizeof(pszDottedInetAddr));
+
+ rtl_uString_newFromAscii(ustrDottedInetAddr,pszDottedInetAddr);
+
+ return Result;
+
+}
+
+oslSocketResult SAL_CALL osl_psz_getDottedInetAddrOfSocketAddr(oslSocketAddr pAddr,
+ sal_Char *pBuffer, sal_uInt32 BufferSize)
+{
+ OSL_ASSERT(pAddr);
+
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr = ( struct sockaddr_in * ) &(pAddr->m_sockaddr);
+
+ if (pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ strncpy(pBuffer, inet_ntoa(pSystemInetAddr->sin_addr), BufferSize);
+ pBuffer[BufferSize - 1] = '\0';
+
+ return osl_Socket_Ok;
+ }
+ }
+
+ return osl_Socket_Error;
+}
+
+#if 0 /* OBSOLETE */
+/*****************************************************************************/
+/* osl_getIpxNetNumber */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getIpxNetNumber(oslSocketAddr Addr,
+ oslSocketIpxNetNumber NetNumber)
+
+{
+ struct sockaddr_ipx* pAddr;
+
+ pAddr= (struct sockaddr_ipx*)Addr;
+
+ OSL_ASSERT(pAddr);
+
+ if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx)))
+ {
+ memcpy(NetNumber, pAddr->sa_netnum, sizeof(NetNumber));
+
+ return osl_Socket_Ok;
+ }
+ else
+ return osl_Socket_Error;
+}
+
+
+/*****************************************************************************/
+/* osl_getIpxNodeNumber */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getIpxNodeNumber(oslSocketAddr Addr,
+ oslSocketIpxNodeNumber NodeNumber)
+
+{
+ struct sockaddr_ipx* pAddr;
+
+ pAddr= (struct sockaddr_ipx*)Addr;
+
+ OSL_ASSERT(pAddr);
+
+ if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx)))
+ {
+ memcpy(NodeNumber, pAddr->sa_nodenum, sizeof(NodeNumber));
+
+ return osl_Socket_Ok;
+ }
+ else
+ return osl_Socket_Error;
+}
+
+
+/*****************************************************************************/
+/* osl_getIpxSocketNumber */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getIpxSocketNumber(oslSocketAddr Addr)
+{
+ struct sockaddr_ipx* pAddr= (struct sockaddr_ipx*)Addr;
+ OSL_ASSERT(pAddr);
+
+ if (pAddr && (pAddr->sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyIpx)))
+ return pAddr->sa_socket;
+ else
+ return OSL_INVALID_IPX_SOCKET_NO;
+}
+
+#endif /* OBSOLETE */
+
+/*****************************************************************************/
+/* osl_createSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_createSocket(oslAddrFamily Family,
+ oslSocketType Type,
+ oslProtocol Protocol)
+{
+ int Flags;
+ oslSocket pSocket;
+
+ /* alloc memory */
+ pSocket= __osl_createSocketImpl(OSL_INVALID_SOCKET);
+
+ /* create socket */
+ pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family),
+ TYPE_TO_NATIVE(Type),
+ PROTOCOL_TO_NATIVE(Protocol));
+
+ /* creation failed => free memory */
+ if(pSocket->m_Socket == OSL_INVALID_SOCKET)
+ {
+ OSL_TRACE("osl_createSocket failed. Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+
+ __osl_destroySocketImpl((pSocket));
+ pSocket= 0;
+ }
+ else
+ {
+ /* set close-on-exec flag */
+ if ((Flags = fcntl(pSocket->m_Socket, F_GETFD, 0)) != -1)
+ {
+ Flags |= FD_CLOEXEC;
+ if (fcntl(pSocket->m_Socket, F_SETFD, Flags) == -1)
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_createSocket failed changing socket flags. Errno: %d; %s\n",
+ errno,
+ strerror(errno));
+ }
+ }
+ else
+ {
+ pSocket->m_nLastError=errno;
+ }
+
+
+ pSocket->m_CloseCallback = NULL;
+ pSocket->m_CallbackArg = NULL;
+ }
+
+ return pSocket;
+}
+
+void SAL_CALL osl_acquireSocket(oslSocket pSocket)
+{
+ osl_incrementInterlockedCount( &(pSocket->m_nRefCount ) );
+}
+
+void SAL_CALL osl_releaseSocket( oslSocket pSocket )
+{
+ if( pSocket && 0 == osl_decrementInterlockedCount( &(pSocket->m_nRefCount) ) )
+ {
+#if defined(LINUX)
+ if ( pSocket->m_bIsAccepting == sal_True )
+ {
+ OSL_ENSURE(0, "osl_destroySocket : attempt to destroy socket while accepting\n");
+ return;
+ }
+#endif /* LINUX */
+ osl_closeSocket( pSocket );
+ __osl_destroySocketImpl( pSocket );
+ }
+}
+
+
+
+/*****************************************************************************/
+/* osl_closeSocket */
+/*****************************************************************************/
+void SAL_CALL osl_closeSocket(oslSocket pSocket)
+{
+ int nRet;
+ int nFD;
+
+ /* socket already invalid */
+ if(pSocket==0)
+ return;
+
+ pSocket->m_nLastError=0;
+ nFD = pSocket->m_Socket;
+
+ if (nFD == OSL_INVALID_SOCKET)
+ return;
+
+ pSocket->m_Socket = OSL_INVALID_SOCKET;
+
+#if defined(LINUX)
+ pSocket->m_bIsInShutdown = sal_True;
+
+ if ( pSocket->m_bIsAccepting == sal_True )
+ {
+ int nConnFD;
+ union {
+ struct sockaddr aSockAddr;
+ struct sockaddr_in aSockAddrIn;
+ } s;
+ socklen_t nSockLen = sizeof(s.aSockAddr);
+
+ nRet = getsockname(nFD, &s.aSockAddr, &nSockLen);
+#if OSL_DEBUG_LEVEL > 1
+ if ( nRet < 0 )
+ {
+ perror("getsockname");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+
+ if ( s.aSockAddr.sa_family == AF_INET )
+ {
+ if ( s.aSockAddrIn.sin_addr.s_addr == htonl(INADDR_ANY) )
+ {
+ s.aSockAddrIn.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
+
+ nConnFD = socket(AF_INET, SOCK_STREAM, 0);
+#if OSL_DEBUG_LEVEL > 1
+ if ( nConnFD < 0 )
+ {
+ perror("socket");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+
+ nRet = connect(nConnFD, &s.aSockAddr, sizeof(s.aSockAddr));
+#if OSL_DEBUG_LEVEL > 1
+ if ( nRet < 0 )
+ {
+ perror("connect");
+ }
+#endif /* OSL_DEBUG_LEVEL */
+ close(nConnFD);
+ }
+ pSocket->m_bIsAccepting = sal_False;
+ }
+#endif /* LINUX */
+
+ /* registrierten Callback ausfuehren */
+ if (pSocket->m_CloseCallback != NULL)
+ {
+ pSocket->m_CloseCallback(pSocket->m_CallbackArg);
+ }
+
+ nRet=close(nFD);
+ if ( nRet != 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("closeSocket close error '%s'\n",strerror(errno));
+ }
+
+ pSocket->m_Socket = OSL_INVALID_SOCKET;
+}
+
+/*****************************************************************************/
+/* osl_getLocalAddrOfSocket */
+/* Note that I rely on the fact that oslSocketAddr and struct sockaddr */
+/* are the same! I don't like it very much but see no other easy way to conceal */
+/* the struct sockaddr from the eyes of the user. */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket)
+{
+ socklen_t AddrLen;
+ struct sockaddr Addr;
+ oslSocketAddr pAddr;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return ((oslSocketAddr)NULL);
+
+ AddrLen= sizeof(struct sockaddr);
+
+ if (getsockname(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
+ return ((oslSocketAddr)NULL);
+
+ pAddr = __osl_createSocketAddrFromSystem( &Addr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_getPeerAddrOfSocket */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
+{
+ socklen_t AddrLen;
+ struct sockaddr Addr;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return 0;
+ }
+
+ pSocket->m_nLastError=0;
+ AddrLen= sizeof(struct sockaddr);
+
+ if(getpeername(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
+ {
+ pSocket->m_nLastError=errno;
+ return 0;
+ }
+ return __osl_createSocketAddrFromSystem( &Addr );
+}
+
+/*****************************************************************************/
+/* osl_bindAddrToSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_bindAddrToSocket(oslSocket pSocket,
+ oslSocketAddr pAddr)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket && pAddr );
+ if ( pSocket == 0 || pAddr == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet = bind(pSocket->m_Socket, &(pAddr->m_sockaddr), sizeof(struct sockaddr));
+
+ if ( nRet == OSL_SOCKET_ERROR)
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+
+/*****************************************************************************/
+/* osl_listenOnSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_listenOnSocket(oslSocket pSocket,
+ sal_Int32 MaxPendingConnections)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet = listen(pSocket->m_Socket,
+ MaxPendingConnections == -1 ?
+ SOMAXCONN :
+ MaxPendingConnections);
+ if ( nRet == OSL_SOCKET_ERROR)
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+
+/*****************************************************************************/
+/* osl_connectSocketTo */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_connectSocketTo(oslSocket pSocket,
+ oslSocketAddr pAddr,
+ const TimeValue* pTimeout)
+{
+ fd_set WriteSet;
+ fd_set ExcptSet;
+ int ReadyHandles;
+ struct timeval tv;
+ oslSocketResult Result= osl_Socket_Ok;
+
+ OSL_PRECOND(pSocket, "osl_connectSocketTo(): need a valid socket!\n");
+
+ if ( pSocket == 0 )
+ {
+ return osl_Socket_Error;
+ }
+
+ pSocket->m_nLastError=0;
+
+ if (osl_isNonBlockingMode(pSocket))
+ {
+ if (connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
+ return osl_Socket_Ok;
+ else
+ if (errno == EWOULDBLOCK || errno == EINPROGRESS)
+ {
+ pSocket->m_nLastError=EINPROGRESS;
+ return osl_Socket_InProgress;
+ }
+
+
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("can't connect : '%s'",strerror(errno));
+ return osl_Socket_Error;
+ }
+
+ /* set socket temporarily to non-blocking */
+ OSL_VERIFY(osl_enableNonBlockingMode(pSocket, sal_True));
+
+ /* initiate connect */
+ if(connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
+ {
+ /* immediate connection */
+ osl_enableNonBlockingMode(pSocket, sal_False);
+
+ return osl_Socket_Ok;
+ }
+ else
+ {
+ /* really an error or just delayed? */
+ if (errno != EINPROGRESS)
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE(
+ "osl_connectSocketTo(): connect failed: errno: %d (%s)\n",
+ errno, strerror(errno));
+
+ osl_enableNonBlockingMode(pSocket, sal_False);
+ return osl_Socket_Error;
+ }
+ }
+
+
+ /* prepare select set for socket */
+ FD_ZERO(&WriteSet);
+ FD_ZERO(&ExcptSet);
+ FD_SET(pSocket->m_Socket, &WriteSet);
+ FD_SET(pSocket->m_Socket, &ExcptSet);
+
+ /* prepare timeout */
+ if (pTimeout)
+ {
+ /* divide milliseconds into seconds and microseconds */
+ tv.tv_sec= pTimeout->Seconds;
+ tv.tv_usec= pTimeout->Nanosec / 1000L;
+ }
+
+ /* select */
+ ReadyHandles= select(pSocket->m_Socket+1,
+ 0,
+ PTR_FD_SET(WriteSet),
+ PTR_FD_SET(ExcptSet),
+ (pTimeout) ? &tv : 0);
+
+ if (ReadyHandles > 0) /* connected */
+ {
+ if ( FD_ISSET(pSocket->m_Socket, &WriteSet ) )
+ {
+ int nErrorCode = 0;
+ socklen_t nErrorSize = sizeof( nErrorCode );
+
+ int nSockOpt;
+
+ nSockOpt = getsockopt ( pSocket->m_Socket, SOL_SOCKET, SO_ERROR,
+ &nErrorCode, &nErrorSize );
+ if ( (nSockOpt == 0) && (nErrorCode == 0))
+ Result = osl_Socket_Ok;
+ else
+ Result = osl_Socket_Error;
+ }
+ else
+ {
+ Result= osl_Socket_Error;
+ }
+ }
+ else if (ReadyHandles < 0) /* error */
+ {
+ if (errno == EBADF) /* most probably interrupted by close() */
+ {
+ /* do not access pSockImpl because it is about to be or */
+ /* already destroyed */
+ return osl_Socket_Interrupted;
+ }
+ else
+ {
+ pSocket->m_nLastError=errno;
+ Result= osl_Socket_Error;
+ }
+ }
+ else /* timeout */
+ {
+ pSocket->m_nLastError=errno;
+ Result= osl_Socket_TimedOut;
+ }
+
+ osl_enableNonBlockingMode(pSocket, sal_False);
+
+ return Result;
+}
+
+
+/*****************************************************************************/
+/* osl_acceptConnectionOnSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_acceptConnectionOnSocket(oslSocket pSocket,
+ oslSocketAddr* ppAddr)
+{
+ struct sockaddr Addr;
+ int Connection, Flags;
+ oslSocket pConnectionSockImpl;
+
+ socklen_t AddrLen = sizeof(struct sockaddr);
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return 0;
+ }
+
+ pSocket->m_nLastError=0;
+#if defined(LINUX)
+ pSocket->m_bIsAccepting = sal_True;
+#endif /* LINUX */
+
+ if( ppAddr && *ppAddr )
+ {
+ osl_destroySocketAddr( *ppAddr );
+ *ppAddr = 0;
+ }
+
+ /* prevent Linux EINTR behaviour */
+ do
+ {
+ Connection = accept(pSocket->m_Socket, &Addr, &AddrLen);
+ } while (Connection == -1 && errno == EINTR);
+
+
+ /* accept failed? */
+ if( Connection == OSL_SOCKET_ERROR )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_acceptConnectionOnSocket : accept error '%s'\n",strerror(errno));
+
+#if defined(LINUX)
+ pSocket->m_bIsAccepting = sal_False;
+#endif /* LINUX */
+ return 0;
+ }
+
+ OSL_ASSERT(AddrLen == sizeof(struct sockaddr));
+
+
+#if defined(LINUX)
+ if ( pSocket->m_bIsInShutdown == sal_True )
+ {
+ close(Connection);
+ OSL_TRACE("osl_acceptConnectionOnSocket : close while accept\n");
+ return 0;
+ }
+#endif /* LINUX */
+
+
+ if(ppAddr)
+ {
+ *ppAddr= __osl_createSocketAddrFromSystem(&Addr);
+ }
+
+ /* alloc memory */
+ pConnectionSockImpl= __osl_createSocketImpl(OSL_INVALID_SOCKET);
+
+ /* set close-on-exec flag */
+ if ((Flags = fcntl(Connection, F_GETFD, 0)) != -1)
+ {
+ Flags |= FD_CLOEXEC;
+ if (fcntl(Connection, F_SETFD, Flags) == -1)
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_acceptConnectionOnSocket failed changing socket flags. Errno: %d (%s)\n",
+ errno,
+ strerror(errno));
+ }
+
+ }
+
+ pConnectionSockImpl->m_Socket = Connection;
+ pConnectionSockImpl->m_nLastError = 0;
+ pConnectionSockImpl->m_CloseCallback = NULL;
+ pConnectionSockImpl->m_CallbackArg = NULL;
+#if defined(LINUX)
+ pConnectionSockImpl->m_bIsAccepting = sal_False;
+
+ pSocket->m_bIsAccepting = sal_False;
+#endif /* LINUX */
+ return pConnectionSockImpl;
+}
+
+/*****************************************************************************/
+/* osl_receiveSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveSocket(oslSocket pSocket,
+ void* pBuffer,
+ sal_uInt32 BytesToRead,
+ oslSocketMsgFlag Flag)
+{
+ int nRead;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_receiveSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ do
+ {
+ nRead = recv(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToRead,
+ MSG_FLAG_TO_NATIVE(Flag));
+ } while ( nRead < 0 && errno == EINTR );
+
+ if ( nRead < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,strerror(errno));
+ }
+ else if ( nRead == 0 )
+ {
+ OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
+ }
+
+ return nRead;
+}
+
+
+/*****************************************************************************/
+/* osl_receiveFromSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveFromSocket(oslSocket pSocket,
+ oslSocketAddr pSenderAddr,
+ void* pBuffer,
+ sal_uInt32 BufferSize,
+ oslSocketMsgFlag Flag)
+{
+ int nRead;
+ struct sockaddr *pSystemSockAddr = 0;
+ socklen_t AddrLen = 0;
+ if( pSenderAddr )
+ {
+ AddrLen = sizeof( struct sockaddr );
+ pSystemSockAddr = &(pSenderAddr->m_sockaddr);
+ }
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_receiveFromSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRead = recvfrom(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BufferSize,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ &AddrLen);
+
+ if ( nRead < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_receiveFromSocket failed : %i '%s'",nRead,strerror(errno));
+ }
+ else if ( nRead == 0 )
+ {
+ OSL_TRACE("osl_receiveSocket failed : %i '%s'",nRead,"EOL");
+ }
+
+ return nRead;
+}
+
+
+/*****************************************************************************/
+/* osl_sendSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendSocket(oslSocket pSocket,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ int nWritten;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_sendSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ do
+ {
+ nWritten = send(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag));
+ } while ( nWritten < 0 && errno == EINTR );
+
+
+ if ( nWritten < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,strerror(errno));
+ }
+ else if ( nWritten == 0 )
+ {
+ OSL_TRACE("osl_sendSocket failed : %i '%s'",nWritten,"EOL");
+ }
+
+ return nWritten;
+}
+
+/*****************************************************************************/
+/* osl_sendToSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendToSocket(oslSocket pSocket,
+ oslSocketAddr ReceiverAddr,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ int nWritten;
+
+ struct sockaddr *pSystemSockAddr = 0;
+ int AddrLen = 0;
+ if( ReceiverAddr )
+ {
+ pSystemSockAddr = &(ReceiverAddr->m_sockaddr);
+ AddrLen = sizeof( struct sockaddr );
+ }
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ OSL_TRACE("osl_sendToSocket : Invalid socket");
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ /* ReceiverAddr might be 0 when used on a connected socket. */
+ /* Then sendto should behave like send. */
+
+ nWritten = sendto(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ AddrLen);
+
+ if ( nWritten < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,strerror(errno));
+ }
+ else if ( nWritten == 0 )
+ {
+ OSL_TRACE("osl_sendToSocket failed : %i '%s'",nWritten,"EOL");
+ }
+
+ return nWritten;
+}
+
+/*****************************************************************************/
+/* osl_readSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_readSocket (
+ oslSocket pSocket, void *pBuffer, sal_Int32 n )
+{
+ sal_uInt8 * Ptr = (sal_uInt8 *)pBuffer;
+ sal_uInt32 BytesRead= 0;
+ sal_uInt32 BytesToRead= n;
+
+ OSL_ASSERT( pSocket);
+
+ /* loop until all desired bytes were read or an error occured */
+ while (BytesToRead > 0)
+ {
+ sal_Int32 RetVal;
+ RetVal= osl_receiveSocket(pSocket,
+ Ptr,
+ BytesToRead,
+ osl_Socket_MsgNormal);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToRead -= RetVal;
+ BytesRead += RetVal;
+ Ptr += RetVal;
+ }
+
+ return BytesRead;
+}
+
+/*****************************************************************************/
+/* osl_writeSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_writeSocket(
+ oslSocket pSocket, const void *pBuffer, sal_Int32 n )
+{
+ /* loop until all desired bytes were send or an error occured */
+ sal_uInt32 BytesSend= 0;
+ sal_uInt32 BytesToSend= n;
+ sal_uInt8 *Ptr = ( sal_uInt8 * )pBuffer;
+
+ OSL_ASSERT( pSocket );
+
+ while (BytesToSend > 0)
+ {
+ sal_Int32 RetVal;
+
+ RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToSend -= RetVal;
+ BytesSend += RetVal;
+ Ptr += RetVal;
+
+ }
+ return BytesSend;
+}
+
+/*****************************************************************************/
+/* __osl_socket_poll */
+/*****************************************************************************/
+
+#ifdef HAVE_POLL_H /* poll() */
+
+sal_Bool __osl_socket_poll (
+ oslSocket pSocket,
+ const TimeValue* pTimeout,
+ short nEvent)
+{
+ struct pollfd fds;
+ int timeout;
+ int result;
+
+ OSL_ASSERT(pSocket);
+ pSocket->m_nLastError = 0;
+
+ fds.fd = pSocket->m_Socket;
+ fds.events = nEvent;
+ fds.revents = 0;
+
+ timeout = -1;
+ if (pTimeout)
+ {
+ /* Convert to [ms] */
+ timeout = pTimeout->Seconds * 1000;
+ timeout += pTimeout->Nanosec / (1000 * 1000);
+ }
+
+ result = poll (&fds, 1, timeout);
+ if (result < 0)
+ {
+ pSocket->m_nLastError = errno;
+ OSL_TRACE("__osl_socket_poll(): poll error: %d (%s)",
+ errno, strerror(errno));
+ return sal_False;
+ }
+ if (result == 0)
+ {
+ /* Timeout */
+ return sal_False;
+ }
+
+ return ((fds.revents & nEvent) == nEvent);
+}
+
+#else /* select() */
+
+sal_Bool __osl_socket_poll (
+ oslSocket pSocket,
+ const TimeValue* pTimeout,
+ short nEvent)
+{
+ fd_set fds;
+ struct timeval tv;
+ int result;
+
+ OSL_ASSERT(pSocket);
+ pSocket->m_nLastError = 0;
+
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ if (pTimeout)
+ {
+ /* Convert to 'timeval' */
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000;
+ }
+
+ result = select (
+ pSocket->m_Socket + 1,
+ (nEvent == POLLIN ) ? PTR_FD_SET(fds) : NULL,
+ (nEvent == POLLOUT) ? PTR_FD_SET(fds) : NULL,
+ (nEvent == POLLPRI) ? PTR_FD_SET(fds) : NULL,
+ (pTimeout) ? &tv : NULL);
+
+ if (result < 0)
+ {
+ pSocket->m_nLastError = errno;
+ OSL_TRACE("__osl_socket_poll(): select error: %d (%s)",
+ errno, strerror(errno));
+ return sal_False;
+ }
+ if (result == 0)
+ {
+ /* Timeout */
+ return sal_False;
+ }
+
+ return (FD_ISSET(pSocket->m_Socket, &fds) ? sal_True : sal_False);
+}
+
+#endif /* HAVE_POLL_H */
+
+/*****************************************************************************/
+/* osl_isReceiveReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isReceiveReady (
+ oslSocket pSocket, const TimeValue* pTimeout)
+{
+ OSL_ASSERT(pSocket);
+ if (pSocket == NULL)
+ {
+ /* ENOTSOCK */
+ return sal_False;
+ }
+
+ return __osl_socket_poll (pSocket, pTimeout, POLLIN);
+}
+
+/*****************************************************************************/
+/* osl_isSendReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isSendReady (
+ oslSocket pSocket, const TimeValue* pTimeout)
+{
+ OSL_ASSERT(pSocket);
+ if (pSocket == NULL)
+ {
+ /* ENOTSOCK */
+ return sal_False;
+ }
+
+ return __osl_socket_poll (pSocket, pTimeout, POLLOUT);
+}
+
+/*****************************************************************************/
+/* osl_isExceptionPending */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isExceptionPending (
+ oslSocket pSocket, const TimeValue* pTimeout)
+{
+ OSL_ASSERT(pSocket);
+ if (pSocket == NULL)
+ {
+ /* ENOTSOCK */
+ return sal_False;
+ }
+
+ return __osl_socket_poll (pSocket, pTimeout, POLLPRI);
+}
+
+/*****************************************************************************/
+/* osl_shutdownSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_shutdownSocket(oslSocket pSocket,
+ oslSocketDirection Direction)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet=shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction));
+ if (nRet != 0 )
+ {
+ pSocket->m_nLastError=errno;
+ OSL_TRACE("shutdown error '%s'\n",strerror(errno));
+ }
+ return (nRet==0);
+}
+
+
+/*****************************************************************************/
+/* osl_getSocketOption */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getSocketOption(oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ socklen_t nOptLen = (socklen_t) BufferLen;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return -1;
+ }
+
+ pSocket->m_nLastError=0;
+
+ if(getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ &nOptLen) == -1)
+ {
+ pSocket->m_nLastError=errno;
+ return -1;
+ }
+
+ return BufferLen;
+}
+
+/*****************************************************************************/
+/* osl_setSocketOption */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setSocketOption(oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ nRet = setsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ BufferLen);
+
+ if ( nRet < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_enableNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_enableNonBlockingMode(oslSocket pSocket,
+ sal_Bool On)
+{
+ int flags;
+ int nRet;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
+
+ if (On)
+ flags |= O_NONBLOCK;
+ else
+ flags &= ~(O_NONBLOCK);
+
+ nRet = fcntl(pSocket->m_Socket, F_SETFL, flags);
+
+ if ( nRet < 0 )
+ {
+ pSocket->m_nLastError=errno;
+ return sal_False;
+ }
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_isNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket)
+{
+ int flags;
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSocket->m_nLastError=0;
+
+ flags = fcntl(pSocket->m_Socket, F_GETFL, 0);
+
+ if (flags == -1 || !(flags & O_NONBLOCK))
+ return sal_False;
+ else
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_getSocketType */
+/*****************************************************************************/
+oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket)
+{
+ int Type=0;
+ socklen_t TypeSize= sizeof(Type);
+
+ OSL_ASSERT(pSocket);
+ if ( pSocket == 0 )
+ {
+ return osl_Socket_TypeInvalid;
+ }
+
+ pSocket->m_nLastError=0;
+
+ if(getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket),
+ OPTION_TO_NATIVE(osl_Socket_OptionType),
+ (sal_Char*)&Type,
+ &TypeSize) == -1)
+ {
+ /* error */
+ pSocket->m_nLastError=errno;
+ return osl_Socket_TypeInvalid;
+ }
+
+ return TYPE_FROM_NATIVE(Type);
+
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketErrorDescription */
+/*****************************************************************************/
+void SAL_CALL osl_getLastSocketErrorDescription(oslSocket Socket, rtl_uString **ustrError)
+{
+ sal_Char pszError[1024];
+
+ pszError[0] = '\0';
+
+ osl_psz_getLastSocketErrorDescription(Socket,pszError,sizeof(pszError));
+
+ rtl_uString_newFromAscii(ustrError,pszError);
+
+ return;
+}
+
+
+void SAL_CALL osl_psz_getLastSocketErrorDescription(oslSocket pSocket, sal_Char* pBuffer, sal_uInt32 BufferSize)
+{
+ /* make shure pBuffer will be a zero-terminated string even when strncpy has to cut */
+ pBuffer[BufferSize-1]= '\0';
+
+ if ( pSocket == 0 )
+ {
+ strncpy(pBuffer, strerror(EINVAL), BufferSize-1);
+ return;
+ }
+
+ strncpy(pBuffer, strerror(pSocket->m_nLastError), BufferSize-1);
+ return;
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketError */
+/*****************************************************************************/
+oslSocketError SAL_CALL osl_getLastSocketError(oslSocket pSocket)
+{
+ if ( pSocket == 0 )
+ {
+ return ERROR_FROM_NATIVE(EINVAL);
+ }
+
+ return ERROR_FROM_NATIVE(pSocket->m_nLastError);
+}
+
+/*****************************************************************************/
+/* SocketSet */
+/*****************************************************************************/
+typedef struct _TSocketSetImpl
+{
+ int m_MaxHandle; /* for select(), the largest descriptor in the set */
+ fd_set m_Set; /* the set of descriptors */
+
+} TSocketSetImpl;
+
+/*****************************************************************************/
+/* osl_createSocketSet */
+/*****************************************************************************/
+oslSocketSet SAL_CALL osl_createSocketSet()
+{
+ TSocketSetImpl* pSet;
+
+ pSet= (TSocketSetImpl*)malloc(sizeof(TSocketSetImpl));
+
+ OSL_ASSERT(pSet);
+
+ if(pSet)
+ {
+ pSet->m_MaxHandle= 0;
+ FD_ZERO(&pSet->m_Set);
+ }
+
+ return (oslSocketSet)pSet;
+}
+
+/*****************************************************************************/
+/* osl_destroySocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_destroySocketSet(oslSocketSet Set)
+{
+ if(Set)
+ free(Set);
+}
+
+/*****************************************************************************/
+/* osl_clearSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_clearSocketSet(oslSocketSet Set)
+{
+ TSocketSetImpl* pSet;
+ OSL_ASSERT(Set);
+ if ( Set == 0 )
+ {
+ return;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+ pSet->m_MaxHandle= 0;
+
+ FD_ZERO(&pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_addToSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_addToSocketSet(oslSocketSet Set, oslSocket pSocket)
+{
+ TSocketSetImpl* pSet;
+
+ OSL_ASSERT(Set);
+ OSL_ASSERT(pSocket);
+
+ if ( Set == 0 || pSocket == 0)
+ {
+ return;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+
+ /* correct max handle */
+ if(pSocket->m_Socket > pSet->m_MaxHandle)
+ pSet->m_MaxHandle= pSocket->m_Socket;
+ FD_SET(pSocket->m_Socket, &pSet->m_Set);
+
+}
+
+/*****************************************************************************/
+/* osl_removeFromSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_removeFromSocketSet(oslSocketSet Set, oslSocket pSocket)
+{
+ TSocketSetImpl* pSet;
+
+ OSL_ASSERT(Set);
+ OSL_ASSERT(pSocket);
+
+ if ( Set == 0 || pSocket == 0)
+ {
+ return;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+
+ /* correct max handle */
+ if(pSocket->m_Socket == pSet->m_MaxHandle)
+ {
+ /* not optimal, since the next used descriptor might be */
+ /* much smaller than m_Socket-1, but it will do */
+ pSet->m_MaxHandle--;
+ if(pSet->m_MaxHandle < 0)
+ {
+ pSet->m_MaxHandle= 0; /* avoid underflow */
+ }
+ }
+
+ FD_CLR(pSocket->m_Socket, &pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_isInSocketSet */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isInSocketSet(oslSocketSet Set, oslSocket pSocket)
+{
+ TSocketSetImpl* pSet;
+
+ OSL_ASSERT(Set);
+ OSL_ASSERT(pSocket);
+ if ( Set == 0 || pSocket == 0 )
+ {
+ return sal_False;
+ }
+
+ pSet= (TSocketSetImpl*)Set;
+
+ return (FD_ISSET(pSocket->m_Socket, &pSet->m_Set) != 0);
+}
+
+/*****************************************************************************/
+/* osl_demultiplexSocketEvents */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_demultiplexSocketEvents(oslSocketSet IncomingSet,
+ oslSocketSet OutgoingSet,
+ oslSocketSet OutOfBandSet,
+ const TimeValue* pTimeout)
+{
+ int MaxHandle= 0;
+ struct timeval tv;
+ TSocketSetImpl* pInSet;
+ TSocketSetImpl* pOutSet;
+ TSocketSetImpl* pOOBSet;
+
+ if (pTimeout)
+ {
+ /* non-blocking call */
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ /* map opaque data to impl-types */
+ pInSet= (TSocketSetImpl*)IncomingSet;
+ pOutSet= (TSocketSetImpl*)OutgoingSet;
+ pOOBSet= (TSocketSetImpl*)OutOfBandSet;
+
+ /* get max handle from all sets */
+ if (pInSet)
+ MaxHandle= pInSet->m_MaxHandle;
+
+ if (pOutSet && (pOutSet->m_MaxHandle > MaxHandle))
+ MaxHandle= pOutSet->m_MaxHandle;
+
+ if (pOOBSet && (pOOBSet->m_MaxHandle > MaxHandle))
+ MaxHandle= pOOBSet->m_MaxHandle;
+
+ return select(MaxHandle+1,
+ pInSet ? PTR_FD_SET(pInSet->m_Set) : 0,
+ pOutSet ? PTR_FD_SET(pOutSet->m_Set) : 0,
+ pOOBSet ? PTR_FD_SET(pOOBSet->m_Set) : 0,
+ pTimeout ? &tv : 0);
+}
+
diff --git a/sal/osl/unx/sockimpl.h b/sal/osl/unx/sockimpl.h
new file mode 100644
index 000000000000..86122e850875
--- /dev/null
+++ b/sal/osl/unx/sockimpl.h
@@ -0,0 +1,78 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_SOCKETIMPL_H_
+#define _OSL_SOCKETIMPL_H_
+
+#include <osl/pipe.h>
+#include <osl/socket.h>
+#include <osl/interlck.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* (*oslCloseCallback) (void*);
+
+struct oslSocketImpl {
+ int m_Socket;
+ int m_nLastError;
+ oslCloseCallback m_CloseCallback;
+ void* m_CallbackArg;
+ oslInterlockedCount m_nRefCount;
+#if defined(LINUX)
+ sal_Bool m_bIsAccepting;
+ sal_Bool m_bIsInShutdown;
+#endif
+};
+
+struct oslSocketAddrImpl
+{
+ sal_Int32 m_nRefCount;
+ struct sockaddr m_sockaddr;
+};
+
+struct oslPipeImpl {
+ int m_Socket;
+ sal_Char m_Name[PATH_MAX + 1];
+ oslInterlockedCount m_nRefCount;
+ sal_Bool m_bClosed;
+#if defined(LINUX)
+ sal_Bool m_bIsAccepting;
+ sal_Bool m_bIsInShutdown;
+#endif
+};
+
+oslSocket __osl_createSocketImpl(int Socket);
+void __osl_destroySocketImpl(oslSocket pImpl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sal/osl/unx/system.c b/sal/osl/unx/system.c
new file mode 100644
index 000000000000..0ea3b819438c
--- /dev/null
+++ b/sal/osl/unx/system.c
@@ -0,0 +1,599 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#ifdef NO_PTHREAD_RTL
+
+static pthread_mutex_t getrtl_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* struct passwd differs on some platforms */
+#if defined NETBSD
+struct passwd *getpwnam_r(const char* name, struct passwd* s, char* buffer, int size )
+{
+ struct passwd* res;
+
+ pthread_mutex_lock(&getrtl_mutex);
+
+ if ( (res = getpwnam(name)) )
+ {
+ int nname, npasswd, nclass, ngecos, ndir;
+
+ nname= strlen(res->pw_name)+1;
+ npasswd= strlen(res->pw_passwd)+1;
+ nclass= strlen(res->pw_class)+1;
+ ngecos= strlen(res->pw_gecos)+1;
+ ndir= strlen(res->pw_dir)+1;
+
+ if (nname+npasswd+nclass+ngecos
+ +ndir+strlen(res->pw_shell) < size)
+ {
+ memcpy(s, res, sizeof(struct passwd));
+
+ strcpy(buffer, res->pw_name);
+ s->pw_name = buffer;
+ buffer += nname;
+
+ strcpy(buffer, res->pw_passwd);
+ s->pw_passwd = buffer;
+ buffer += npasswd;
+
+ strcpy(buffer, res->pw_class);
+ s->pw_class = buffer;
+ buffer += nclass;
+
+ strcpy(buffer, res->pw_gecos);
+ s->pw_gecos = buffer;
+ buffer += ngecos;
+
+ strcpy(buffer, res->pw_dir);
+ s->pw_dir = buffer;
+ buffer += ndir;
+
+ strcpy(buffer, res->pw_shell);
+ s->pw_shell = buffer;
+
+ res = s;
+ }
+ else
+ res = 0;
+ }
+
+ pthread_mutex_unlock(&getrtl_mutex);
+
+ return(res);
+}
+
+int getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer,
+ size_t buflen, struct passwd **result)
+{
+ struct passwd* res;
+ int retval = 0;
+
+ pthread_mutex_lock(&getrtl_mutex);
+
+ if ( (res = getpwuid(uid)) )
+ {
+ size_t pw_name, pw_passwd, pw_class, pw_gecos, pw_dir, pw_shell;
+
+ pw_name = strlen(res->pw_name)+1;
+ pw_passwd = strlen(res->pw_passwd)+1;
+ pw_class = strlen(res->pw_class)+1;
+ pw_gecos = strlen(res->pw_gecos)+1;
+ pw_dir = strlen(res->pw_dir)+1;
+ pw_shell = strlen(res->pw_shell)+1;
+
+ if (pw_name+pw_passwd+pw_class+pw_gecos
+ +pw_dir+pw_shell < buflen)
+ {
+ memcpy(pwd, res, sizeof(struct passwd));
+
+ strncpy(buffer, res->pw_name, pw_name);
+ pwd->pw_name = buffer;
+ buffer += pw_name;
+
+ strncpy(buffer, res->pw_passwd, pw_passwd);
+ pwd->pw_passwd = buffer;
+ buffer += pw_passwd;
+
+ strncpy(buffer, res->pw_class, pw_class);
+ pwd->pw_class = buffer;
+ buffer += pw_class;
+
+ strncpy(buffer, res->pw_gecos, pw_gecos);
+ pwd->pw_gecos = buffer;
+ buffer += pw_gecos;
+
+ strncpy(buffer, res->pw_dir, pw_dir);
+ pwd->pw_dir = buffer;
+ buffer += pw_dir;
+
+ strncpy(buffer, res->pw_shell, pw_shell);
+ pwd->pw_shell = buffer;
+ buffer += pw_shell;
+
+ *result = pwd ;
+ retval = 0 ;
+
+ }
+ else
+ retval = ENOMEM;
+ }
+ else
+ retval = errno ;
+
+ pthread_mutex_unlock(&getrtl_mutex);
+
+ return retval;
+}
+
+struct tm *localtime_r(const time_t *timep, struct tm *buffer)
+{
+ struct tm* res;
+
+ pthread_mutex_lock(&getrtl_mutex);
+
+ if ( (res = localtime(timep)))
+ {
+ memcpy(buffer, res, sizeof(struct tm));
+ res = buffer;
+ }
+
+ pthread_mutex_unlock(&getrtl_mutex);
+
+ return res;
+}
+
+struct tm *gmtime_r(const time_t *timep, struct tm *buffer)
+{
+ struct tm* res;
+
+ pthread_mutex_lock(&getrtl_mutex);
+
+ if ( (res = gmtime(timep)) )
+ {
+ memcpy(buffer, res, sizeof(struct tm));
+ res = buffer;
+ }
+
+ pthread_mutex_unlock(&getrtl_mutex);
+
+ return res;
+}
+#endif /* defined NETBSD */
+
+#ifdef SCO
+#include <pwd.h>
+#include <shadow.h>
+#include <sys/types.h>
+
+struct spwd *getspnam_r(const char *name, struct spwd* s, char* buffer, int size )
+{
+ struct spwd* res;
+
+ pthread_mutex_lock(&getrtl_mutex);
+
+ if ( res = getspnam(name) )
+ {
+ int nnamp;
+
+ nnamp = strlen(res->sp_namp)+1;
+
+ if (nnamp+strlen(res->sp_pwdp) < size) {
+ memcpy(s, res, sizeof(struct spwd));
+
+ strcpy(buffer, res->sp_namp);
+ s->sp_namp = buffer;
+ buffer += nnamp;
+
+ strcpy(buffer, res->sp_pwdp);
+ s->sp_pwdp = buffer;
+
+ res = s;
+ }
+ else
+ res = 0;
+ }
+
+ pthread_mutex_unlock(&getrtl_mutex);
+
+ return res;
+}
+
+struct passwd *getpwnam_r(const char* name, struct passwd* s, char* buffer, int size )
+{
+ struct passwd* res;
+
+ pthread_mutex_lock(&getrtl_mutex);
+
+ if ( res = getpwnam(name) )
+ {
+ int nname, npasswd, nage;
+ int ncomment, ngecos, ndir;
+
+ nname= strlen(res->pw_name)+1;
+ npasswd= strlen(res->pw_passwd)+1;
+ nage= strlen(res->pw_age)+1;
+ ncomment= strlen(res->pw_comment)+1;
+ ngecos= strlen(res->pw_gecos)+1;
+ ndir= strlen(res->pw_dir)+1;
+
+ if (nname+npasswd+nage+ncomment+ngecos+ndir
+ +strlen(res->pw_shell) < size)
+ {
+ memcpy(s, res, sizeof(struct passwd));
+
+ strcpy(buffer, res->pw_name);
+ s->pw_name = buffer;
+ buffer += nname;
+
+ strcpy(buffer, res->pw_passwd);
+ s->pw_passwd = buffer;
+ buffer += npasswd;
+
+ strcpy(buffer, res->pw_age);
+ s->pw_age = buffer;
+ buffer += nage;
+
+ strcpy(buffer, res->pw_comment);
+ s->pw_comment = buffer;
+ buffer += ncomment;
+
+ strcpy(buffer, res->pw_gecos);
+ s->pw_gecos = buffer;
+ buffer += ngecos;
+
+ strcpy(buffer, res->pw_dir);
+ s->pw_dir = buffer;
+ buffer += ndir;
+
+ strcpy(buffer, res->pw_shell);
+ s->pw_shell = buffer;
+
+ res = s;
+ }
+ else
+ res = 0;
+ }
+
+ pthread_mutex_unlock(&getrtl_mutex);
+
+ return res;
+}
+#endif /* defined SCO */
+
+#if !defined(FREEBSD) || (__FreeBSD_version < 601103)
+
+extern int h_errno;
+
+struct hostent *gethostbyname_r(const char *name, struct hostent *result,
+ char *buffer, int buflen, int *h_errnop)
+{
+ /* buffer layout: name\0
+ * array_of_pointer_to_aliases
+ * NULL
+ * alias1\0...aliasn\0
+ * array_of_pointer_to_addresses
+ * NULL
+ * addr1addr2addr3...addrn
+ */
+ struct hostent* res;
+
+ pthread_mutex_lock(&getrtl_mutex);
+
+ if ( (res = gethostbyname(name)) )
+ {
+ int nname, naliases, naddr_list, naliasesdata, n;
+ char **p, **parray, *data;
+
+ /* Check buffer size before copying, we want to leave the
+ * buffers unmodified in case something goes wrong.
+ *
+ * Is this required?
+ */
+
+ nname= strlen(res->h_name)+1;
+
+ naliases = naddr_list = naliasesdata = 0;
+
+ for ( p = res->h_aliases; *p != NULL; p++) {
+ naliases++;
+ naliasesdata += strlen(*p)+1;
+ }
+
+ for ( p = res->h_addr_list; *p != NULL; p++)
+ naddr_list++;
+
+ if ( nname
+ + (naliases+1)*sizeof(char*) + naliasesdata
+ + (naddr_list+1)*sizeof(char*) + naddr_list*res->h_length
+ <= buflen )
+ {
+ memcpy(result, res, sizeof(struct hostent));
+
+ strcpy(buffer, res->h_name);
+ result->h_name = buffer;
+ buffer += nname;
+
+ parray = (char**)buffer;
+ result->h_aliases = parray;
+ data = buffer + (naliases+1)*sizeof(char*);
+ for ( p = res->h_aliases; *p != NULL; p++) {
+ n = strlen(*p)+1;
+ *parray++ = data;
+ memcpy(data, *p, n);
+ data += n;
+ }
+ *parray = NULL;
+ buffer = data;
+ parray = (char**)buffer;
+ result->h_addr_list = parray;
+ data = buffer + (naddr_list+1)*sizeof(char*);
+ for ( p = res->h_addr_list; *p != NULL; p++) {
+ *parray++ = data;
+ memcpy(data, *p, res->h_length);
+ data += res->h_length;
+ }
+ *parray = NULL;
+
+ res = result;
+ }
+ else
+ {
+ errno = ERANGE;
+ res = NULL;
+ }
+ }
+ else
+ {
+ *h_errnop = h_errno;
+ }
+
+ pthread_mutex_unlock(&getrtl_mutex);
+
+ return res;
+}
+#endif /* !defined(FREEBSD) || (__FreeBSD_version < 601103) */
+
+#if defined(MACOSX)
+/*
+ * Add support for resolving Mac native alias files (not the same as unix alias files)
+ * returns 0 on success.
+ */
+int macxp_resolveAlias(char *path, int buflen)
+{
+ FSRef aFSRef;
+ OSStatus nErr;
+ Boolean bFolder;
+ Boolean bAliased;
+ char *unprocessedPath = path;
+
+ if ( *unprocessedPath == '/' )
+ unprocessedPath++;
+
+ int nRet = 0;
+ while ( !nRet && unprocessedPath && *unprocessedPath )
+ {
+ unprocessedPath = strchr( unprocessedPath, '/' );
+ if ( unprocessedPath )
+ *unprocessedPath = '\0';
+
+ nErr = noErr;
+ bFolder = FALSE;
+ bAliased = FALSE;
+ if ( FSPathMakeRef( (const UInt8 *)path, &aFSRef, 0 ) == noErr )
+ {
+ nErr = FSResolveAliasFileWithMountFlags( &aFSRef, TRUE, &bFolder, &bAliased, kResolveAliasFileNoUI );
+ if ( nErr == nsvErr )
+ {
+ errno = ENOENT;
+ nRet = -1;
+ }
+ else if ( nErr == noErr && bAliased )
+ {
+ char tmpPath[ PATH_MAX ];
+ if ( FSRefMakePath( &aFSRef, (UInt8 *)tmpPath, PATH_MAX ) == noErr )
+ {
+ int nLen = strlen( tmpPath ) + ( unprocessedPath ? strlen( unprocessedPath + 1 ) + 1 : 0 );
+ if ( nLen < buflen && nLen < PATH_MAX )
+ {
+ if ( unprocessedPath )
+ {
+ int nTmpPathLen = strlen( tmpPath );
+ strcat( tmpPath, "/" );
+ strcat( tmpPath, unprocessedPath + 1 );
+ strcpy( path, tmpPath);
+ unprocessedPath = path + nTmpPathLen;
+ }
+ else if ( !unprocessedPath )
+ {
+ strcpy( path, tmpPath);
+ }
+ }
+ else
+ {
+ errno = ENAMETOOLONG;
+ nRet = -1;
+ }
+ }
+ }
+ }
+
+ if ( unprocessedPath )
+ *unprocessedPath++ = '/';
+ }
+
+ return nRet;
+}
+
+#endif /* defined MACOSX */
+
+#endif /* NO_PTHREAD_RTL */
+
+#if (defined (LINUX) && (GLIBC >= 2))
+/* The linux kernel thread implemention, always return the pid of the
+ thread subprocess and not of the main process. So we save the main
+ pid at startup
+*/
+
+// Directly from libc.so.6, obviously missing from some unistd.h:
+extern __pid_t __getpid(void);
+
+static pid_t pid = -1;
+
+static void savePid(void) __attribute__((constructor));
+
+static void savePid(void)
+{
+ if (pid == -1)
+ pid = __getpid();
+}
+
+pid_t getpid(void)
+{
+ if (pid == -1)
+ savePid();
+
+ return (pid);
+}
+#endif /* (defined (LINUX) && (GLIBC >= 2)) */
+
+#ifdef NO_PTHREAD_SEMAPHORES
+int sem_init(sem_t* sem, int pshared, unsigned int value)
+{
+ pthread_mutex_init(&sem->mutex, PTHREAD_MUTEXATTR_DEFAULT);
+ pthread_cond_init(&sem->increased, PTHREAD_CONDATTR_DEFAULT);
+
+ sem->value = (int)value;
+ return 0;
+}
+
+int sem_destroy(sem_t* sem)
+{
+ pthread_mutex_destroy(&sem->mutex);
+ pthread_cond_destroy(&sem->increased);
+ sem->value = 0;
+ return 0;
+}
+
+int sem_wait(sem_t* sem)
+{
+ pthread_mutex_lock(&sem->mutex);
+
+ while (sem->value <= 0)
+ {
+ pthread_cond_wait(&sem->increased, &sem->mutex);
+ }
+
+ sem->value--;
+ pthread_mutex_unlock(&sem->mutex);
+
+ return 0;
+}
+
+int sem_trywait(sem_t* sem)
+{
+ int result = 0;
+
+ pthread_mutex_lock(&sem->mutex);
+
+ if (sem->value > 0)
+ {
+ sem->value--;
+ }
+ else
+ {
+ errno = EAGAIN;
+ result = -1;
+ }
+
+ pthread_mutex_unlock(&sem->mutex);
+
+ return result;
+}
+
+int sem_post(sem_t* sem)
+{
+ pthread_mutex_lock(&sem->mutex);
+
+ sem->value++;
+
+ pthread_mutex_unlock(&sem->mutex);
+
+ pthread_cond_signal(&sem->increased);
+
+ return 0;
+}
+#endif
+
+#if defined(FREEBSD)
+char *fcvt(double value, int ndigit, int *decpt, int *sign)
+{
+ static char ret[256];
+ char buf[256],zahl[256],format[256]="%";
+ char *v1,*v2;
+
+ if (value==0.0) value=1e-30;
+
+ if (value<0.0) *sign=1; else *sign=0;
+
+ if (value<1.0)
+ {
+ *decpt=(int)log10(value);
+ value*=pow(10.0,1-*decpt);
+ ndigit+=*decpt-1;
+ if (ndigit<0) ndigit=0;
+ }
+ else
+ {
+ *decpt=(int)log10(value)+1;
+ }
+
+ sprintf(zahl,"%d",ndigit);
+ strcat(format,zahl);
+ strcat(format,".");
+ strcat(format,zahl);
+ strcat(format,"f");
+
+ sprintf(buf,format,value);
+
+ if (ndigit!=0)
+ {
+ v1=strtok(buf,".");
+ v2=strtok(NULL,".");
+ strcpy(ret,v1);
+ strcat(ret,v2);
+ }
+ else
+ {
+ strcpy(ret,buf);
+ }
+
+ return(ret);
+}
+
+#endif
diff --git a/sal/osl/unx/system.h b/sal/osl/unx/system.h
new file mode 100644
index 000000000000..1cb0979490c0
--- /dev/null
+++ b/sal/osl/unx/system.h
@@ -0,0 +1,495 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __OSL_SYSTEM_H__
+#define __OSL_SYSTEM_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <signal.h>
+#include <utime.h>
+
+#include <pwd.h>
+
+#include <netdb.h>
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <sys/types.h>
+
+/* Make sockets of type AF_UNIX use underlying FS rights */
+#ifdef SOLARIS
+# define _XOPEN_SOURCE 500
+# include <sys/socket.h>
+# undef _XOPEN_SOURCE
+#else
+# include <sys/socket.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifdef SYSV
+# include <sys/utsname.h>
+#endif
+
+#ifdef LINUX
+# ifndef __USE_GNU
+# define __USE_GNU
+# endif
+
+#if GLIBC >= 2
+# include <shadow.h>
+# include <pthread.h>
+# include <sys/file.h>
+# include <sys/ioctl.h>
+# include <sys/uio.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <dlfcn.h>
+# include <endian.h>
+# include <sys/time.h>
+# include <semaphore.h>
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif __BYTE_ORDER == __BIG_ENDIAN
+# ifndef _BIG_ENDIAN
+# define _BIG_ENDIAN
+# endif
+# elif __BYTE_ORDER == __PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# define IORESOURCE_TRANSFER_BSD
+# define IOCHANNEL_TRANSFER_BSD_RENO
+# define pthread_testcancel()
+# define NO_PTHREAD_PRIORITY
+# define PTHREAD_SIGACTION pthread_sigaction
+#else
+# include <shadow.h>
+# include <asm/sigcontext.h>
+# include <pthread.h>
+# include <sys/file.h>
+# include <sys/ioctl.h>
+# include <linux/net.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <linux/elfcore.h>
+# include <dlfcn.h>
+# include <endian.h>
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif __BYTE_ORDER == __BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif __BYTE_ORDER == __PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# define IORESOURCE_TRANSFER_BSD
+# define IOCHANNEL_TRANSFER_BSD_RENO
+# define pthread_testcancel()
+# define NO_PTHREAD_RTL
+# define NO_PTHREAD_PRIORITY
+# define PTHREAD_SIGACTION pthread_sigaction
+#endif
+
+# ifndef ETIME
+# define ETIME ETIMEDOUT
+# endif
+
+#endif
+
+#ifdef NETBSD
+# define ETIME ETIMEDOUT
+# define _POSIX_THREAD_SYSCALL_SOFT 1
+# include <pthread.h>
+# include <netdb.h>
+# include <sys/sem.h>
+# include <sys/exec.h>
+# include <sys/filio.h>
+# include <sys/ioctl.h>
+# include <sys/time.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <dlfcn.h>
+# include <machine/endian.h>
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define _LITTLE_ENDIAN_OO
+# elif BYTE_ORDER == BIG_ENDIAN
+# define _BIG_ENDIAN_OO
+# elif BYTE_ORDER == PDP_ENDIAN
+# define _PDP_ENDIAN_OO
+# endif
+# define IORESOURCE_TRANSFER_BSD
+# define IOCHANNEL_TRANSFER_BSD_RENO
+# define pthread_testcancel()
+# define NO_PTHREAD_PRIORITY
+# define NO_PTHREAD_SEMAPHORES
+# define NO_PTHREAD_RTL
+# define PTHREAD_SIGACTION pthread_sigaction
+#endif
+
+#ifdef FREEBSD
+# define ETIME ETIMEDOUT
+# include <pthread.h>
+# include <sys/sem.h>
+# include <semaphore.h>
+# include <dlfcn.h>
+# include <sys/filio.h>
+# include <sys/ioctl.h>
+# include <sys/param.h>
+# include <sys/time.h>
+# include <sys/uio.h>
+# include <sys/exec.h>
+# include <vm/vm.h>
+# include <vm/vm_param.h>
+# include <vm/pmap.h>
+# include <vm/swap_pager.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# define IORESOURCE_TRANSFER_BSD
+# include <machine/endian.h>
+#if __FreeBSD_version < 500000
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif BYTE_ORDER == BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif BYTE_ORDER == PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+#endif
+# define NO_PTHREAD_RTL
+#endif
+
+#ifdef SCO
+# define AF_IPX -1
+# include <strings.h>
+# include <pthread.h>
+# include <shadow.h>
+# include <netdb.h>
+# include <sys/un.h>
+# include <sys/netinet/tcp.h>
+# include <sys/types.h>
+# include <sys/byteorder.h>
+# include <dlfcn.h>
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif BYTE_ORDER == BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif BYTE_ORDER == PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# define sched_yield() pthread_yield()
+# define pthread_testcancel()
+# define NO_PTHREAD_RTL
+# define NO_PTHREAD_PRIORITY
+extern int pthread_cancel(pthread_t);
+extern unsigned int nanosleep(unsigned int);
+# define SLEEP_TIMESPEC(timespec) (timespec .tv_sec > 0) ? sleep(timespec .tv_sec), nanosleep(timespec .tv_nsec) : nanosleep(timespec .tv_nsec)
+# define PATH_MAX _POSIX_PATH_MAX
+# define S_ISSOCK S_ISFIFO
+# define PTHREAD_SIGACTION pthread_sigaction
+# define STAT_PARENT stat
+#endif
+
+#ifdef AIX
+# define AF_IPX -1
+# include <strings.h>
+# include <pthread.h>
+# include <sys/time.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <sys/machine.h>
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# elif BYTE_ORDER == BIG_ENDIAN
+# define _BIG_ENDIAN
+# elif BYTE_ORDER == PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# define sched_yield() pthread_yield()
+# define SLEEP_TIMESPEC(timespec) nsleep(&timespec, 0)
+# define LIBPATH "LIBPATH"
+# define NO_PTHREAD_SEMAPHORES
+# define NO_DL_FUNCTIONS
+#endif
+
+#ifdef HPUX
+# define AF_IPX -1
+# undef howmany
+# undef MAXINT
+# include <pthread.h>
+# include <sys/un.h>
+# include <sys/sched.h>
+# include <sys/xti.h>
+# include <sys/pstat.h>
+# include <shadow.h>
+# include <crypt.h>
+# include <machine/param.h>
+# define LIBPATH "SHLIB_PATH"
+# define PTR_FD_SET(s) ((int *)&(s))
+# define PTHREAD_VALUE(t) ((t).field2)
+# define PTHREAD_NONE_INIT { 0, -1 }
+# define PTHREAD_ATTR_DEFAULT pthread_attr_default
+# define PTHREAD_MUTEXATTR_DEFAULT pthread_mutexattr_default
+# define PTHREAD_CONDATTR_DEFAULT pthread_condattr_default
+# define pthread_detach(t) pthread_detach(&(t))
+# define NO_PTHREAD_PRIORITY
+# define NO_PTHREAD_SEMAPHORES
+# define NO_DL_FUNCTIONS
+# undef sigaction
+# define PTHREAD_SIGACTION cma_sigaction
+#endif
+
+#ifdef SOLARIS
+# include <shadow.h>
+# include <sys/un.h>
+# include <stropts.h>
+# include <pthread.h>
+# include <semaphore.h>
+# include <netinet/tcp.h>
+# include <sys/filio.h>
+# include <dlfcn.h>
+# include <sys/isa_defs.h>
+# define IORESOURCE_TRANSFER_SYSV
+# define IOCHANNEL_TRANSFER_BSD
+# define LIBPATH "LD_LIBRARY_PATH"
+#endif
+
+#ifdef MACOSX
+#define __OPENTRANSPORTPROVIDERS__ // these are already defined
+#define TimeValue CFTimeValue // Do not conflict with TimeValue in sal/inc/osl/time.h
+#include <Carbon/Carbon.h>
+#undef TimeValue
+# ifndef ETIME
+# define ETIME ETIMEDOUT
+# endif
+# include <dlfcn.h>
+# include <pthread.h>
+# include <sys/file.h>
+# include <sys/ioctl.h>
+# include <sys/uio.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+# include <machine/endian.h>
+# include <sys/time.h>
+# include <sys/semaphore.h>
+/* fixme are premac and postmac still needed here? */
+# include <premac.h>
+# include <mach-o/dyld.h>
+# include <postmac.h>
+# if BYTE_ORDER == LITTLE_ENDIAN
+# ifndef _LITTLE_ENDIAN
+# define _LITTLE_ENDIAN
+# endif
+# elif BYTE_ORDER == BIG_ENDIAN
+# ifndef _BIG_ENDIAN
+# define _BIG_ENDIAN
+# endif
+# elif BYTE_ORDER == PDP_ENDIAN
+# ifndef _PDP_ENDIAN
+# define _PDP_ENDIAN
+# endif
+# endif
+# define IOCHANNEL_TRANSFER_BSD_RENO
+# define NO_PTHREAD_RTL
+/* for NSGetArgc/Argv/Environ */
+# include <crt_externs.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+int macxp_resolveAlias(char *path, int buflen);
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#if !defined(_WIN32) && !defined(_WIN16) && !defined(OS2) && \
+ !defined(LINUX) && !defined(NETBSD) && !defined(FREEBSD) && !defined(SCO) && \
+ !defined(AIX) && !defined(HPUX) && \
+ !defined(SOLARIS) && !defined(MACOSX)
+# error "Target platform not specified!"
+#endif
+
+#if defined(NETBSD)
+#if defined _LITTLE_ENDIAN_OO
+# define _OSL_BIGENDIAN
+#elif defined _BIG_ENDIAN_OO
+# define _OSL_LITENDIAN
+#else
+# error undetermined endianess
+#endif
+#else
+#if defined _LITTLE_ENDIAN
+# define _OSL_BIGENDIAN
+#elif defined _BIG_ENDIAN
+# define _OSL_LITENDIAN
+#else
+# error undetermined endianess
+#endif
+#endif
+
+#ifndef PTR_FD_SET
+# define PTR_FD_SET(s) (&(s))
+#endif
+
+#ifndef NORMALIZE_TIMESPEC
+# define NORMALIZE_TIMESPEC(timespec) \
+ timespec . tv_sec += timespec . tv_nsec / 1000000000; \
+ timespec . tv_nsec %= 1000000000;
+#endif
+
+#ifndef SET_TIMESPEC
+# define SET_TIMESPEC(timespec, sec, nsec) \
+ timespec . tv_sec = (sec); \
+ timespec . tv_nsec = (nsec); \
+ NORMALIZE_TIMESPEC(timespec);
+#endif
+
+#ifndef SLEEP_TIMESPEC
+# define SLEEP_TIMESPEC(timespec) nanosleep(&timespec, 0)
+#endif
+
+#ifndef INIT_GROUPS
+# define INIT_GROUPS(name, gid) ((setgid((gid)) == 0) && (initgroups((name), (gid)) == 0))
+#endif
+
+#ifndef PTHREAD_VALUE
+# define PTHREAD_VALUE(t) (t)
+#endif
+#ifndef PTHREAD_NONE
+# if (__GNUC__ < 4) && !defined(MACOSX)
+extern pthread_t _pthread_none_;
+# endif
+# define PTHREAD_NONE _pthread_none_
+# ifndef PTHREAD_NONE_INIT
+# define PTHREAD_NONE_INIT ((pthread_t)-1)
+# endif
+#endif
+
+#ifndef PTHREAD_ATTR_DEFAULT
+# define PTHREAD_ATTR_DEFAULT NULL
+#endif
+#ifndef PTHREAD_MUTEXATTR_DEFAULT
+# define PTHREAD_MUTEXATTR_DEFAULT NULL
+#endif
+#ifndef PTHREAD_CONDATTR_DEFAULT
+# define PTHREAD_CONDATTR_DEFAULT NULL
+#endif
+
+#ifndef PTHREAD_SIGACTION
+# define PTHREAD_SIGACTION sigaction
+#endif
+
+#ifndef STAT_PARENT
+# define STAT_PARENT lstat
+#endif
+
+/* socket options which might not be defined on all unx flavors */
+#ifndef SO_ACCEPTCONN
+# define SO_ACCEPTCONN 0
+#endif
+#ifndef SO_SNDLOWAT
+# define SO_SNDLOWAT 0
+#endif
+#ifndef SO_RCVLOWAT
+# define SO_RCVLOWAT 0
+#endif
+#ifndef SO_SNDTIMEO
+# define SO_SNDTIMEO 0
+#endif
+#ifndef SO_RCVTIMEO
+# define SO_RCVTIMEO 0
+#endif
+#ifndef SO_USELOOPBACK
+# define SO_USELOOPBACK 0
+#endif
+#ifndef MSG_MAXIOVLEN
+# define MSG_MAXIOVLEN 0
+#endif
+
+/* BEGIN HACK */
+/* dummy define and declarations for IPX should be replaced by */
+/* original ipx headers when these are available for this platform */
+
+#ifndef SA_FAMILY_DECL
+# define SA_FAMILY_DECL short sa_family
+#endif
+
+typedef struct sockaddr_ipx {
+ SA_FAMILY_DECL;
+ char sa_netnum[4];
+ char sa_nodenum[6];
+ unsigned short sa_socket;
+} SOCKADDR_IPX;
+
+#define NSPROTO_IPX 1000
+#define NSPROTO_SPX 1256
+#define NSPROTO_SPXII 1257
+
+/* END HACK */
+
+#ifdef NO_PTHREAD_SEMAPHORES
+
+typedef struct
+{
+ pthread_mutex_t mutex;
+ pthread_cond_t increased;
+ int value;
+} sem_t;
+extern int sem_init(sem_t* sem, int pshared, unsigned int value);
+extern int sem_destroy(sem_t* sem);
+extern int sem_wait(sem_t* sem);
+extern int sem_trywait(sem_t* sem);
+extern int sem_post(sem_t* sem);
+
+#endif
+
+#ifdef NO_PTHREAD_RTL
+#if !defined FREEBSD || (__FreeBSD_version < 500112)
+struct passwd *getpwent_r(struct passwd *pwd, char *buffer, int buflen);
+extern struct spwd *getspnam_r(const char *name, struct spwd *result,
+ char *buffer, int buflen);
+
+struct tm *localtime_r(const time_t *timep, struct tm *buffer);
+struct tm *gmtime_r(const time_t *timep, struct tm *buffer);
+#endif /* !defined FREEBSD || (__FreeBSD_version < 500112) */
+#if !defined(FREEBSD) || (__FreeBSD_version < 601103)
+struct hostent *gethostbyname_r(const char *name, struct hostent *result,
+ char *buffer, int buflen, int *h_errnop);
+#endif /* !defined(FREEBSD) || (__FreeBSD_version < 601103) */
+#endif
+
+#endif /* __OSL_SYSTEM_H__ */
+
diff --git a/sal/osl/unx/tempfile.c b/sal/osl/unx/tempfile.c
new file mode 100644
index 000000000000..e10fffaa5ce2
--- /dev/null
+++ b/sal/osl/unx/tempfile.c
@@ -0,0 +1,370 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*****************************************************************/
+/* Includes */
+/*****************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "system.h"
+#include <osl/file.h>
+#include <osl/thread.h>
+#include <rtl/ustrbuf.h>
+#include <osl/diagnose.h>
+
+#ifndef _FILE_URL_H_
+#include "file_url.h"
+#endif
+
+/*****************************************************************/
+/* osl_getTempFirURL */
+/*****************************************************************/
+
+oslFileError SAL_CALL osl_getTempDirURL( rtl_uString** pustrTempDir )
+{
+#ifdef MACOSX
+ const char *pValue = getenv( "TMPDIR" );
+
+ /* If TMPDIR environment variable is not set, use "/tmp" instead
+ of P_tmpdir because its value is "/var/tmp" and it is not
+ deleted on system start up */
+ if ( !pValue )
+ pValue = "/tmp";
+#else
+
+ const char *pValue = getenv( "TEMP" );
+
+ if ( !pValue )
+ {
+ pValue = getenv( "TMP" );
+#if defined(SOLARIS) || defined (LINUX) || defined (FREEBSD)
+ if ( !pValue )
+ pValue = P_tmpdir;
+#endif
+ }
+#endif /* MACOSX */
+
+ if ( pValue )
+ {
+ oslFileError error;
+ rtl_uString *ustrTempPath = NULL;
+
+ rtl_string2UString( &ustrTempPath, pValue, strlen( pValue ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(ustrTempPath != NULL);
+ error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
+ rtl_uString_release( ustrTempPath );
+
+ return error;
+ }
+ else
+ return osl_File_E_NOENT;
+}
+
+/******************************************************************
+ * Generates a random unique file name. We're using the scheme
+ * from the standard c-lib function mkstemp to generate a more
+ * or less random unique file name
+ *
+ * @param rand_name
+ * receives the random name
+ ******************************************************************/
+
+static const char LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+static const int COUNT_OF_LETTERS = sizeof(LETTERS)/sizeof(LETTERS[0]) - 1;
+
+#define RAND_NAME_LENGTH 6
+
+static void osl_gen_random_name_impl_(rtl_uString** rand_name)
+{
+ static uint64_t value;
+
+ char buffer[RAND_NAME_LENGTH];
+ struct timeval tv;
+ uint64_t v;
+ int i;
+
+ gettimeofday(&tv, NULL);
+
+ value += ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
+
+ v = value;
+
+ for (i = 0; i < RAND_NAME_LENGTH; i++)
+ {
+ buffer[i] = LETTERS[v % COUNT_OF_LETTERS];
+ v /= COUNT_OF_LETTERS;
+ }
+
+ rtl_string2UString(
+ rand_name,
+ buffer,
+ RAND_NAME_LENGTH,
+ RTL_TEXTENCODING_ASCII_US,
+ OSTRING_TO_OUSTRING_CVTFLAGS);
+ OSL_ASSERT(*rand_name != NULL);
+}
+
+/*****************************************************************
+ * Helper function
+ * Either use the directory provided or the result of
+ * osl_getTempDirUrl and return it as system path and file url
+ ****************************************************************/
+
+static oslFileError osl_setup_base_directory_impl_(
+ rtl_uString* pustrDirectoryURL,
+ rtl_uString** ppustr_base_dir)
+{
+ rtl_uString* dir_url = 0;
+ rtl_uString* dir = 0;
+ oslFileError error = osl_File_E_None;
+
+ if (pustrDirectoryURL)
+ rtl_uString_assign(&dir_url, pustrDirectoryURL);
+ else
+ error = osl_getTempDirURL(&dir_url);
+
+ if (osl_File_E_None == error)
+ {
+ error = osl_getSystemPathFromFileURL_Ex(dir_url, &dir, FURL_DENY_RELATIVE);
+ rtl_uString_release(dir_url);
+ }
+
+ if (osl_File_E_None == error)
+ {
+ rtl_uString_assign(ppustr_base_dir, dir);
+ rtl_uString_release(dir);
+ }
+
+ return error;
+}
+
+/*****************************************************************
+ * osl_setup_createTempFile_impl
+ * validate input parameter, setup variables
+ ****************************************************************/
+
+ static oslFileError osl_setup_createTempFile_impl_(
+ rtl_uString* pustrDirectoryURL,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL,
+ rtl_uString** ppustr_base_dir,
+ sal_Bool* b_delete_on_close)
+ {
+ oslFileError osl_error;
+
+ OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
+
+ if ((0 == pHandle) && (0 == ppustrTempFileURL))
+ {
+ osl_error = osl_File_E_INVAL;
+ }
+ else
+ {
+ osl_error = osl_setup_base_directory_impl_(
+ pustrDirectoryURL, ppustr_base_dir);
+
+ *b_delete_on_close = (0 == ppustrTempFileURL);
+ }
+
+ return osl_error;
+ }
+
+/*****************************************************************
+ * Create a unique file in the specified directory and return
+ * it's name
+ ****************************************************************/
+
+static oslFileError osl_create_temp_file_impl_(
+ const rtl_uString* pustr_base_directory,
+ oslFileHandle* file_handle,
+ rtl_uString** ppustr_temp_file_name)
+{
+ rtl_uString* rand_name = 0;
+ sal_uInt32 len_base_dir = 0;
+ rtl_uString* tmp_file_path = 0;
+ rtl_uString* tmp_file_url = 0;
+ sal_Int32 capacity = 0;
+ oslFileError osl_error = osl_File_E_None;
+ sal_Int32 offset_file_name;
+ const sal_Unicode* puchr;
+
+ OSL_PRECOND(pustr_base_directory, "Invalid Parameter");
+ OSL_PRECOND(file_handle, "Invalid Parameter");
+ OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter");
+
+ len_base_dir = rtl_uString_getLength(pustr_base_directory);
+
+ rtl_uStringbuffer_newFromStr_WithLength(
+ &tmp_file_path,
+ rtl_uString_getStr((rtl_uString*)pustr_base_directory),
+ len_base_dir);
+
+ rtl_uStringbuffer_ensureCapacity(
+ &tmp_file_path,
+ &capacity,
+ (len_base_dir + 1 + RAND_NAME_LENGTH));
+
+ offset_file_name = len_base_dir;
+
+ puchr = rtl_uString_getStr(tmp_file_path);
+
+ /* ensure that the last character is a '/' */
+
+ if ((sal_Unicode)'/' != puchr[len_base_dir - 1])
+ {
+ rtl_uStringbuffer_insert_ascii(
+ &tmp_file_path,
+ &capacity,
+ len_base_dir,
+ "/",
+ 1);
+
+ offset_file_name++;
+ }
+
+ while(1) /* try until success */
+ {
+ osl_gen_random_name_impl_(&rand_name);
+
+ rtl_uStringbuffer_insert(
+ &tmp_file_path,
+ &capacity,
+ offset_file_name,
+ rtl_uString_getStr(rand_name),
+ rtl_uString_getLength(rand_name));
+
+ osl_error = osl_getFileURLFromSystemPath(
+ tmp_file_path, &tmp_file_url);
+
+ if (osl_File_E_None == osl_error)
+ {
+ /* RW permission for the user only! */
+ mode_t old_mode = umask(077);
+
+ osl_error = osl_openFile(
+ tmp_file_url,
+ file_handle,
+ osl_File_OpenFlag_Read |
+ osl_File_OpenFlag_Write |
+ osl_File_OpenFlag_Create);
+
+ umask(old_mode);
+ }
+
+ /* in case of error osl_File_E_EXIST we simply try again else we give up */
+
+ if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST))
+ {
+ if (rand_name)
+ rtl_uString_release(rand_name);
+
+ if (tmp_file_url)
+ rtl_uString_release(tmp_file_url);
+
+ break;
+ }
+ } /* while(1) */
+
+ if (osl_File_E_None == osl_error)
+ rtl_uString_assign(ppustr_temp_file_name, tmp_file_path);
+
+ if (tmp_file_path)
+ rtl_uString_release(tmp_file_path);
+
+ return osl_error;
+}
+
+/*****************************************************************
+ * osl_createTempFile
+ *****************************************************************/
+
+oslFileError SAL_CALL osl_createTempFile(
+ rtl_uString* pustrDirectoryURL,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL)
+{
+ rtl_uString* base_directory = 0;
+ rtl_uString* temp_file_name = 0;
+ oslFileHandle temp_file_handle;
+ sal_Bool b_delete_on_close;
+ oslFileError osl_error;
+
+ osl_error = osl_setup_createTempFile_impl_(
+ pustrDirectoryURL,
+ pHandle,
+ ppustrTempFileURL,
+ &base_directory,
+ &b_delete_on_close);
+
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+
+ osl_error = osl_create_temp_file_impl_(
+ base_directory, &temp_file_handle, &temp_file_name);
+
+ if (osl_File_E_None == osl_error)
+ {
+ rtl_uString* temp_file_url = 0;
+
+ /* assuming this works */
+ osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url);
+
+ if (b_delete_on_close)
+ {
+ osl_error = osl_removeFile(temp_file_url);
+
+ if (osl_File_E_None == osl_error)
+ *pHandle = temp_file_handle;
+ else
+ osl_closeFile(temp_file_handle);
+ }
+ else
+ {
+ if (pHandle)
+ *pHandle = temp_file_handle;
+ else
+ osl_closeFile(temp_file_handle);
+
+ rtl_uString_assign(ppustrTempFileURL, temp_file_url);
+ }
+
+ if (temp_file_url)
+ rtl_uString_release(temp_file_url);
+
+ if (temp_file_name)
+ rtl_uString_release(temp_file_name);
+ }
+
+ if (base_directory)
+ rtl_uString_release(base_directory);
+
+ return osl_error;
+}
diff --git a/sal/osl/unx/thread.c b/sal/osl/unx/thread.c
new file mode 100644
index 000000000000..fe53915b792f
--- /dev/null
+++ b/sal/osl/unx/thread.c
@@ -0,0 +1,1035 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+#include <string.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/nlsupport.h>
+#ifndef _RTL_TEXTENC_H_
+#include <rtl/textenc.h>
+#endif
+
+/****************************************************************************
+ * @@@ TODO @@@
+ *
+ * (1) 'osl_thread_priority_init_Impl()'
+ * - insane assumption that initializing caller is main thread
+ * - use _POSIX_THREAD_PRIORITY_SCHEDULING, not NO_PTHREAD_PRIORITY (?)
+ * - POSIX doesn't require defined prio's for SCHED_OTHER (!)
+ * - use SCHED_RR instead of SCHED_OTHER for defined behaviour (?)
+ * (2) 'oslThreadIdentifier' and '{insert|remove|lookup}ThreadId()'
+ * - cannot reliably be applied to 'alien' threads;
+ * - memory leak for 'alien' thread 'HashEntry's;
+ * - use 'PTHREAD_VALUE(pthread_t)' as identifier instead (?)
+ * - if yes, change 'oslThreadIdentifier' to 'intptr_t' or similar
+ * (3) 'oslSigAlarmHandler()' (#71232#)
+ * - [Under Solaris we get SIGALRM in e.g. pthread_join which terminates
+ * the process. So we initialize our signal handling module and do
+ * register a SIGALRM Handler which catches and ignores it]
+ * - should this still happen, 'signal.c' needs to be fixed instead.
+ *
+ ****************************************************************************/
+
+/*****************************************************************************/
+/* Internal data structures and functions */
+/*****************************************************************************/
+
+#define THREADIMPL_FLAGS_TERMINATE 0x00001
+#define THREADIMPL_FLAGS_STARTUP 0x00002
+#define THREADIMPL_FLAGS_SUSPENDED 0x00004
+#define THREADIMPL_FLAGS_ACTIVE 0x00008
+#define THREADIMPL_FLAGS_ATTACHED 0x00010
+#define THREADIMPL_FLAGS_DESTROYED 0x00020
+
+typedef struct osl_thread_impl_st
+{
+ pthread_t m_hThread;
+ sal_uInt16 m_Ident; /* @@@ see TODO @@@ */
+ short m_Flags;
+ oslWorkerFunction m_WorkerFunction;
+ void* m_pData;
+ pthread_mutex_t m_Lock;
+ pthread_cond_t m_Cond;
+} Thread_Impl;
+
+struct osl_thread_priority_st
+{
+ int m_Highest;
+ int m_Above_Normal;
+ int m_Normal;
+ int m_Below_Normal;
+ int m_Lowest;
+};
+
+#define OSL_THREAD_PRIORITY_INITIALIZER { 127, 96, 64, 32, 0 }
+static void osl_thread_priority_init_Impl (void);
+
+struct osl_thread_textencoding_st
+{
+ pthread_key_t m_key; /* key to store thread local text encoding */
+ rtl_TextEncoding m_default; /* the default text encoding */
+};
+
+#define OSL_THREAD_TEXTENCODING_INITIALIZER { 0, RTL_TEXTENCODING_DONTKNOW }
+static void osl_thread_textencoding_init_Impl (void);
+
+struct osl_thread_global_st
+{
+ pthread_once_t m_once;
+ struct osl_thread_priority_st m_priority;
+ struct osl_thread_textencoding_st m_textencoding;
+};
+
+static struct osl_thread_global_st g_thread =
+{
+ PTHREAD_ONCE_INIT,
+ OSL_THREAD_PRIORITY_INITIALIZER,
+ OSL_THREAD_TEXTENCODING_INITIALIZER
+};
+
+static void osl_thread_init_Impl (void);
+
+static Thread_Impl* osl_thread_construct_Impl (void);
+static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl);
+
+static void* osl_thread_start_Impl (void * pData);
+static void osl_thread_cleanup_Impl (void * pData);
+
+static oslThread osl_thread_create_Impl (
+ oslWorkerFunction pWorker, void * pThreadData, short nFlags);
+
+static void osl_thread_join_cleanup_Impl (void * opaque);
+static void osl_thread_wait_cleanup_Impl (void * opaque);
+
+/* @@@ see TODO @@@ */
+static sal_uInt16 insertThreadId (pthread_t hThread);
+static sal_uInt16 lookupThreadId (pthread_t hThread);
+static void removeThreadId (pthread_t hThread);
+
+/*****************************************************************************/
+/* osl_thread_init_Impl */
+/*****************************************************************************/
+static void osl_thread_init_Impl (void)
+{
+ osl_thread_priority_init_Impl();
+ osl_thread_textencoding_init_Impl();
+}
+
+/*****************************************************************************/
+/* osl_thread_join_cleanup_Impl */
+/*****************************************************************************/
+static void osl_thread_join_cleanup_Impl (void * opaque)
+{
+ pthread_t hThread = (pthread_t)(opaque);
+ pthread_detach (hThread);
+}
+
+/*****************************************************************************/
+/* osl_thread_wait_cleanup_Impl */
+/*****************************************************************************/
+static void osl_thread_wait_cleanup_Impl (void * opaque)
+{
+ pthread_mutex_t * pMutex = (pthread_mutex_t*)(opaque);
+ pthread_mutex_unlock (pMutex);
+}
+
+/*****************************************************************************/
+/* osl_thread_construct_Impl */
+/*****************************************************************************/
+Thread_Impl* osl_thread_construct_Impl (void)
+{
+ Thread_Impl* pImpl = malloc (sizeof(Thread_Impl));
+ if (pImpl)
+ {
+ memset (pImpl, 0, sizeof(Thread_Impl));
+
+ pthread_mutex_init (&(pImpl->m_Lock), PTHREAD_MUTEXATTR_DEFAULT);
+ pthread_cond_init (&(pImpl->m_Cond), PTHREAD_CONDATTR_DEFAULT);
+ }
+ return (pImpl);
+}
+
+/*****************************************************************************/
+/* osl_thread_destruct_Impl */
+/*****************************************************************************/
+static void osl_thread_destruct_Impl (Thread_Impl ** ppImpl)
+{
+ OSL_ASSERT(ppImpl);
+ if (*ppImpl)
+ {
+ pthread_cond_destroy (&((*ppImpl)->m_Cond));
+ pthread_mutex_destroy (&((*ppImpl)->m_Lock));
+
+ free (*ppImpl);
+ (*ppImpl) = 0;
+ }
+}
+
+/*****************************************************************************/
+/* osl_thread_cleanup_Impl */
+/*****************************************************************************/
+static void osl_thread_cleanup_Impl (void* pData)
+{
+ pthread_t thread;
+ int attached;
+ int destroyed;
+ Thread_Impl* pImpl= (Thread_Impl*)pData;
+
+ pthread_mutex_lock (&(pImpl->m_Lock));
+
+ thread = pImpl->m_hThread;
+ attached = (pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) != 0;
+ destroyed = (pImpl->m_Flags & THREADIMPL_FLAGS_DESTROYED) != 0;
+ pImpl->m_Flags &= ~(THREADIMPL_FLAGS_ACTIVE | THREADIMPL_FLAGS_ATTACHED);
+
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+
+ /* release oslThreadIdentifier @@@ see TODO @@@ */
+ removeThreadId (thread);
+
+ if (attached)
+ {
+ pthread_detach (thread);
+ }
+
+ if (destroyed)
+ {
+ osl_thread_destruct_Impl (&pImpl);
+ }
+}
+
+/*****************************************************************************/
+/* osl_thread_start_Impl */
+/*****************************************************************************/
+static void* osl_thread_start_Impl (void* pData)
+{
+ int terminate;
+ Thread_Impl* pImpl= (Thread_Impl*)pData;
+
+ OSL_ASSERT(pImpl);
+
+ pthread_mutex_lock (&(pImpl->m_Lock));
+
+ /* install cleanup handler */
+ pthread_cleanup_push (osl_thread_cleanup_Impl, pData);
+
+ /* request oslThreadIdentifier @@@ see TODO @@@ */
+ pImpl->m_Ident = insertThreadId (pImpl->m_hThread);
+
+ /* signal change from STARTUP to ACTIVE state */
+ pImpl->m_Flags &= ~THREADIMPL_FLAGS_STARTUP;
+ pImpl->m_Flags |= THREADIMPL_FLAGS_ACTIVE;
+ pthread_cond_signal (&(pImpl->m_Cond));
+
+ /* Check if thread is started in SUSPENDED state */
+ while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
+ {
+ /* wait until SUSPENDED flag is cleared */
+ pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
+ pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
+ pthread_cleanup_pop (0);
+ }
+
+ /* check for SUSPENDED to TERMINATE state change */
+ terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
+
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+
+ if (!terminate)
+ {
+ /* call worker function */
+ pImpl->m_WorkerFunction(pImpl->m_pData);
+ }
+
+ /* call cleanup handler and leave */
+ pthread_cleanup_pop (1);
+ return (0);
+}
+
+/*****************************************************************************/
+/* osl_thread_create_Impl */
+/*****************************************************************************/
+static oslThread osl_thread_create_Impl (
+ oslWorkerFunction pWorker,
+ void* pThreadData,
+ short nFlags)
+{
+ Thread_Impl* pImpl;
+ int nRet=0;
+
+ pImpl = osl_thread_construct_Impl();
+ if (!pImpl)
+ return (0); /* ENOMEM */
+
+ pImpl->m_WorkerFunction = pWorker;
+ pImpl->m_pData = pThreadData;
+ pImpl->m_Flags = nFlags | THREADIMPL_FLAGS_STARTUP;
+
+ pthread_mutex_lock (&(pImpl->m_Lock));
+
+ if ((nRet = pthread_create (
+ &(pImpl->m_hThread),
+ PTHREAD_ATTR_DEFAULT,
+ osl_thread_start_Impl,
+ (void*)(pImpl))) != 0)
+ {
+ OSL_TRACE("osl_thread_create_Impl(): errno: %d, %s\n",
+ nRet, strerror(nRet));
+
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+ osl_thread_destruct_Impl (&pImpl);
+
+ return (0);
+ }
+
+ /* wait for change from STARTUP to ACTIVE state */
+ while (pImpl->m_Flags & THREADIMPL_FLAGS_STARTUP)
+ {
+ /* wait until STARTUP flag is cleared */
+ pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
+ pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
+ pthread_cleanup_pop (0);
+ }
+
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+
+ return ((oslThread)(pImpl));
+}
+
+/*****************************************************************************/
+/* osl_createThread */
+/*****************************************************************************/
+oslThread osl_createThread (
+ oslWorkerFunction pWorker,
+ void * pThreadData)
+{
+ return osl_thread_create_Impl (
+ pWorker,
+ pThreadData,
+ THREADIMPL_FLAGS_ATTACHED);
+}
+
+/*****************************************************************************/
+/* osl_createSuspendedThread */
+/*****************************************************************************/
+oslThread osl_createSuspendedThread (
+ oslWorkerFunction pWorker,
+ void * pThreadData)
+{
+ return osl_thread_create_Impl (
+ pWorker,
+ pThreadData,
+ THREADIMPL_FLAGS_ATTACHED |
+ THREADIMPL_FLAGS_SUSPENDED );
+}
+
+/*****************************************************************************/
+/* osl_destroyThread */
+/*****************************************************************************/
+void SAL_CALL osl_destroyThread(oslThread Thread)
+{
+ if (Thread != NULL) {
+ Thread_Impl * impl = (Thread_Impl *) Thread;
+ int active;
+ pthread_mutex_lock(&impl->m_Lock);
+ active = (impl->m_Flags & THREADIMPL_FLAGS_ACTIVE) != 0;
+ impl->m_Flags |= THREADIMPL_FLAGS_DESTROYED;
+ pthread_mutex_unlock(&impl->m_Lock);
+ if (!active) {
+ osl_thread_destruct_Impl(&impl);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* osl_resumeThread */
+/*****************************************************************************/
+void SAL_CALL osl_resumeThread(oslThread Thread)
+{
+ Thread_Impl* pImpl= (Thread_Impl*)Thread;
+
+ OSL_ASSERT(pImpl);
+ if (!pImpl)
+ return; /* EINVAL */
+
+ pthread_mutex_lock (&(pImpl->m_Lock));
+
+ if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
+ {
+ /* clear SUSPENDED flag */
+ pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
+ pthread_cond_signal (&(pImpl->m_Cond));
+ }
+
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+}
+
+/*****************************************************************************/
+/* osl_suspendThread */
+/*****************************************************************************/
+void SAL_CALL osl_suspendThread(oslThread Thread)
+{
+ Thread_Impl* pImpl= (Thread_Impl*)Thread;
+
+ OSL_ASSERT(pImpl);
+ if (!pImpl)
+ return; /* EINVAL */
+
+ pthread_mutex_lock (&(pImpl->m_Lock));
+
+ pImpl->m_Flags |= THREADIMPL_FLAGS_SUSPENDED;
+
+ if (pthread_equal (pthread_self(), pImpl->m_hThread))
+ {
+ /* self suspend */
+ while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
+ {
+ /* wait until SUSPENDED flag is cleared */
+ pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
+ pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
+ pthread_cleanup_pop (0);
+ }
+ }
+
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+}
+
+/*****************************************************************************/
+/* osl_isThreadRunning */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
+{
+ sal_Bool active;
+ Thread_Impl* pImpl= (Thread_Impl*)Thread;
+
+ if (!pImpl)
+ return sal_False;
+
+ pthread_mutex_lock (&(pImpl->m_Lock));
+ active = ((pImpl->m_Flags & THREADIMPL_FLAGS_ACTIVE) > 0);
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+
+ return (active);
+}
+
+/*****************************************************************************/
+/* osl_joinWithThread */
+/*****************************************************************************/
+void SAL_CALL osl_joinWithThread(oslThread Thread)
+{
+ pthread_t thread;
+ int attached;
+ Thread_Impl* pImpl= (Thread_Impl*)Thread;
+
+ if (!pImpl)
+ return;
+
+ pthread_mutex_lock (&(pImpl->m_Lock));
+
+ if (pthread_equal (pthread_self(), pImpl->m_hThread))
+ {
+ /* self join */
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+ return; /* EDEADLK */
+ }
+
+ thread = pImpl->m_hThread;
+ attached = ((pImpl->m_Flags & THREADIMPL_FLAGS_ATTACHED) > 0);
+ pImpl->m_Flags &= ~THREADIMPL_FLAGS_ATTACHED;
+
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+
+ if (attached)
+ {
+ /* install cleanup handler to ensure consistent flags and state */
+ pthread_cleanup_push (
+ osl_thread_join_cleanup_Impl, (void*)thread);
+
+ /* join */
+ pthread_join (thread, NULL);
+
+ /* remove cleanup handler */
+ pthread_cleanup_pop (0);
+ }
+}
+
+/*****************************************************************************/
+/* osl_terminateThread */
+/*****************************************************************************/
+void SAL_CALL osl_terminateThread(oslThread Thread)
+{
+ Thread_Impl* pImpl= (Thread_Impl*)Thread;
+
+ OSL_ASSERT(pImpl);
+ if (!pImpl)
+ return; /* EINVAL */
+
+ pthread_mutex_lock (&(pImpl->m_Lock));
+
+ if (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
+ {
+ /* clear SUSPENDED flag */
+ pImpl->m_Flags &= ~THREADIMPL_FLAGS_SUSPENDED;
+ pthread_cond_signal (&(pImpl->m_Cond));
+ }
+
+ pImpl->m_Flags |= THREADIMPL_FLAGS_TERMINATE;
+
+ pthread_mutex_unlock (&(pImpl->m_Lock));
+}
+
+/*****************************************************************************/
+/* osl_scheduleThread */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
+{
+ int terminate;
+ Thread_Impl* pImpl= (Thread_Impl*)Thread;
+
+ OSL_ASSERT(pImpl);
+ if (!pImpl)
+ return sal_False; /* EINVAL */
+
+ OSL_ASSERT(pthread_equal (pthread_self(), pImpl->m_hThread));
+ if (!(pthread_equal (pthread_self(), pImpl->m_hThread)))
+ return sal_False; /* EINVAL */
+
+ pthread_testcancel();
+ pthread_mutex_lock (&(pImpl->m_Lock));
+
+ while (pImpl->m_Flags & THREADIMPL_FLAGS_SUSPENDED)
+ {
+ /* wait until SUSPENDED flag is cleared */
+ pthread_cleanup_push (osl_thread_wait_cleanup_Impl, &(pImpl->m_Lock));
+ pthread_cond_wait (&(pImpl->m_Cond), &(pImpl->m_Lock));
+ pthread_cleanup_pop (0);
+ }
+
+ terminate = ((pImpl->m_Flags & THREADIMPL_FLAGS_TERMINATE) > 0);
+
+ pthread_mutex_unlock(&(pImpl->m_Lock));
+ pthread_testcancel();
+
+ return (terminate == 0);
+}
+
+/*****************************************************************************/
+/* osl_waitThread */
+/*****************************************************************************/
+void SAL_CALL osl_waitThread(const TimeValue* pDelay)
+{
+ if (pDelay)
+ {
+ struct timespec delay;
+
+ SET_TIMESPEC(delay, pDelay->Seconds, pDelay->Nanosec);
+
+ SLEEP_TIMESPEC(delay);
+ }
+}
+
+/*****************************************************************************/
+/* osl_yieldThread */
+/*
+ Note that POSIX scheduling _really_ requires threads to call this
+ functions, since a thread only reschedules to other thread, when
+ it blocks (sleep, blocking I/O) OR calls sched_yield().
+*/
+/*****************************************************************************/
+void SAL_CALL osl_yieldThread()
+{
+ sched_yield();
+}
+
+/*****************************************************************************/
+/* osl_getThreadIdentifier @@@ see TODO @@@ */
+/*****************************************************************************/
+
+#define HASHID(x) ((unsigned int)PTHREAD_VALUE(x) % HashSize)
+
+typedef struct _HashEntry
+{
+ pthread_t Handle;
+ sal_uInt16 Ident;
+ struct _HashEntry *Next;
+} HashEntry;
+
+static HashEntry* HashTable[31];
+static int HashSize = sizeof(HashTable) / sizeof(HashTable[0]);
+
+static pthread_mutex_t HashLock = PTHREAD_MUTEX_INITIALIZER;
+
+static sal_uInt16 LastIdent = 0;
+
+static sal_uInt16 lookupThreadId (pthread_t hThread)
+{
+ HashEntry *pEntry;
+
+ pthread_mutex_lock(&HashLock);
+
+ pEntry = HashTable[HASHID(hThread)];
+ while (pEntry != NULL)
+ {
+ if (pthread_equal(pEntry->Handle, hThread))
+ {
+ pthread_mutex_unlock(&HashLock);
+ return (pEntry->Ident);
+ }
+ pEntry = pEntry->Next;
+ }
+
+ pthread_mutex_unlock(&HashLock);
+
+ return (0);
+}
+
+static sal_uInt16 insertThreadId (pthread_t hThread)
+{
+ HashEntry *pEntry, *pInsert = NULL;
+
+ pthread_mutex_lock(&HashLock);
+
+ pEntry = HashTable[HASHID(hThread)];
+
+ while (pEntry != NULL)
+ {
+ if (pthread_equal(pEntry->Handle, hThread))
+ break;
+
+ pInsert = pEntry;
+ pEntry = pEntry->Next;
+ }
+
+ if (pEntry == NULL)
+ {
+ pEntry = (HashEntry*) calloc(sizeof(HashEntry), 1);
+
+ pEntry->Handle = hThread;
+
+ ++ LastIdent;
+
+ if ( LastIdent == 0 )
+ LastIdent = 1;
+
+ pEntry->Ident = LastIdent;
+
+ if (pInsert)
+ pInsert->Next = pEntry;
+ else
+ HashTable[HASHID(hThread)] = pEntry;
+ }
+
+ pthread_mutex_unlock(&HashLock);
+
+ return (pEntry->Ident);
+}
+
+static void removeThreadId (pthread_t hThread)
+{
+ HashEntry *pEntry, *pRemove = NULL;
+
+ pthread_mutex_lock(&HashLock);
+
+ pEntry = HashTable[HASHID(hThread)];
+ while (pEntry != NULL)
+ {
+ if (pthread_equal(pEntry->Handle, hThread))
+ break;
+
+ pRemove = pEntry;
+ pEntry = pEntry->Next;
+ }
+
+ if (pEntry != NULL)
+ {
+ if (pRemove)
+ pRemove->Next = pEntry->Next;
+ else
+ HashTable[HASHID(hThread)] = pEntry->Next;
+
+ free(pEntry);
+ }
+
+ pthread_mutex_unlock(&HashLock);
+}
+
+oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
+{
+ Thread_Impl* pImpl= (Thread_Impl*)Thread;
+ sal_uInt16 Ident;
+
+ if (pImpl)
+ Ident = pImpl->m_Ident;
+ else
+ {
+ /* current thread */
+ pthread_t current = pthread_self();
+
+ Ident = lookupThreadId (current);
+ if (Ident == 0)
+ /* @@@ see TODO: alien pthread_self() @@@ */
+ Ident = insertThreadId (current);
+ }
+
+ return ((oslThreadIdentifier)(Ident));
+}
+
+/*****************************************************************************
+ @@@ see TODO @@@
+ osl_thread_priority_init_Impl
+
+ set the base-priority of the main-thread to
+ oslThreadPriorityNormal (64) since 0 (lowest) is
+ the system default. This behaviour collides with
+ our enum-priority definition (highest..normal..lowest).
+ A normaluser will expect the main-thread of an app.
+ to have the "normal" priority.
+
+*****************************************************************************/
+static void osl_thread_priority_init_Impl (void)
+{
+#ifndef NO_PTHREAD_PRIORITY
+ struct sched_param param;
+ int policy=0;
+ int nRet=0;
+
+/* @@@ see TODO: calling thread may not be main thread @@@ */
+
+ if ((nRet = pthread_getschedparam(pthread_self(), &policy, &param)) != 0)
+ {
+ OSL_TRACE("failed to get priority of thread [%s]\n",strerror(nRet));
+ return;
+ }
+
+#if defined (SOLARIS)
+ if ( policy >= _SCHED_NEXT)
+ {
+ /* mfe: pthread_getschedparam on Solaris has a possible Bug */
+ /* one gets 959917873 as the policy */
+ /* so set the policy to a default one */
+ policy=SCHED_OTHER;
+ }
+#endif /* SOLARIS */
+
+ if ((nRet = sched_get_priority_min(policy) ) != -1)
+ {
+ OSL_TRACE("Min Prioriy for policy '%i' == '%i'\n",policy,nRet);
+ g_thread.m_priority.m_Lowest=nRet;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ fprintf(stderr,"failed to get min sched param [%s]\n",strerror(errno));
+ }
+#endif /* OSL_DEBUG_LEVEL */
+
+ if ((nRet = sched_get_priority_max(policy) ) != -1)
+ {
+ OSL_TRACE("Max Prioriy for policy '%i' == '%i'\n",policy,nRet);
+ g_thread.m_priority.m_Highest=nRet;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ {
+ fprintf(stderr,"failed to get max sched param [%s]\n",strerror(errno));
+ }
+#endif /* OSL_DEBUG_LEVEL */
+
+ g_thread.m_priority.m_Normal =
+ (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Highest) / 2;
+ g_thread.m_priority.m_Below_Normal =
+ (g_thread.m_priority.m_Lowest + g_thread.m_priority.m_Normal) / 2;
+ g_thread.m_priority.m_Above_Normal =
+ (g_thread.m_priority.m_Normal + g_thread.m_priority.m_Highest) / 2;
+
+/* @@@ set prio of calling (not main) thread (?) @@@ */
+
+ param.sched_priority= g_thread.m_priority.m_Normal;
+
+ if ((nRet = pthread_setschedparam(pthread_self(), policy, &param)) != 0)
+ {
+ OSL_TRACE("failed to change base priority of thread [%s]\n",strerror(nRet));
+ OSL_TRACE("Thread ID '%i', Policy '%i', Priority '%i'\n",pthread_self(),policy,param.sched_priority);
+ }
+
+#endif /* NO_PTHREAD_PRIORITY */
+}
+
+/*****************************************************************************/
+/* osl_setThreadPriority */
+/*
+ Impl-Notes: contrary to solaris-docu, which claims
+ valid priority-levels from 0 .. INT_MAX, only the
+ range 0..127 is accepted. (0 lowest, 127 highest)
+*/
+/*****************************************************************************/
+void SAL_CALL osl_setThreadPriority (
+ oslThread Thread,
+ oslThreadPriority Priority)
+{
+#ifndef NO_PTHREAD_PRIORITY
+
+ struct sched_param Param;
+ int policy;
+ int nRet;
+
+#endif /* NO_PTHREAD_PRIORITY */
+
+ Thread_Impl* pImpl= (Thread_Impl*)Thread;
+
+ OSL_ASSERT(pImpl);
+ if (!pImpl)
+ return; /* EINVAL */
+
+#ifdef NO_PTHREAD_PRIORITY
+ (void) Priority; /* unused */
+#else /* NO_PTHREAD_PRIORITY */
+
+ if (pthread_getschedparam(pImpl->m_hThread, &policy, &Param) != 0)
+ return; /* ESRCH */
+
+#if defined (SOLARIS)
+ if ( policy >= _SCHED_NEXT)
+ {
+ /* mfe: pthread_getschedparam on Solaris has a possible Bug */
+ /* one gets 959917873 as the policy */
+ /* so set the policy to a default one */
+ policy=SCHED_OTHER;
+ }
+#endif /* SOLARIS */
+
+ pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
+
+ switch(Priority)
+ {
+ case osl_Thread_PriorityHighest:
+ Param.sched_priority= g_thread.m_priority.m_Highest;
+ break;
+
+ case osl_Thread_PriorityAboveNormal:
+ Param.sched_priority= g_thread.m_priority.m_Above_Normal;
+ break;
+
+ case osl_Thread_PriorityNormal:
+ Param.sched_priority= g_thread.m_priority.m_Normal;
+ break;
+
+ case osl_Thread_PriorityBelowNormal:
+ Param.sched_priority= g_thread.m_priority.m_Below_Normal;
+ break;
+
+ case osl_Thread_PriorityLowest:
+ Param.sched_priority= g_thread.m_priority.m_Lowest;
+ break;
+
+ case osl_Thread_PriorityUnknown:
+ OSL_ASSERT(sal_False); /* only fools try this...*/
+
+ /* let release-version behave friendly */
+ return;
+
+ default:
+ /* enum expanded, but forgotten here...*/
+ OSL_ENSURE(sal_False,"osl_setThreadPriority : unknown priority\n");
+
+ /* let release-version behave friendly */
+ return;
+ }
+
+ if ((nRet = pthread_setschedparam(pImpl->m_hThread, policy, &Param)) != 0)
+ {
+ OSL_TRACE("failed to change thread priority [%s]\n",strerror(nRet));
+ }
+
+#endif /* NO_PTHREAD_PRIORITY */
+}
+
+/*****************************************************************************/
+/* osl_getThreadPriority */
+/*****************************************************************************/
+oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread)
+{
+#ifndef NO_PTHREAD_PRIORITY
+
+ struct sched_param Param;
+ int Policy;
+
+#endif /* NO_PTHREAD_PRIORITY */
+
+ oslThreadPriority Priority = osl_Thread_PriorityNormal;
+ Thread_Impl* pImpl= (Thread_Impl*)Thread;
+
+ OSL_ASSERT(pImpl);
+ if (!pImpl)
+ return osl_Thread_PriorityUnknown; /* EINVAL */
+
+#ifndef NO_PTHREAD_PRIORITY
+
+ if (pthread_getschedparam(pImpl->m_hThread, &Policy, &Param) != 0)
+ return osl_Thread_PriorityUnknown; /* ESRCH */
+
+ pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
+
+ /* map pthread priority to enum */
+ if (Param.sched_priority==g_thread.m_priority.m_Highest)
+ {
+ /* 127 - highest */
+ Priority= osl_Thread_PriorityHighest;
+ }
+ else if (Param.sched_priority > g_thread.m_priority.m_Normal)
+ {
+ /* 65..126 - above normal */
+ Priority= osl_Thread_PriorityAboveNormal;
+ }
+ else if (Param.sched_priority == g_thread.m_priority.m_Normal)
+ {
+ /* normal */
+ Priority= osl_Thread_PriorityNormal;
+ }
+ else if (Param.sched_priority > g_thread.m_priority.m_Lowest)
+ {
+ /* 63..1 -below normal */
+ Priority= osl_Thread_PriorityBelowNormal;
+ }
+ else if (Param.sched_priority == g_thread.m_priority.m_Lowest)
+ {
+ /* 0 - lowest */
+ Priority= osl_Thread_PriorityLowest;
+ }
+ else
+ {
+ /* unknown */
+ Priority= osl_Thread_PriorityUnknown;
+ }
+
+#endif /* NO_PTHREAD_PRIORITY */
+
+ return Priority;
+}
+
+/*****************************************************************************/
+/* osl_createThreadKey */
+/*****************************************************************************/
+oslThreadKey SAL_CALL osl_createThreadKey( oslThreadKeyCallbackFunction pCallback )
+{
+ pthread_key_t key;
+
+ if (pthread_key_create(&key, pCallback) != 0)
+ key = 0;
+
+ return ((oslThreadKey)key);
+}
+
+/*****************************************************************************/
+/* osl_destroyThreadKey */
+/*****************************************************************************/
+void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
+{
+ pthread_key_delete((pthread_key_t)Key);
+}
+
+/*****************************************************************************/
+/* osl_getThreadKeyData */
+/*****************************************************************************/
+void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
+{
+ return (pthread_getspecific((pthread_key_t)Key));
+}
+
+/*****************************************************************************/
+/* osl_setThreadKeyData */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
+{
+ return (pthread_setspecific((pthread_key_t)Key, pData) == 0);
+}
+
+/*****************************************************************************/
+/* Thread Local Text Encoding */
+/*****************************************************************************/
+static void osl_thread_textencoding_init_Impl (void)
+{
+ rtl_TextEncoding defaultEncoding;
+ const char * pszEncoding;
+
+ /* create thread specific data key */
+ pthread_key_create (&(g_thread.m_textencoding.m_key), NULL);
+
+ /* determine default text encoding */
+ pszEncoding = getenv ("SOLAR_USER_RTL_TEXTENCODING");
+ if (pszEncoding)
+ defaultEncoding = atoi(pszEncoding);
+ else
+ defaultEncoding = osl_getTextEncodingFromLocale(NULL);
+
+ OSL_ASSERT(defaultEncoding != RTL_TEXTENCODING_DONTKNOW);
+
+ /*
+ Tools string functions call abort() on an unknown encoding so ASCII
+ is a meaningfull fallback regardless wether the assertion makes sense.
+ */
+
+ if ( RTL_TEXTENCODING_DONTKNOW == defaultEncoding )
+ defaultEncoding = RTL_TEXTENCODING_ASCII_US;
+
+ g_thread.m_textencoding.m_default = defaultEncoding;
+}
+
+/*****************************************************************************/
+/* osl_getThreadTextEncoding */
+/*****************************************************************************/
+rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding()
+{
+ rtl_TextEncoding threadEncoding;
+
+ pthread_once (&(g_thread.m_once), osl_thread_init_Impl);
+
+ /* check for thread specific encoding, use default if not set */
+ threadEncoding = SAL_INT_CAST(
+ rtl_TextEncoding,
+ (sal_uIntPtr) pthread_getspecific(g_thread.m_textencoding.m_key));
+ if (0 == threadEncoding)
+ threadEncoding = g_thread.m_textencoding.m_default;
+
+ return threadEncoding;
+}
+
+/*****************************************************************************/
+/* osl_setThreadTextEncoding */
+/*****************************************************************************/
+rtl_TextEncoding osl_setThreadTextEncoding(rtl_TextEncoding Encoding)
+{
+ rtl_TextEncoding oldThreadEncoding = osl_getThreadTextEncoding();
+
+ /* save encoding in thread local storage */
+ pthread_setspecific (
+ g_thread.m_textencoding.m_key,
+ (void*) SAL_INT_CAST(sal_uIntPtr, Encoding));
+
+ return oldThreadEncoding;
+}
diff --git a/sal/osl/unx/time.c b/sal/osl/unx/time.c
new file mode 100644
index 000000000000..c1a98a6b87a9
--- /dev/null
+++ b/sal/osl/unx/time.c
@@ -0,0 +1,269 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/time.h>
+
+/* FIXME: detection should be done in configure script */
+#if defined(MACOSX) || defined(FREEBSD) || defined(NETBSD) || defined(LINUX)
+#define STRUCT_TM_HAS_GMTOFF 1
+
+#elif defined(SOLARIS)
+#define HAS_ALTZONE 1
+#endif
+
+/*--------------------------------------------------
+ * osl_getSystemTime
+ *-------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getSystemTime(TimeValue* TimeValue)
+{
+ struct timeval tp;
+
+ /* FIXME: use higher resolution */
+ gettimeofday(&tp, NULL);
+
+ TimeValue->Seconds = tp.tv_sec;
+ TimeValue->Nanosec = tp.tv_usec * 1000;
+
+ return (sal_True);
+}
+
+
+/*--------------------------------------------------
+ * osl_getDateTimeFromTimeValue
+ *-------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getDateTimeFromTimeValue( TimeValue* pTimeVal, oslDateTime* pDateTime )
+{
+ struct tm *pSystemTime;
+ struct tm tmBuf;
+ time_t atime;
+
+ atime = (time_t)pTimeVal->Seconds;
+
+ /* Convert time from type time_t to struct tm */
+ pSystemTime = gmtime_r( &atime, &tmBuf );
+
+
+ /* Convert struct tm to struct oslDateTime */
+ if ( pSystemTime != NULL )
+ {
+ pDateTime->NanoSeconds = pTimeVal->Nanosec;
+ pDateTime->Seconds = pSystemTime->tm_sec;
+ pDateTime->Minutes = pSystemTime->tm_min;
+ pDateTime->Hours = pSystemTime->tm_hour;
+ pDateTime->Day = pSystemTime->tm_mday;
+ pDateTime->DayOfWeek = pSystemTime->tm_wday;
+ pDateTime->Month = pSystemTime->tm_mon + 1;
+ pDateTime->Year = pSystemTime->tm_year + 1900;
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+/*--------------------------------------------------
+ * osl_getTimeValueFromDateTime
+ *--------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getTimeValueFromDateTime( oslDateTime* pDateTime, TimeValue* pTimeVal )
+{
+ struct tm aTime;
+ time_t nSeconds;
+
+ /* Convert struct oslDateTime to struct tm */
+ aTime.tm_sec = pDateTime->Seconds;
+ aTime.tm_min = pDateTime->Minutes;
+ aTime.tm_hour = pDateTime->Hours;
+ aTime.tm_mday = pDateTime->Day;
+ aTime.tm_wday = pDateTime->DayOfWeek;
+
+ if ( pDateTime->Month > 0 )
+ aTime.tm_mon = pDateTime->Month - 1;
+ else
+ return sal_False;
+
+ if ( pDateTime->Year >= 1900 )
+ aTime.tm_year = pDateTime->Year - 1900;
+ else
+ return sal_False;
+
+ aTime.tm_isdst = -1;
+ aTime.tm_wday = 0;
+ aTime.tm_yday = 0;
+
+ /* Convert time to calendar value */
+ nSeconds = mktime( &aTime );
+
+ /*
+ * mktime expects the struct tm to be in local timezone, so we have to adjust
+ * the returned value to be timezone neutral.
+ */
+
+ if ( nSeconds != (time_t) -1 )
+ {
+ time_t bias;
+
+ /* timezone corrections */
+ tzset();
+
+#if defined(STRUCT_TM_HAS_GMTOFF)
+ /* members of struct tm are corrected by mktime */
+ bias = 0 - aTime.tm_gmtoff;
+
+#elif defined(HAS_ALTZONE)
+ /* check if daylight saving time is in effect */
+ bias = aTime.tm_isdst > 0 ? altzone : timezone;
+#else
+ /* exspect daylight saving time to be one hour */
+ bias = aTime.tm_isdst > 0 ? timezone - 3600 : timezone;
+#endif
+
+ pTimeVal->Seconds = nSeconds;
+ pTimeVal->Nanosec = pDateTime->NanoSeconds;
+
+ if ( nSeconds > bias )
+ pTimeVal->Seconds -= bias;
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+
+/*--------------------------------------------------
+ * osl_getLocalTimeFromSystemTime
+ *--------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getLocalTimeFromSystemTime( TimeValue* pSystemTimeVal, TimeValue* pLocalTimeVal )
+{
+ struct tm *pLocalTime;
+ struct tm tmBuf;
+ time_t bias;
+ time_t atime;
+
+ atime = (time_t) pSystemTimeVal->Seconds;
+ pLocalTime = localtime_r( &atime, &tmBuf );
+
+#if defined(STRUCT_TM_HAS_GMTOFF)
+ /* members of struct tm are corrected by mktime */
+ bias = 0 - pLocalTime->tm_gmtoff;
+
+#elif defined(HAS_ALTZONE)
+ /* check if daylight saving time is in effect */
+ bias = pLocalTime->tm_isdst > 0 ? altzone : timezone;
+#else
+ /* exspect daylight saving time to be one hour */
+ bias = pLocalTime->tm_isdst > 0 ? timezone - 3600 : timezone;
+#endif
+
+ if ( (sal_Int64) pSystemTimeVal->Seconds > bias )
+ {
+ pLocalTimeVal->Seconds = pSystemTimeVal->Seconds - bias;
+ pLocalTimeVal->Nanosec = pSystemTimeVal->Nanosec;
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+/*--------------------------------------------------
+ * osl_getSystemTimeFromLocalTime
+ *--------------------------------------------------*/
+
+sal_Bool SAL_CALL osl_getSystemTimeFromLocalTime( TimeValue* pLocalTimeVal, TimeValue* pSystemTimeVal )
+{
+ struct tm *pLocalTime;
+ struct tm tmBuf;
+ time_t bias;
+ time_t atime;
+
+ atime = (time_t) pLocalTimeVal->Seconds;
+
+ /* Convert atime, which is a local time, to it's GMT equivalent. Then, get
+ * the timezone offset for the local time for the GMT equivalent time. Note
+ * that we cannot directly use local time to determine the timezone offset
+ * because GMT is the only reliable time that we can determine timezone
+ * offset from.
+ */
+
+ atime = mktime( gmtime_r( &atime, &tmBuf ) );
+ pLocalTime = localtime_r( &atime, &tmBuf );
+
+#if defined(STRUCT_TM_HAS_GMTOFF)
+ /* members of struct tm are corrected by mktime */
+ bias = 0 - pLocalTime->tm_gmtoff;
+
+#elif defined(HAS_ALTZONE)
+ /* check if daylight saving time is in effect */
+ bias = pLocalTime->tm_isdst > 0 ? altzone : timezone;
+#else
+ /* exspect daylight saving time to be one hour */
+ bias = pLocalTime->tm_isdst > 0 ? timezone - 3600 : timezone;
+#endif
+
+ if ( (sal_Int64) pLocalTimeVal->Seconds + bias > 0 )
+ {
+ pSystemTimeVal->Seconds = pLocalTimeVal->Seconds + bias;
+ pSystemTimeVal->Nanosec = pLocalTimeVal->Nanosec;
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+
+
+static struct timeval startTime;
+static sal_Bool bGlobalTimer = sal_False;
+
+sal_uInt32 SAL_CALL osl_getGlobalTimer()
+{
+ struct timeval currentTime;
+ sal_uInt32 nSeconds;
+
+ // FIXME: not thread safe !!
+ if ( bGlobalTimer == sal_False )
+ {
+ gettimeofday( &startTime, NULL );
+ bGlobalTimer=sal_True;
+ }
+
+ gettimeofday( &currentTime, NULL );
+
+ nSeconds = (sal_uInt32)( currentTime.tv_sec - startTime.tv_sec );
+
+ return ( nSeconds * 1000 ) + (long) (( currentTime.tv_usec - startTime.tv_usec) / 1000 );
+}
diff --git a/sal/osl/unx/util.c b/sal/osl/unx/util.c
new file mode 100644
index 000000000000..5ba04db56021
--- /dev/null
+++ b/sal/osl/unx/util.c
@@ -0,0 +1,350 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef SOLARIS
+#include <sys/sockio.h>
+#endif
+
+#include "osl/util.h"
+
+
+
+/*****************************************************************************/
+/* Static Module Functions */
+/*****************************************************************************/
+
+static int osl_getHWAddr(const char *ifname, char* hard_addr);
+static int osl_checkAddr(const char* addr);
+
+
+/*****************************************************************************/
+/* osl_getEthernetAddress */
+/*****************************************************************************/
+
+sal_Bool SAL_CALL osl_getEthernetAddress( sal_uInt8 * pAddr )
+{
+ char buff[1024];
+ char hard_addr[64];
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ int i;
+ int so;
+
+#ifdef SOLARIS
+ /** algorithm doesn't work on solaris */
+ return sal_False;
+#else
+
+ if ( pAddr == 0 )
+ {
+ return sal_False;
+ }
+
+
+ /*
+ * All we need is ... a network file descriptor.
+ * Normally, this is a very socket.
+ */
+
+ so = socket(AF_INET, SOCK_DGRAM, 0);
+
+
+ /*
+ * The first thing we have to do, get the interface configuration.
+ * It is a list of attached/configured interfaces
+ */
+
+ ifc.ifc_len = sizeof(buff);
+ ifc.ifc_buf = buff;
+ if ( ioctl(so, SIOCGIFCONF, &ifc) < 0 )
+ {
+/* fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));*/
+ close(so);
+ return sal_False;
+ }
+
+ close(so);
+
+ /*
+ * For each of the interfaces in the interface list,
+ * try to get the hardware address
+ */
+
+ ifr = ifc.ifc_req;
+ for ( i = ifc.ifc_len / sizeof(struct ifreq) ; --i >= 0 ; ifr++ )
+ {
+ int nRet=0;
+ nRet = osl_getHWAddr(ifr->ifr_name,hard_addr);
+ if ( nRet > 0 )
+ {
+ memcpy( pAddr , hard_addr, 6 );
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+#endif
+}
+
+
+/*****************************************************************************/
+/* osl_getHWAddr */
+/*****************************************************************************/
+
+static int osl_getHWAddr(const char *ifname, char* hard_addr)
+{
+ int ret=0;
+ struct ifreq ifr;
+ int so = socket(AF_INET, SOCK_DGRAM, 0);
+
+ strcpy(ifr.ifr_name, ifname);
+
+ /*
+ * First, get the Interface-FLAGS
+ */
+
+ ret=ioctl(so, SIOCGIFFLAGS, &ifr) ;
+
+ if ( ret < 0 )
+ {
+/* fprintf(stderr, "SIOCGIFFLAGS: %s\n", strerror(errno)); */
+ close(so);
+ return ret;
+ }
+
+
+ /*
+ * If it is the loopback device, do not consider it any further
+ */
+
+ if (ifr.ifr_flags & IFF_LOOPBACK)
+ {
+/* fprintf(stderr, "SIOCGIFFLAGS : is LOOPBACK : %s\n", strerror(errno));*/
+ close(so);
+ return 0;
+ }
+
+
+ /*
+ * And now, the real thing: the get address
+ */
+
+#ifdef SIOCGIFHWADDR
+ ret=ioctl(so, SIOCGIFHWADDR, &ifr);
+#else
+ ret=ioctl(so, SIOCGIFADDR, &ifr);
+#endif
+
+ if (ret < 0) {
+/* fprintf(stderr, "SIOCGIFADDR: %s\n", strerror(errno));*/
+ memset(hard_addr, 0, 32);
+ close(so);
+ return ret;
+ }
+
+ close(so);
+
+#ifdef SIOCGIFHWADDR
+ memcpy(hard_addr,ifr.ifr_hwaddr.sa_data,8);
+#else
+ memcpy(hard_addr,ifr.ifr_ifru.ifru_addr.sa_data,8);
+#endif
+
+
+ /*
+ * Check, if no real, i.e. 00:00:00:00:00:00, address was retrieved.
+ * The Linux dummy device has this kind of behaviour
+ */
+
+ ret=osl_checkAddr(hard_addr);
+
+ if (ret < 0) {
+/* fprintf(stderr, "SIOCGIFADDR got '00:00:00:00:00:00'\n"); */
+ return ret;
+ }
+
+/* fprintf(stderr,"interface : %s -- ",ifname);*/
+/* fprintf(stderr,"HWaddr : %s\n", print_ether(hard_addr));*/
+
+ return 1;
+}
+
+
+/*****************************************************************************/
+/* osl_checkAddr */
+/*****************************************************************************/
+
+static int osl_checkAddr(const char* addr)
+{
+ if (addr[0]==0 && addr[1]==0 &&
+ addr[2]==0 && addr[3]==0 &&
+ addr[4]==0 && addr[5]==0)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+
+#if defined (SPARC)
+
+#if defined (SOLARIS) && !defined(__sparcv8plus) && !defined(__sparcv9)
+#include <sys/types.h>
+#include <sys/processor.h>
+
+/*****************************************************************************/
+/* osl_InitSparcV9 */
+/*****************************************************************************/
+
+void osl_InterlockedCountSetV9(sal_Bool bV9);
+
+/*
+ * osl_InitSparcV9() should be executed as early as possible. We place it in the
+ * .init section of sal
+ */
+#if defined ( __SUNPRO_C ) || defined ( __SUNPRO_CC )
+void osl_InitSparcV9(void);
+#pragma init (osl_InitSparcV9)
+#elif defined ( __GNUC__ )
+void osl_InitSparcV9(void) __attribute__((constructor));
+#endif
+
+void osl_InitSparcV9(void)
+{
+ /* processor_info() identifies SPARCV8 (ie sun4c machines) simply as "sparc"
+ * and SPARCV9 (ie ultra sparcs, sun4u) as "sparcv9". Since we know that we
+ * run at least on a SPARCV8 architecture or better, any processor type != "sparc"
+ * and != "i386" is considered to be SPARCV9 or better
+ *
+ * This way we are certain that this will still work if someone names SPARCV10
+ * "foobar"
+ */
+ processor_info_t aInfo;
+ int rc;
+
+ rc = processor_info(0, &aInfo);
+
+ if ( rc != -1 ) {
+ if ( !strcmp( "sparc", aInfo.pi_processor_type ) /* SPARCV8 */
+ || !strcmp( "i386", aInfo.pi_processor_type ) ) /* can't happen, but ... */
+ return;
+ /* we are reasonably certain to be on sparcv9/sparcv8plus or better */
+ osl_InterlockedCountSetV9(sal_True);
+ }
+}
+
+#endif /* SOLARIS */
+
+#if defined(NETBSD) && defined(GCC) && !defined(__sparcv9) && !defined(__sparc_v9__)
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+void osl_InitSparcV9(void) __attribute__((constructor));
+void osl_InterlockedCountSetV9(sal_Bool bV9);
+
+/* Determine which processor we are running on (sparc v8 or v9)
+ * The approach is very similar to Solaris.
+ */
+
+void osl_InitSparcV9(void)
+{
+ int mib[2]={CTL_HW,HW_MACHINE};
+ char processorname[256];
+ size_t len=256;
+
+ /* get the machine name */
+ sysctl(mib, 2, processorname, &len, NULL, 0);
+ if (!strncmp("sparc64",processorname, len)) {
+ osl_InterlockedCountSetV9(sal_True);
+ }
+}
+
+#endif /* NETBSD */
+
+#endif /* SPARC */
+
+#if defined ( LINUX ) && defined ( SPARC )
+#include <sys/utsname.h>
+void osl_InitSparcV9(void) __attribute__((constructor));
+void osl_InterlockedCountSetV9(sal_Bool bV9);
+/* Determine which processor we are running on (sparc v8 or v9)
+ * The approach is very similar to Solaris.
+ */
+void osl_InitSparcV9(void)
+{
+ struct utsname name;
+ int rc;
+ rc = uname(&name);
+ if ( rc != -1 ) {
+ if ( !strcmp( "sparc", name.machine ))
+ return;
+ osl_InterlockedCountSetV9(sal_True);
+ }
+}
+#endif
+
+#if ( defined(__GNUC__) && (defined(X86) || defined(X86_64)) )\
+ || ( defined(SOLARIS) && defined (__SUNPRO_C) && defined(__i386) )
+
+/* Safe default */
+int osl_isSingleCPU = 0;
+
+/* Determine if we are on a multiprocessor/multicore/HT x86/x64 system
+ *
+ * The lock prefix for atomic operations in osl_[inc|de]crementInterlockedCount()
+ * comes with a cost and is especially expensive on pre HT x86 single processor
+ * systems, where it isn't needed at all.
+ *
+ * This should be run as early as possible, thus it's placed in the init section
+ */
+#if defined(_SC_NPROCESSORS_CONF) /* i.e. MACOSX for Intel doesn't have this */
+#if defined(__GNUC__)
+void osl_interlockedCountCheckForSingleCPU(void) __attribute__((constructor));
+#elif defined(__SUNPRO_C)
+void osl_interlockedCountCheckForSingleCPU(void);
+#pragma init (osl_interlockedCountCheckForSingleCPU)
+#endif
+
+void osl_interlockedCountCheckForSingleCPU(void)
+{
+ /* In case sysconfig fails be on the safe side,
+ * consider it a multiprocessor/multicore/HT system */
+ if ( sysconf(_SC_NPROCESSORS_CONF) == 1 ) {
+ osl_isSingleCPU = 1;
+ }
+}
+#endif /* defined(_SC_NPROCESSORS_CONF) */
+#endif
diff --git a/sal/osl/unx/uunxapi.cxx b/sal/osl/unx/uunxapi.cxx
new file mode 100644
index 000000000000..299ea4198fdc
--- /dev/null
+++ b/sal/osl/unx/uunxapi.cxx
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+ #ifndef _OSL_UUNXAPI_H_
+ #include "uunxapi.h"
+ #endif
+
+ #ifndef __OSL_SYSTEM_H__
+ #include "system.h"
+ #endif
+
+ #ifndef _LIMITS_H
+ #include <limits.h>
+ #endif
+
+ #ifndef _RTL_USTRING_HXX_
+ #include <rtl/ustring.hxx>
+ #endif
+
+ #ifndef _OSL_THREAD_H_
+ #include <osl/thread.h>
+ #endif
+
+ //###########################
+ inline rtl::OString OUStringToOString(const rtl_uString* s)
+ {
+ return rtl::OUStringToOString(
+ rtl::OUString(const_cast<rtl_uString*>(s)),
+ osl_getThreadTextEncoding());
+ }
+
+ //###########################
+#ifdef MACOSX
+/*
+ * Helper function for resolving Mac native alias files (not the same as unix alias files)
+ * and to return the resolved alias as rtl::OString
+ */
+ inline rtl::OString macxp_resolveAliasAndConvert(const rtl_uString* s)
+ {
+ rtl::OString p = OUStringToOString(s);
+ sal_Char path[PATH_MAX];
+ if (p.getLength() < PATH_MAX)
+ {
+ strcpy(path, p.getStr());
+ macxp_resolveAlias(path, PATH_MAX);
+ p = rtl::OString(path);
+ }
+ return p;
+ }
+#endif /* MACOSX */
+
+ //###########################
+ //access_u
+ int access_u(const rtl_uString* pustrPath, int mode)
+ {
+#ifndef MACOSX // not MACOSX
+ return access(OUStringToOString(pustrPath).getStr(), mode);
+#else
+ return access(macxp_resolveAliasAndConvert(pustrPath).getStr(), mode);
+#endif
+ }
+
+ //#########################
+ //realpath_u
+ sal_Bool realpath_u(const rtl_uString* pustrFileName, rtl_uString** ppustrResolvedName)
+ {
+#ifndef MACOSX // not MACOSX
+ rtl::OString fn = OUStringToOString(pustrFileName);
+#else
+ rtl::OString fn = macxp_resolveAliasAndConvert(pustrFileName);
+#endif
+ char rp[PATH_MAX];
+ bool bRet = realpath(fn.getStr(), rp);
+
+ if (bRet)
+ {
+ rtl::OUString resolved = rtl::OStringToOUString(
+ rtl::OString(static_cast<sal_Char*>(rp)),
+ osl_getThreadTextEncoding());
+
+ rtl_uString_assign(ppustrResolvedName, resolved.pData);
+ }
+ return bRet;
+ }
+
+ //#########################
+ //lstat_u
+ int lstat_u(const rtl_uString* pustrPath, struct stat* buf)
+ {
+#ifndef MACOSX // not MACOSX
+ return lstat(OUStringToOString(pustrPath).getStr(), buf);
+#else
+ return lstat(macxp_resolveAliasAndConvert(pustrPath).getStr(), buf);
+#endif
+ }
+
+ //#########################
+ // @see mkdir
+ int mkdir_u(const rtl_uString* path, mode_t mode)
+ {
+ return mkdir(OUStringToOString(path).getStr(), mode);
+ }
+
diff --git a/sal/osl/unx/uunxapi.h b/sal/osl/unx/uunxapi.h
new file mode 100644
index 000000000000..9eddc5fe4753
--- /dev/null
+++ b/sal/osl/unx/uunxapi.h
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #ifndef _OSL_UUNXAPI_H_
+ #define _OSL_UUNXAPI_H_
+
+ #ifndef _UNISTD_H
+ #include <unistd.h>
+ #endif
+
+ #ifndef _STDLIB_H
+ #include <stdlib.h>
+ #endif
+
+ #ifndef _TYPES_H
+ #include <sys/types.h>
+ #endif
+
+ #ifndef _STAT_H
+ #include <sys/stat.h>
+ #endif
+
+ #ifndef _RTL_USTRING_H_
+ #include <rtl/ustring.h>
+ #endif
+
+
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+
+ /* @see access */
+ int access_u(const rtl_uString* pustrPath, int mode);
+
+ /***********************************
+ @descr
+ The return value differs from the
+ realpath function
+
+ @returns sal_True on success else
+ sal_False
+
+ @see realpath
+ **********************************/
+ sal_Bool realpath_u(
+ const rtl_uString* pustrFileName,
+ rtl_uString** ppustrResolvedName);
+
+ /* @see lstat */
+ int lstat_u(const rtl_uString* pustrPath, struct stat* buf);
+
+ /* @see mkdir */
+ int mkdir_u(const rtl_uString* path, mode_t mode);
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+
+ #endif /* _OSL_UUNXAPI_H_ */
+
diff --git a/sal/osl/unx/uunxapi.hxx b/sal/osl/unx/uunxapi.hxx
new file mode 100644
index 000000000000..7f1a9072e8cc
--- /dev/null
+++ b/sal/osl/unx/uunxapi.hxx
@@ -0,0 +1,98 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #ifndef _OSL_UUNXAPI_HXX_
+ #define _OSL_UUNXAPI_HXX_
+
+ #ifndef _OSL_UUNXAPI_H_
+ #include "uunxapi.h"
+ #endif
+
+ #ifndef _RTL_USTRING_HXX_
+ #include <rtl/ustring.hxx>
+ #endif
+
+ namespace osl
+ {
+
+ /***********************************
+ osl::access
+
+ @see access
+ **********************************/
+
+ inline int access(const rtl::OUString& ustrPath, int mode)
+ {
+ return access_u(ustrPath.pData, mode);
+ }
+
+ /***********************************
+ osl::realpath
+
+ @descr
+ The return value differs from the
+ realpath function
+
+ @returns sal_True on success else
+ sal_False
+
+ @see realpath
+ **********************************/
+
+ inline sal_Bool realpath(
+ const rtl::OUString& ustrFileName,
+ rtl::OUString& ustrResolvedName)
+ {
+ return realpath_u(ustrFileName.pData, &ustrResolvedName.pData);
+ }
+
+
+ /***********************************
+ osl::lstat
+
+ @see lstat
+ **********************************/
+
+ inline int lstat(const rtl::OUString& ustrPath, struct stat& buf)
+ {
+ return lstat_u(ustrPath.pData, &buf);
+ }
+
+ /***********************************
+ osl::mkdir
+ @see mkdir
+ **********************************/
+ inline int mkdir(const rtl::OUString& aPath, mode_t aMode)
+ {
+ return mkdir_u(aPath.pData, aMode);
+ }
+
+ } // end namespace osl
+
+
+ #endif /* _OSL_UUNXAPI_HXX_ */
+
diff --git a/sal/osl/w32/MAKEFILE.MK b/sal/osl/w32/MAKEFILE.MK
new file mode 100644
index 000000000000..4749048847b5
--- /dev/null
+++ b/sal/osl/w32/MAKEFILE.MK
@@ -0,0 +1,118 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=sal
+TARGET=cpposl
+USE_LDUMP2=TRUE
+
+PROJECTPCH4DLL=TRUE
+PROJECTPCH=cont_pch
+PROJECTPCHSOURCE=cont_pch
+
+MULTITHREAD_OBJ=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# Uncomment the following line if you want to compile with -Wall
+# it disables lots of unnecessary warnings comming from the Win32
+# header files (disabling warnings via command line only works with
+# MSVC >= 7.x)
+#
+# CFLAGS+=/wd4668 /wd4711 /wd4201 /wd4710 /wd4619 /wd4514 /wd4820
+
+# --- Files --------------------------------------------------------
+.IF "$(CCNUMVER)" >= "001400000000"
+CDEFS+=-D_CRT_NON_CONFORMING_SWPRINTFS
+.ENDIF
+
+.IF "$(header)" == ""
+
+SLOFILES= $(SLO)$/conditn.obj \
+ $(SLO)$/diagnose.obj \
+ $(SLO)$/dllentry.obj \
+ $(SLO)$/semaphor.obj \
+ $(SLO)$/socket.obj \
+ $(SLO)$/interlck.obj \
+ $(SLO)$/nlsupport.obj\
+ $(SLO)$/mutex.obj \
+ $(SLO)$/thread.obj \
+ $(SLO)$/module.obj \
+ $(SLO)$/process.obj \
+ $(SLO)$/security.obj \
+ $(SLO)$/profile.obj \
+ $(SLO)$/time.obj \
+ $(SLO)$/signal.obj \
+ $(SLO)$/pipeimpl.obj \
+ $(SLO)$/pipe.obj \
+ $(SLO)$/util.obj \
+ $(SLO)$/file.obj\
+ $(SLO)$/file_dirvol.obj\
+ $(SLO)$/file_error.obj\
+ $(SLO)$/file_url.obj\
+ $(SLO)$/tempfile.obj\
+ $(SLO)$/path_helper.obj\
+ $(SLO)$/procimpl.obj \
+ $(SLO)$/salinit.obj
+
+OBJFILES= $(OBJ)$/conditn.obj \
+ $(OBJ)$/diagnose.obj \
+ $(OBJ)$/libutil.obj \
+ $(OBJ)$/semaphor.obj \
+ $(OBJ)$/socket.obj \
+ $(OBJ)$/interlck.obj \
+ $(OBJ)$/nlsupport.obj\
+ $(OBJ)$/mutex.obj \
+ $(OBJ)$/thread.obj \
+ $(OBJ)$/module.obj \
+ $(OBJ)$/process.obj \
+ $(OBJ)$/security.obj \
+ $(OBJ)$/profile.obj \
+ $(OBJ)$/time.obj \
+ $(OBJ)$/signal.obj \
+ $(OBJ)$/pipeimpl.obj \
+ $(OBJ)$/pipe.obj \
+ $(OBJ)$/util.obj \
+ $(OBJ)$/file.obj\
+ $(OBJ)$/file_dirvol.obj\
+ $(OBJ)$/file_error.obj\
+ $(OBJ)$/file_url.obj\
+ $(OBJ)$/tempfile.obj\
+ $(OBJ)$/path_helper.obj\
+ $(OBJ)$/procimpl.obj \
+ $(OBJ)$/salinit.obj
+
+.ENDIF
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+
diff --git a/sal/osl/w32/conditn.c b/sal/osl/w32/conditn.c
new file mode 100644
index 000000000000..1a382af89fcf
--- /dev/null
+++ b/sal/osl/w32/conditn.c
@@ -0,0 +1,141 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/conditn.h>
+#include <osl/diagnose.h>
+#include <osl/time.h>
+
+/*
+ under WIN32, we use the void* oslCondition
+ as a WIN32 HANDLE (which is also a 32-bit value)
+*/
+
+/*****************************************************************************/
+/* osl_createCondition */
+/*****************************************************************************/
+oslCondition SAL_CALL osl_createCondition(void)
+{
+ oslCondition Condition;
+
+ Condition= (oslCondition)CreateEvent(0, /* no security */
+ sal_True, /* manual reset */
+ sal_False, /* initial state not signaled */
+ 0); /* automatic name */
+
+ return Condition;
+
+}
+
+/*****************************************************************************/
+/* osl_destroyCondition */
+/*****************************************************************************/
+void SAL_CALL osl_destroyCondition(oslCondition Condition)
+{
+ if(Condition)
+ {
+ OSL_VERIFY(CloseHandle(Condition));
+ }
+}
+
+/*****************************************************************************/
+/* osl_setCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setCondition(oslCondition Condition)
+{
+ OSL_ASSERT(Condition);
+
+ return (sal_Bool)(SetEvent((HANDLE)Condition) != FALSE);
+}
+
+/*****************************************************************************/
+/* osl_resetCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_resetCondition(oslCondition Condition)
+{
+ OSL_ASSERT(Condition);
+
+ return (sal_Bool)(ResetEvent((HANDLE)Condition) != FALSE);
+}
+
+/*****************************************************************************/
+/* osl_waitCondition */
+/*****************************************************************************/
+oslConditionResult SAL_CALL osl_waitCondition(oslCondition Condition,
+ const TimeValue* pTimeout)
+{
+ DWORD timeout;
+
+ OSL_ASSERT(Condition);
+
+ if (pTimeout)
+ timeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000L;
+ else
+ timeout = INFINITE;
+
+ /* It's necessary to process SendMessage calls to the current thread to give other threads
+ access to COM objects instatiated in this thread */
+
+ while ( 1 )
+ {
+ /* Only wake up if a SendMessage call to the threads message loop is detected */
+ switch( MsgWaitForMultipleObjects( 1, (HANDLE *)(&Condition), FALSE, timeout, QS_SENDMESSAGE ) )
+ {
+ case WAIT_OBJECT_0 + 1:
+ {
+ MSG msg;
+
+ /* We Must not dispatch the message. PM_NOREMOVE leaves the message queue untouched
+ but dispatches SendMessage calls automatically */
+
+ PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE );
+ }
+ break;
+
+ case WAIT_OBJECT_0:
+ return (osl_cond_result_ok);
+
+ case WAIT_TIMEOUT:
+ return (osl_cond_result_timeout);
+
+ default:
+ return (osl_cond_result_error);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* osl_checkCondition */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_checkCondition(oslCondition Condition)
+{
+ OSL_ASSERT(Condition);
+
+ return (sal_Bool)(WaitForSingleObject((HANDLE)Condition, 0) == WAIT_OBJECT_0);
+}
+
diff --git a/sal/osl/w32/diagnose.c b/sal/osl/w32/diagnose.c
new file mode 100644
index 000000000000..b46bff44b73c
--- /dev/null
+++ b/sal/osl/w32/diagnose.c
@@ -0,0 +1,188 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#define NO_DEBUG_CRT
+
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+
+#define NO_DEBUG_CRT
+
+static pfunc_osl_printDebugMessage _pPrintDebugMessage = NULL;
+static pfunc_osl_printDetailedDebugMessage _pPrintDetailedDebugMessage = NULL;
+
+pfunc_osl_printDebugMessage SAL_CALL osl_setDebugMessageFunc( pfunc_osl_printDebugMessage pNewFunc )
+{
+ pfunc_osl_printDebugMessage pOldFunc = _pPrintDebugMessage;
+ _pPrintDebugMessage = pNewFunc;
+
+ return pOldFunc;
+}
+
+pfunc_osl_printDetailedDebugMessage SAL_CALL osl_setDetailedDebugMessageFunc( pfunc_osl_printDetailedDebugMessage pNewFunc )
+{
+ pfunc_osl_printDetailedDebugMessage pOldFunc = _pPrintDetailedDebugMessage;
+ _pPrintDetailedDebugMessage = pNewFunc;
+ return pOldFunc;
+}
+
+/*
+ Trace output
+*/
+
+void SAL_CALL osl_breakDebug(void)
+{
+ DebugBreak();
+}
+
+
+
+/* Uncomment this define to get profiling time output */
+/* #define OSL_PROFILING */
+/* comment this define to stop output thread identifier*/
+#define OSL_TRACE_THREAD 1
+void SAL_CALL osl_trace(const sal_Char* lpszFormat, ...)
+{
+ va_list args;
+ int written = 0;
+
+ va_start(args, lpszFormat);
+
+#if defined(OSL_PROFILING)
+ fprintf(stderr, "time : %06lu : ", osl_getGlobalTimer() );
+#else
+#if defined(OSL_TRACE_THREAD)
+ fprintf(stderr,"Thread: %6d :",osl_getThreadIdentifier(NULL));
+#else
+ fprintf(stderr,"Trace Message : ");
+#endif
+#endif
+
+ if ( IsDebuggerPresent() )
+ {
+ sal_Char szMessage[512];
+ written = _vsnprintf( szMessage, sizeof(szMessage) - 2, lpszFormat, args );
+ if ( written == -1 )
+ written = sizeof(szMessage) - 2;
+ szMessage[ written++ ] = '\n';
+ szMessage[ written ] = 0;
+ OutputDebugString( szMessage );
+ }
+
+ vfprintf(stderr,lpszFormat, args);
+
+ fprintf(stderr,"\n");
+
+ fflush(stderr);
+
+ va_end(args);
+}
+
+sal_Bool SAL_CALL osl_assertFailedLine(const sal_Char* pszFileName, sal_Int32 nLine, const sal_Char* pszMessage)
+{
+#ifndef NO_DEBUG_CRT
+ return (_CrtDbgReport(_CRT_ASSERT, pszFileName, nLine, NULL, pszMessage));
+#else
+ HWND hWndParent;
+ UINT nFlags;
+ int nCode;
+
+ /* get app name or NULL if unknown (don't call assert) */
+ LPCSTR lpszAppName = "Error";
+ sal_Char szMessage[512];
+
+ /* format message into buffer */
+ szMessage[sizeof(szMessage)-1] = '\0'; /* zero terminate always */
+ _snprintf(szMessage, sizeof(szMessage)-1, "%s: File %hs, Line %d\n:%s\n",
+ lpszAppName, pszFileName, nLine, pszMessage);
+
+ OutputDebugString(szMessage);
+
+ if ( _pPrintDetailedDebugMessage )
+ _pPrintDetailedDebugMessage( pszFileName, nLine, pszMessage );
+ else if ( _pPrintDebugMessage )
+ _pPrintDebugMessage( szMessage );
+ else if ( !getenv( "DISABLE_SAL_DBGBOX" ) )
+ {
+ TCHAR szBoxMessage[1024];
+
+ /* active popup window for the current thread */
+ hWndParent = GetActiveWindow();
+ if (hWndParent != NULL)
+ hWndParent = GetLastActivePopup(hWndParent);
+
+ /* set message box flags */
+ nFlags = MB_TASKMODAL | MB_ICONWARNING | MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_SETFOREGROUND;
+ if (hWndParent == NULL)
+ nFlags |= MB_SERVICE_NOTIFICATION;
+
+ /* display the assert */
+
+ szBoxMessage[sizeof(szBoxMessage)-1] = 0;
+ _snprintf(szBoxMessage, sizeof(szBoxMessage)-1, "%s\n( Yes=Abort / No=Ignore / Cancel=Debugger )",
+ szMessage);
+
+ nCode = MessageBox(hWndParent, szBoxMessage, "Assertion Failed!", nFlags);
+
+ if (nCode == IDYES)
+ FatalExit(-1);
+
+ if (nCode == IDNO)
+ return sal_False; /* ignore */
+
+ if (nCode == IDCANCEL)
+ return sal_True; /* will cause oslDebugBreak */
+ }
+#endif /* NO_DEBUG_CRT */
+ return sal_False; /* not shure, not care */
+}
+
+sal_Int32 SAL_CALL osl_reportError(sal_uInt32 nType, const sal_Char* pszMessage)
+{
+ UINT nFlags;
+ int nDisposition;
+
+ // active popup window for the current thread
+ HWND hWndParent = GetActiveWindow();
+ if (hWndParent != NULL)
+ hWndParent = GetLastActivePopup(hWndParent);
+
+ nType = nType; /* avoid warnings */
+
+ /* set message box flags */
+ nFlags = MB_TASKMODAL | MB_ICONERROR | MB_YESNOCANCEL | MB_DEFBUTTON2 | MB_SETFOREGROUND;
+ if (hWndParent == NULL)
+ nFlags |= MB_SERVICE_NOTIFICATION;
+
+ // display the assert
+ nDisposition = MessageBox(hWndParent, pszMessage, "Exception!", nFlags);
+
+ return nDisposition;
+}
+
diff --git a/sal/osl/w32/dllentry.c b/sal/osl/w32/dllentry.c
new file mode 100644
index 000000000000..b6a21d6c2724
--- /dev/null
+++ b/sal/osl/w32/dllentry.c
@@ -0,0 +1,370 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#include <tlhelp32.h>
+#include <systools/win32/uwinapi.h>
+#include <winsock.h>
+#include <osl/diagnose.h>
+#include <sal/types.h>
+#include <float.h>
+
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <sal/types.h>
+
+//------------------------------------------------------------------------------
+// externals
+//------------------------------------------------------------------------------
+
+extern DWORD g_dwTLSTextEncodingIndex;
+extern void SAL_CALL _osl_callThreadKeyCallbackOnThreadDetach(void);
+extern CRITICAL_SECTION g_ThreadKeyListCS;
+extern oslMutex g_Mutex;
+extern oslMutex g_CurrentDirectoryMutex;
+
+extern void rtl_locale_fini (void);
+extern void rtl_memory_fini (void);
+extern void rtl_cache_fini (void);
+extern void rtl_arena_fini (void);
+
+#ifdef __MINGW32__
+
+typedef void (*func_ptr) (void);
+extern func_ptr __CTOR_LIST__[];
+extern func_ptr __DTOR_LIST__[];
+
+static void do_startup(void);
+static void do_cleanup(void);
+
+#else
+
+/*
+This is needed because DllMain is called after static constructors. A DLL's
+startup and shutdown sequence looks like this:
+
+_pRawDllMain()
+_CRT_INIT()
+DllMain()
+....
+DllMain()
+_CRT_INIT()
+_pRawDllMain()
+
+*/
+
+static BOOL WINAPI _RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved );
+extern BOOL (WINAPI *_pRawDllMain)(HANDLE, DWORD, LPVOID) = _RawDllMain;
+
+#endif
+
+//------------------------------------------------------------------------------
+// globales
+//------------------------------------------------------------------------------
+
+DWORD g_dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; // remember plattform
+
+//------------------------------------------------------------------------------
+// DllMain
+//------------------------------------------------------------------------------
+#ifdef _M_IX86
+int osl_isSingleCPU = 0;
+#endif
+
+#ifdef __MINGW32__
+
+void
+__do_global_dtors (void)
+{
+ static func_ptr *p = __DTOR_LIST__ + 1;
+
+ /*
+ * Call each destructor in the destructor list until a null pointer
+ * is encountered.
+ */
+ while (*p)
+ {
+ (*(p)) ();
+ p++;
+ }
+}
+
+void
+__do_global_ctors (void)
+{
+ unsigned long nptrs = (unsigned long) __CTOR_LIST__[0];
+ unsigned i;
+
+ /*
+ * If the first entry in the constructor list is -1 then the list
+ * is terminated with a null entry. Otherwise the first entry was
+ * the number of pointers in the list.
+ */
+ if (nptrs == -1)
+ {
+ for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++)
+ ;
+ }
+
+ /*
+ * Go through the list backwards calling constructors.
+ */
+ for (i = nptrs; i >= 1; i--)
+ {
+ __CTOR_LIST__[i] ();
+ }
+
+ /*
+ * Register the destructors for processing on exit.
+ */
+ atexit (__do_global_dtors);
+}
+
+static int initialized = 0;
+
+void
+__main (void)
+{
+ if (!initialized)
+ {
+ initialized = 1;
+ do_startup();
+ __do_global_ctors ();
+ }
+}
+
+static void do_startup( void )
+{
+#else
+static BOOL WINAPI _RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
+{
+ (void)hinstDLL; /* avoid warnings */
+ (void)lpvReserved; /* avoid warnings */
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+#endif
+ OSVERSIONINFO aInfo;
+
+#ifdef _M_IX86
+ SYSTEM_INFO SystemInfo;
+
+ GetSystemInfo(&SystemInfo);
+
+ /* Determine if we are on a multiprocessor/multicore/HT x86/x64 system
+ *
+ * The lock prefix for atomic operations in osl_[inc|de]crementInterlockedCount()
+ * comes with a cost and is especially expensive on pre HT x86 single processor
+ * systems, where it isn't needed at all.
+ */
+ if ( SystemInfo.dwNumberOfProcessors == 1 ) {
+ osl_isSingleCPU = 1;
+ }
+#endif
+ /* Suppress file error messages from system like "Floppy A: not inserted" */
+ SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS );
+
+ /* initialize global mutex */
+ g_Mutex = osl_createMutex();
+
+ /* initialize "current directory" mutex */
+ g_CurrentDirectoryMutex = osl_createMutex();
+
+
+ /* initialize Win9x unicode functions */
+ aInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+
+ if ( GetVersionEx(&aInfo) )
+ g_dwPlatformId = aInfo.dwPlatformId;
+
+ g_dwTLSTextEncodingIndex = TlsAlloc();
+ InitializeCriticalSection( &g_ThreadKeyListCS );
+
+ //We disable floating point exceptions. This is the usual state at program startup
+ //but on Windows 98 and ME this is not always the case.
+ _control87(_MCW_EM, _MCW_EM);
+#ifdef __MINGW32__
+ atexit(do_cleanup);
+}
+
+void do_cleanup( void )
+{
+#else
+ break;
+ }
+
+ case DLL_PROCESS_DETACH:
+#endif
+
+ WSACleanup( );
+
+ TlsFree( g_dwTLSTextEncodingIndex );
+ DeleteCriticalSection( &g_ThreadKeyListCS );
+
+ osl_destroyMutex( g_Mutex );
+
+ osl_destroyMutex( g_CurrentDirectoryMutex );
+
+#ifndef __MINGW32__
+
+ /*
+
+ On a product build memory management finalization might
+ cause a crash without assertion (assertions off) if heap is
+ corrupted. But a crash report won't help here because at
+ this point all other threads have been terminated and only
+ ntdll is on the stack. No chance to find the reason for the
+ corrupted heap if so.
+
+ So annoying the user with a crash report is completly useless.
+
+ */
+
+#ifndef DBG_UTIL
+ __try
+#endif
+ {
+ /* cleanup locale hashtable */
+ rtl_locale_fini();
+
+ /* finalize memory management */
+ rtl_memory_fini();
+ rtl_cache_fini();
+ rtl_arena_fini();
+ }
+#ifndef DBG_UTIL
+ __except( EXCEPTION_EXECUTE_HANDLER )
+ {
+ }
+#endif
+ break;
+ }
+
+ return TRUE;
+#endif
+}
+
+static DWORD GetParentProcessId()
+{
+ DWORD dwParentProcessId = 0;
+ HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
+
+ if ( IsValidHandle( hSnapshot ) )
+ {
+ PROCESSENTRY32 pe;
+ BOOL fSuccess;
+
+ ZeroMemory( &pe, sizeof(pe) );
+ pe.dwSize = sizeof(pe);
+ fSuccess = Process32First( hSnapshot, &pe );
+
+ while( fSuccess )
+ {
+ if ( GetCurrentProcessId() == pe.th32ProcessID )
+ {
+ dwParentProcessId = pe.th32ParentProcessID;
+ break;
+ }
+
+ fSuccess = Process32Next( hSnapshot, &pe );
+ }
+
+ CloseHandle( hSnapshot );
+ }
+
+ return dwParentProcessId;
+}
+
+static DWORD WINAPI ParentMonitorThreadProc( LPVOID lpParam )
+{
+ DWORD dwParentProcessId = (DWORD)lpParam;
+
+ HANDLE hParentProcess = OpenProcess( SYNCHRONIZE, FALSE, dwParentProcessId );
+ if ( IsValidHandle( hParentProcess ) )
+ {
+ if ( WAIT_OBJECT_0 == WaitForSingleObject( hParentProcess, INFINITE ) )
+ {
+ TerminateProcess( GetCurrentProcess(), 0 );
+ }
+ CloseHandle( hParentProcess );
+ }
+ return 0;
+}
+
+BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
+{
+ (void)hinstDLL; /* avoid warning */
+ (void)lpvReserved; /* avoid warning */
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ TCHAR szBuffer[64];
+
+ // This code will attach the process to it's parent process
+ // if the parent process had set the environment variable.
+ // The corresponding code (setting the environment variable)
+ // is is desktop/win32/source/officeloader.cxx
+
+
+ DWORD dwResult = GetEnvironmentVariable( "ATTACHED_PARENT_PROCESSID", szBuffer, sizeof(szBuffer) );
+
+ if ( dwResult && dwResult < sizeof(szBuffer) )
+ {
+ DWORD dwThreadId = 0;
+
+ DWORD dwParentProcessId = (DWORD)atol( szBuffer );
+
+ if ( dwParentProcessId && GetParentProcessId() == dwParentProcessId )
+ {
+ // No error check, it works or it does not
+ // Thread should only be started for headless mode, see desktop/win32/source/officeloader.cxx
+ CreateThread( NULL, 0, ParentMonitorThreadProc, (LPVOID)dwParentProcessId, 0, &dwThreadId ); //
+ }
+ }
+
+ return TRUE;
+ }
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ _osl_callThreadKeyCallbackOnThreadDetach( );
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/sal/osl/w32/file.cxx b/sal/osl/w32/file.cxx
new file mode 100644
index 000000000000..7728189387cd
--- /dev/null
+++ b/sal/osl/w32/file.cxx
@@ -0,0 +1,1194 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT 0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "osl/file.hxx"
+
+#include "file_url.h"
+#include "file_error.h"
+
+#include "osl/diagnose.h"
+#include "rtl/alloc.h"
+#include "rtl/byteseq.h"
+#include "rtl/ustring.hxx"
+
+#include <stdio.h>
+#include <tchar.h>
+
+#ifdef __MINGW32__
+#include <wchar.h>
+#include <ctype.h>
+#endif
+
+#include <algorithm>
+#include <limits>
+
+#ifdef max /* conflict w/ std::numeric_limits<T>::max() */
+#undef max
+#endif
+#ifdef min
+#undef min
+#endif
+
+//##################################################################
+// File handle implementation
+//##################################################################
+struct FileHandle_Impl
+{
+ CRITICAL_SECTION m_mutex;
+ HANDLE m_hFile;
+
+ /** State
+ */
+ enum StateBits
+ {
+ STATE_SEEKABLE = 1, /* open() sets, iff regular file */
+ STATE_READABLE = 2, /* open() sets, read() requires */
+ STATE_WRITEABLE = 4, /* open() sets, write() requires */
+ STATE_MODIFIED = 8 /* write() sets, flush() resets */
+ };
+ int m_state;
+
+ sal_uInt64 m_size; /* file size */
+ LONGLONG m_offset; /* physical offset from begin of file */
+ LONGLONG m_filepos; /* logical offset from begin of file */
+
+ LONGLONG m_bufptr; /* buffer offset from begin of file */
+ SIZE_T m_buflen; /* buffer filled [0, m_bufsiz - 1] */
+
+ SIZE_T m_bufsiz;
+ sal_uInt8 * m_buffer;
+
+ explicit FileHandle_Impl (HANDLE hFile);
+ ~FileHandle_Impl();
+
+ static void* operator new(size_t n);
+ static void operator delete(void * p, size_t);
+ static SIZE_T getpagesize();
+
+ sal_uInt64 getPos() const;
+ oslFileError setPos (sal_uInt64 uPos);
+
+ sal_uInt64 getSize() const;
+ oslFileError setSize (sal_uInt64 uPos);
+
+ oslFileError readAt (
+ LONGLONG nOffset,
+ void * pBuffer,
+ DWORD nBytesRequested,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeAt (
+ LONGLONG nOffset,
+ void const * pBuffer,
+ DWORD nBytesToWrite,
+ sal_uInt64 * pBytesWritten);
+
+ oslFileError readFileAt (
+ LONGLONG nOffset,
+ void * pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeFileAt (
+ LONGLONG nOffset,
+ void const * pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64 * pBytesWritten);
+
+ oslFileError readLineAt (
+ LONGLONG nOffset,
+ sal_Sequence ** ppSequence,
+ sal_uInt64 * pBytesRead);
+
+ oslFileError writeSequence_Impl (
+ sal_Sequence ** ppSequence,
+ SIZE_T * pnOffset,
+ const void * pBuffer,
+ SIZE_T nBytes);
+
+ oslFileError syncFile();
+
+ /** Buffer cache / allocator.
+ */
+ class Allocator
+ {
+ rtl_cache_type * m_cache;
+ SIZE_T m_bufsiz;
+
+ Allocator (Allocator const &);
+ Allocator & operator= (Allocator const &);
+
+ public:
+ static Allocator & get();
+
+ void allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize);
+ void deallocate (sal_uInt8 * pBuffer);
+
+ protected:
+ Allocator();
+ ~Allocator();
+ };
+
+ /** Guard.
+ */
+ class Guard
+ {
+ LPCRITICAL_SECTION m_mutex;
+
+ public:
+ explicit Guard(LPCRITICAL_SECTION pMutex);
+ ~Guard();
+ };
+};
+
+FileHandle_Impl::Allocator &
+FileHandle_Impl::Allocator::get()
+{
+ static Allocator g_aBufferAllocator;
+ return g_aBufferAllocator;
+}
+
+FileHandle_Impl::Allocator::Allocator()
+ : m_cache (0),
+ m_bufsiz (0)
+{
+ SIZE_T const pagesize = FileHandle_Impl::getpagesize();
+ m_cache = rtl_cache_create (
+ "osl_file_buffer_cache", pagesize, 0, 0, 0, 0, 0, 0, 0);
+ if (0 != m_cache)
+ m_bufsiz = pagesize;
+}
+
+FileHandle_Impl::Allocator::~Allocator()
+{
+ rtl_cache_destroy(m_cache), m_cache = 0;
+}
+
+void FileHandle_Impl::Allocator::allocate (sal_uInt8 ** ppBuffer, SIZE_T * pnSize)
+{
+ OSL_PRECOND((0 != ppBuffer) && (0 != pnSize), "FileHandle_Impl::Allocator::allocate(): contract violation");
+ *ppBuffer = static_cast< sal_uInt8* >(rtl_cache_alloc(m_cache)), *pnSize = m_bufsiz;
+}
+
+void FileHandle_Impl::Allocator::deallocate (sal_uInt8 * pBuffer)
+{
+ if (0 != pBuffer)
+ rtl_cache_free (m_cache, pBuffer);
+}
+
+FileHandle_Impl::Guard::Guard(LPCRITICAL_SECTION pMutex)
+ : m_mutex (pMutex)
+{
+ OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::Guard(): null pointer.");
+ ::EnterCriticalSection (m_mutex);
+}
+FileHandle_Impl::Guard::~Guard()
+{
+ OSL_PRECOND (m_mutex != 0, "FileHandle_Impl::Guard::~Guard(): null pointer.");
+ ::LeaveCriticalSection (m_mutex);
+}
+
+FileHandle_Impl::FileHandle_Impl(HANDLE hFile)
+ : m_hFile (hFile),
+ m_state (STATE_READABLE | STATE_WRITEABLE),
+ m_size (0),
+ m_offset (0),
+ m_filepos (0),
+ m_bufptr (-1),
+ m_buflen (0),
+ m_bufsiz (0),
+ m_buffer (0)
+{
+ ::InitializeCriticalSection (&m_mutex);
+ Allocator::get().allocate (&m_buffer, &m_bufsiz);
+ if (m_buffer != 0)
+ memset (m_buffer, 0, m_bufsiz);
+}
+
+FileHandle_Impl::~FileHandle_Impl()
+{
+ Allocator::get().deallocate (m_buffer), m_buffer = 0;
+ ::DeleteCriticalSection (&m_mutex);
+}
+
+void * FileHandle_Impl::operator new(size_t n)
+{
+ return rtl_allocateMemory(n);
+}
+
+void FileHandle_Impl::operator delete(void * p, size_t)
+{
+ rtl_freeMemory(p);
+}
+
+SIZE_T FileHandle_Impl::getpagesize()
+{
+ SYSTEM_INFO info;
+ ::GetSystemInfo (&info);
+ return sal::static_int_cast< SIZE_T >(info.dwPageSize);
+}
+
+sal_uInt64 FileHandle_Impl::getPos() const
+{
+ return sal::static_int_cast< sal_uInt64 >(m_filepos);
+}
+
+oslFileError FileHandle_Impl::setPos (sal_uInt64 uPos)
+{
+ m_filepos = sal::static_int_cast< LONGLONG >(uPos);
+ return osl_File_E_None;
+}
+
+sal_uInt64 FileHandle_Impl::getSize() const
+{
+ LONGLONG bufend = std::max((LONGLONG)(0), m_bufptr) + m_buflen;
+ return std::max(m_size, sal::static_int_cast< sal_uInt64 >(bufend));
+}
+
+oslFileError FileHandle_Impl::setSize (sal_uInt64 uSize)
+{
+ LARGE_INTEGER nDstPos; nDstPos.QuadPart = sal::static_int_cast< LONGLONG >(uSize);
+ if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN))
+ return oslTranslateFileError( GetLastError() );
+
+ if (!::SetEndOfFile(m_hFile))
+ return oslTranslateFileError( GetLastError() );
+ m_size = uSize;
+
+ nDstPos.QuadPart = m_offset;
+ if (!::SetFilePointerEx(m_hFile, nDstPos, 0, FILE_BEGIN))
+ return oslTranslateFileError( GetLastError() );
+
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::readAt (
+ LONGLONG nOffset,
+ void * pBuffer,
+ DWORD nBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::readAt(): not seekable");
+ if (!(m_state & STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ OSL_PRECOND(m_state & STATE_READABLE, "FileHandle_Impl::readAt(): not readable");
+ if (!(m_state & STATE_READABLE))
+ return osl_File_E_BADF;
+
+ if (nOffset != m_offset)
+ {
+ LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset;
+ if (!::SetFilePointerEx(m_hFile, liOffset, 0, FILE_BEGIN))
+ return oslTranslateFileError( GetLastError() );
+ m_offset = nOffset;
+ }
+
+ DWORD dwDone = 0;
+ if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0))
+ return oslTranslateFileError( GetLastError() );
+ m_offset += dwDone;
+
+ *pBytesRead = dwDone;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::writeAt (
+ LONGLONG nOffset,
+ void const * pBuffer,
+ DWORD nBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ OSL_PRECOND(m_state & STATE_SEEKABLE, "FileHandle_Impl::writeAt(): not seekable");
+ if (!(m_state & STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ OSL_PRECOND(m_state & STATE_WRITEABLE, "FileHandle_Impl::writeAt(): not writeable");
+ if (!(m_state & STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ if (nOffset != m_offset)
+ {
+ LARGE_INTEGER liOffset; liOffset.QuadPart = nOffset;
+ if (!::SetFilePointerEx (m_hFile, liOffset, 0, FILE_BEGIN))
+ return oslTranslateFileError( GetLastError() );
+ m_offset = nOffset;
+ }
+
+ DWORD dwDone = 0;
+ if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0))
+ return oslTranslateFileError( GetLastError() );
+ m_offset += dwDone;
+
+ m_size = std::max(m_size, sal::static_int_cast< sal_uInt64 >(m_offset));
+
+ *pBytesWritten = dwDone;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::readFileAt (
+ LONGLONG nOffset,
+ void * pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
+ if (g_limit_dword < uBytesRequested)
+ return osl_File_E_OVERFLOW;
+ DWORD nBytesRequested = sal::static_int_cast< DWORD >(uBytesRequested);
+
+ if (0 == (m_state & STATE_SEEKABLE))
+ {
+ // not seekable (pipe)
+ DWORD dwDone = 0;
+ if (!::ReadFile(m_hFile, pBuffer, nBytesRequested, &dwDone, 0))
+ return oslTranslateFileError( GetLastError() );
+ *pBytesRead = dwDone;
+ return osl_File_E_None;
+ }
+ else if (0 == m_buffer)
+ {
+ // not buffered
+ return readAt (nOffset, pBuffer, nBytesRequested, pBytesRead);
+ }
+ else
+ {
+ sal_uInt8 * buffer = static_cast< sal_uInt8* >(pBuffer);
+ for (*pBytesRead = 0; nBytesRequested > 0; )
+ {
+ LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ SIZE_T const bufpos = (nOffset % m_bufsiz);
+
+ if (bufptr != m_bufptr)
+ {
+ // flush current buffer
+ oslFileError result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = -1, m_buflen = 0;
+
+ if (nBytesRequested >= m_bufsiz)
+ {
+ // buffer too small, read through from file
+ sal_uInt64 uDone = 0;
+ result = readAt (nOffset, &(buffer[*pBytesRead]), nBytesRequested, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+
+ nBytesRequested -= sal::static_int_cast< DWORD >(uDone), *pBytesRead += uDone;
+ return osl_File_E_None;
+ }
+
+ // update buffer (pointer)
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
+ }
+ if (bufpos >= m_buflen)
+ {
+ // end of file
+ return osl_File_E_None;
+ }
+
+ SIZE_T const bytes = std::min(m_buflen - bufpos, nBytesRequested);
+ memcpy (&(buffer[*pBytesRead]), &(m_buffer[bufpos]), bytes);
+ nBytesRequested -= bytes, *pBytesRead += bytes, nOffset += bytes;
+ }
+ return osl_File_E_None;
+ }
+}
+
+oslFileError FileHandle_Impl::writeFileAt (
+ LONGLONG nOffset,
+ void const * pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64 * pBytesWritten)
+{
+ static sal_uInt64 const g_limit_dword = std::numeric_limits< DWORD >::max();
+ if (g_limit_dword < uBytesToWrite)
+ return osl_File_E_OVERFLOW;
+ DWORD nBytesToWrite = sal::static_int_cast< DWORD >(uBytesToWrite);
+
+ if (0 == (m_state & STATE_SEEKABLE))
+ {
+ // not seekable (pipe)
+ DWORD dwDone = 0;
+ if (!::WriteFile(m_hFile, pBuffer, nBytesToWrite, &dwDone, 0))
+ return oslTranslateFileError( GetLastError() );
+ *pBytesWritten = dwDone;
+ return osl_File_E_None;
+ }
+ else if (0 == m_buffer)
+ {
+ // not buffered
+ return writeAt(nOffset, pBuffer, nBytesToWrite, pBytesWritten);
+ }
+ else
+ {
+ sal_uInt8 const * buffer = static_cast< sal_uInt8 const* >(pBuffer);
+ for (*pBytesWritten = 0; nBytesToWrite > 0; )
+ {
+ LONGLONG const bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ SIZE_T const bufpos = (nOffset % m_bufsiz);
+ if (bufptr != m_bufptr)
+ {
+ // flush current buffer
+ oslFileError result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = -1, m_buflen = 0;
+
+ if (nBytesToWrite >= m_bufsiz)
+ {
+ // buffer too small, write through to file
+ sal_uInt64 uDone = 0;
+ result = writeAt (nOffset, &(buffer[*pBytesWritten]), nBytesToWrite, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ if (uDone != nBytesToWrite)
+ return osl_File_E_IO;
+
+ nBytesToWrite -= sal::static_int_cast< DWORD >(uDone), *pBytesWritten += uDone;
+ return osl_File_E_None;
+ }
+
+ // update buffer (pointer)
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
+ }
+
+ SIZE_T const bytes = std::min(m_bufsiz - bufpos, nBytesToWrite);
+ memcpy (&(m_buffer[bufpos]), &(buffer[*pBytesWritten]), bytes);
+ nBytesToWrite -= bytes, *pBytesWritten += bytes, nOffset += bytes;
+
+ m_buflen = std::max(m_buflen, bufpos + bytes);
+ m_state |= STATE_MODIFIED;
+ }
+ return osl_File_E_None;
+ }
+}
+
+oslFileError FileHandle_Impl::readLineAt (
+ LONGLONG nOffset,
+ sal_Sequence ** ppSequence,
+ sal_uInt64 * pBytesRead)
+{
+ oslFileError result = osl_File_E_None;
+
+ LONGLONG bufptr = (nOffset / m_bufsiz) * m_bufsiz;
+ if (bufptr != m_bufptr)
+ {
+ /* flush current buffer */
+ result = syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+
+ /* update buffer (pointer) */
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+
+ m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
+ }
+
+ static int const LINE_STATE_BEGIN = 0;
+ static int const LINE_STATE_CR = 1;
+ static int const LINE_STATE_LF = 2;
+
+ SIZE_T bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos, dstpos = 0;
+ int state = (bufpos >= m_buflen) ? LINE_STATE_LF : LINE_STATE_BEGIN;
+
+ for ( ; state != LINE_STATE_LF; )
+ {
+ if (curpos >= m_buflen)
+ {
+ /* buffer examined */
+ if (0 < (curpos - bufpos))
+ {
+ /* flush buffer to sequence */
+ result = writeSequence_Impl (
+ ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos);
+ if (result != osl_File_E_None)
+ return (result);
+ *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
+ }
+
+ bufptr = nOffset / m_bufsiz * m_bufsiz;
+ if (bufptr != m_bufptr)
+ {
+ /* update buffer (pointer) */
+ sal_uInt64 uDone = 0;
+ result = readAt (bufptr, m_buffer, m_bufsiz, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ m_bufptr = bufptr, m_buflen = sal::static_int_cast< SIZE_T >(uDone);
+ }
+
+ bufpos = sal::static_int_cast< SIZE_T >(nOffset - m_bufptr), curpos = bufpos;
+ if (bufpos >= m_buflen)
+ break;
+ }
+ switch (state)
+ {
+ case LINE_STATE_CR:
+ state = LINE_STATE_LF;
+ switch (m_buffer[curpos])
+ {
+ case 0x0A: /* CRLF */
+ /* eat current char */
+ curpos++;
+ break;
+ default: /* single CR */
+ /* keep current char */
+ break;
+ }
+ break;
+ default:
+ /* determine next state */
+ switch (m_buffer[curpos])
+ {
+ case 0x0A: /* single LF */
+ state = LINE_STATE_LF;
+ break;
+ case 0x0D: /* CR */
+ state = LINE_STATE_CR;
+ break;
+ default: /* advance to next char */
+ curpos++;
+ break;
+ }
+ if (state != LINE_STATE_BEGIN)
+ {
+ /* store (and eat) the newline char */
+ m_buffer[curpos] = 0x0A, curpos++;
+
+ /* flush buffer to sequence */
+ result = writeSequence_Impl (
+ ppSequence, &dstpos, &(m_buffer[bufpos]), curpos - bufpos - 1);
+ if (result != osl_File_E_None)
+ return (result);
+ *pBytesRead += curpos - bufpos, nOffset += curpos - bufpos;
+ }
+ break;
+ }
+ }
+
+ result = writeSequence_Impl (ppSequence, &dstpos, 0, 0);
+ if (result != osl_File_E_None)
+ return (result);
+ if (0 < dstpos)
+ return osl_File_E_None;
+ if (bufpos >= m_buflen)
+ return osl_File_E_AGAIN;
+ return osl_File_E_None;
+}
+
+oslFileError FileHandle_Impl::writeSequence_Impl (
+ sal_Sequence ** ppSequence,
+ SIZE_T * pnOffset,
+ const void * pBuffer,
+ SIZE_T nBytes)
+{
+ sal_Int32 nElements = *pnOffset + nBytes;
+ if (!*ppSequence)
+ {
+ /* construct sequence */
+ rtl_byte_sequence_constructNoDefault(ppSequence, nElements);
+ }
+ else if (nElements != (*ppSequence)->nElements)
+ {
+ /* resize sequence */
+ rtl_byte_sequence_realloc(ppSequence, nElements);
+ }
+ if (*ppSequence != 0)
+ {
+ /* fill sequence */
+ memcpy(&((*ppSequence)->elements[*pnOffset]), pBuffer, nBytes), *pnOffset += nBytes;
+ }
+ return (*ppSequence != 0) ? osl_File_E_None : osl_File_E_NOMEM;
+}
+
+oslFileError FileHandle_Impl::syncFile()
+{
+ oslFileError result = osl_File_E_None;
+ if (m_state & STATE_MODIFIED)
+ {
+ sal_uInt64 uDone = 0;
+ result = writeAt (m_bufptr, m_buffer, m_buflen, &uDone);
+ if (result != osl_File_E_None)
+ return (result);
+ if (uDone != m_buflen)
+ return osl_File_E_IO;
+ m_state &= ~STATE_MODIFIED;
+ }
+ return (result);
+}
+
+//##################################################################
+// File I/O functions
+//##################################################################
+
+extern "C" oslFileHandle
+SAL_CALL osl_createFileHandleFromOSHandle (
+ HANDLE hFile,
+ sal_uInt32 uFlags)
+{
+ if ( !IsValidHandle(hFile) )
+ return 0; // EINVAL
+
+ FileHandle_Impl * pImpl = new FileHandle_Impl(hFile);
+ if (pImpl == 0)
+ {
+ // cleanup and fail
+ (void) ::CloseHandle(hFile);
+ return 0; // ENOMEM
+ }
+
+ /* check for regular file */
+ if (FILE_TYPE_DISK == GetFileType(hFile))
+ {
+ /* mark seekable */
+ pImpl->m_state |= FileHandle_Impl::STATE_SEEKABLE;
+
+ /* init current size */
+ LARGE_INTEGER uSize = { 0, 0 };
+ (void) ::GetFileSizeEx(hFile, &uSize);
+ pImpl->m_size = (sal::static_int_cast<sal_uInt64>(uSize.HighPart) << 32) + uSize.LowPart;
+ }
+
+ if (!(uFlags & osl_File_OpenFlag_Read))
+ pImpl->m_state &= ~FileHandle_Impl::STATE_READABLE;
+ if (!(uFlags & osl_File_OpenFlag_Write))
+ pImpl->m_state &= ~FileHandle_Impl::STATE_WRITEABLE;
+
+ OSL_POSTCOND(
+ (uFlags & osl_File_OpenFlag_Read) || (uFlags & osl_File_OpenFlag_Write),
+ "osl_createFileHandleFromOSHandle(): missing read/write access flags");
+ return (oslFileHandle)(pImpl);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_openFile(
+ rtl_uString * strPath,
+ oslFileHandle * pHandle,
+ sal_uInt32 uFlags )
+{
+ rtl_uString * strSysPath = 0;
+ oslFileError result = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+ if (result != osl_File_E_None)
+ return (result);
+
+ DWORD dwAccess = GENERIC_READ, dwShare = FILE_SHARE_READ, dwCreation = 0, dwAttributes = 0;
+
+ if ( uFlags & osl_File_OpenFlag_Write )
+ dwAccess |= GENERIC_WRITE;
+ else
+ dwShare |= FILE_SHARE_WRITE;
+
+ if ( uFlags & osl_File_OpenFlag_NoLock )
+ dwShare |= FILE_SHARE_WRITE;
+
+ if ( uFlags & osl_File_OpenFlag_Create )
+ dwCreation |= CREATE_NEW;
+ else
+ dwCreation |= OPEN_EXISTING;
+
+ HANDLE hFile = CreateFileW(
+ reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )),
+ dwAccess, dwShare, NULL, dwCreation, dwAttributes, NULL );
+
+ // @@@ ERROR HANDLING @@@
+ if ( !IsValidHandle( hFile ) )
+ result = oslTranslateFileError( GetLastError() );
+
+ *pHandle = osl_createFileHandleFromOSHandle (hFile, uFlags | osl_File_OpenFlag_Read);
+
+ rtl_uString_release( strSysPath );
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_syncFile(oslFileHandle Handle)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ return result;
+
+ if (!FlushFileBuffers(pImpl->m_hFile))
+ return oslTranslateFileError(GetLastError());
+
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_closeFile(oslFileHandle Handle)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
+ return osl_File_E_INVAL;
+
+ ::EnterCriticalSection (&(pImpl->m_mutex));
+
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ {
+ /* ignore double failure */
+ (void)::CloseHandle(pImpl->m_hFile);
+ }
+ else if (!::CloseHandle(pImpl->m_hFile))
+ {
+ /* translate error code */
+ result = oslTranslateFileError( GetLastError() );
+ }
+
+ ::LeaveCriticalSection (&(pImpl->m_mutex));
+ delete pImpl;
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_mapFile(
+ oslFileHandle Handle,
+ void** ppAddr,
+ sal_uInt64 uLength,
+ sal_uInt64 uOffset,
+ sal_uInt32 uFlags)
+{
+ struct FileMapping
+ {
+ HANDLE m_handle;
+
+ explicit FileMapping (HANDLE hMap)
+ : m_handle (hMap)
+ {}
+
+ ~FileMapping()
+ {
+ (void)::CloseHandle(m_handle);
+ }
+ };
+
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppAddr))
+ return osl_File_E_INVAL;
+ *ppAddr = 0;
+
+ static SIZE_T const nLimit = std::numeric_limits< SIZE_T >::max();
+ if (uLength > nLimit)
+ return osl_File_E_OVERFLOW;
+ SIZE_T const nLength = sal::static_int_cast< SIZE_T >(uLength);
+
+ OSVERSIONINFO osinfo;
+ osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ (void)::GetVersionEx(&osinfo);
+
+ if (VER_PLATFORM_WIN32_NT != osinfo.dwPlatformId)
+ return osl_File_E_NOSYS; // Unsupported
+
+ FileMapping aMap( ::CreateFileMapping (pImpl->m_hFile, NULL, SEC_COMMIT | PAGE_READONLY, 0, 0, NULL) );
+ if (!IsValidHandle(aMap.m_handle))
+ return oslTranslateFileError( GetLastError() );
+
+ DWORD const dwOffsetHi = sal::static_int_cast<DWORD>(uOffset >> 32);
+ DWORD const dwOffsetLo = sal::static_int_cast<DWORD>(uOffset & 0xFFFFFFFF);
+
+ *ppAddr = ::MapViewOfFile( aMap.m_handle, FILE_MAP_READ, dwOffsetHi, dwOffsetLo, nLength );
+ if (0 == *ppAddr)
+ return oslTranslateFileError( GetLastError() );
+
+ if (uFlags & osl_File_MapFlag_RandomAccess)
+ {
+ // Determine memory pagesize.
+ SYSTEM_INFO info;
+ ::GetSystemInfo( &info );
+ DWORD const dwPageSize = info.dwPageSize;
+
+ /*
+ * Pagein, touching first byte of each memory page.
+ * Note: volatile disables optimizing the loop away.
+ */
+ BYTE * pData (reinterpret_cast<BYTE*>(*ppAddr));
+ SIZE_T nSize (nLength);
+
+ volatile BYTE c = 0;
+ while (nSize > dwPageSize)
+ {
+ c ^= pData[0];
+ pData += dwPageSize;
+ nSize -= dwPageSize;
+ }
+ if (nSize > 0)
+ {
+ c ^= pData[0];
+ pData += nSize;
+ nSize -= nSize;
+ }
+ }
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_unmapFile(void* pAddr, sal_uInt64 /* uLength */)
+{
+ if (0 == pAddr)
+ return osl_File_E_INVAL;
+
+ if (!::UnmapViewOfFile (pAddr))
+ return oslTranslateFileError( GetLastError() );
+
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_readLine(
+ oslFileHandle Handle,
+ sal_Sequence ** ppSequence)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == ppSequence))
+ return osl_File_E_INVAL;
+ sal_uInt64 uBytesRead = 0;
+
+ // read at current filepos; filepos += uBytesRead;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->readLineAt (
+ pImpl->m_filepos, ppSequence, &uBytesRead);
+ if (result == osl_File_E_None)
+ pImpl->m_filepos += uBytesRead;
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_readFile(
+ oslFileHandle Handle,
+ void * pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64 * pBytesRead)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead))
+ return osl_File_E_INVAL;
+
+ // read at current filepos; filepos += *pBytesRead;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->readFileAt (
+ pImpl->m_filepos, pBuffer, uBytesRequested, pBytesRead);
+ if (result == osl_File_E_None)
+ pImpl->m_filepos += *pBytesRead;
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_writeFile(
+ oslFileHandle Handle,
+ const void * pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64 * pBytesWritten )
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten))
+ return osl_File_E_INVAL;
+
+ // write at current filepos; filepos += *pBytesWritten;
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->writeFileAt (
+ pImpl->m_filepos, pBuffer, uBytesToWrite, pBytesWritten);
+ if (result == osl_File_E_None)
+ pImpl->m_filepos += *pBytesWritten;
+ return (result);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_readFileAt(
+ oslFileHandle Handle,
+ sal_uInt64 uOffset,
+ void* pBuffer,
+ sal_uInt64 uBytesRequested,
+ sal_uInt64* pBytesRead)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesRead))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
+ if (g_limit_longlong < uOffset)
+ return osl_File_E_OVERFLOW;
+ LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset);
+
+ // read at specified fileptr
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ return pImpl->readFileAt (nOffset, pBuffer, uBytesRequested, pBytesRead);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_writeFileAt(
+ oslFileHandle Handle,
+ sal_uInt64 uOffset,
+ const void* pBuffer,
+ sal_uInt64 uBytesToWrite,
+ sal_uInt64* pBytesWritten)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pBuffer) || (0 == pBytesWritten))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_SEEKABLE))
+ return osl_File_E_SPIPE;
+
+ static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
+ if (g_limit_longlong < uOffset)
+ return osl_File_E_OVERFLOW;
+ LONGLONG const nOffset = sal::static_int_cast< LONGLONG >(uOffset);
+
+ // write at specified fileptr
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ return pImpl->writeFileAt (nOffset, pBuffer, uBytesToWrite, pBytesWritten);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_isEndOfFile (oslFileHandle Handle, sal_Bool *pIsEOF)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pIsEOF))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pIsEOF = (pImpl->getPos() == pImpl->getSize());
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_getFilePos(oslFileHandle Handle, sal_uInt64 *pPos)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pPos))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pPos = pImpl->getPos();
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_setFilePos(oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uOffset)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
+ return osl_File_E_INVAL;
+
+ static sal_Int64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
+ if (g_limit_longlong < uOffset)
+ return osl_File_E_OVERFLOW;
+ LONGLONG nPos = 0, nOffset = sal::static_int_cast< LONGLONG >(uOffset);
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ switch (uHow)
+ {
+ case osl_Pos_Absolut:
+ if (0 > nOffset)
+ return osl_File_E_INVAL;
+ break;
+
+ case osl_Pos_Current:
+ nPos = sal::static_int_cast< LONGLONG >(pImpl->getPos());
+ if ((0 > nOffset) && (-1*nOffset > nPos))
+ return osl_File_E_INVAL;
+ if (g_limit_longlong < nPos + nOffset)
+ return osl_File_E_OVERFLOW;
+ break;
+
+ case osl_Pos_End:
+ nPos = sal::static_int_cast< LONGLONG >(pImpl->getSize());
+ if ((0 > nOffset) && (-1*nOffset > nPos))
+ return osl_File_E_INVAL;
+ if (g_limit_longlong < nPos + nOffset)
+ return osl_File_E_OVERFLOW;
+ break;
+
+ default:
+ return osl_File_E_INVAL;
+ }
+
+ return pImpl->setPos (nPos + nOffset);
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_getFileSize (oslFileHandle Handle, sal_uInt64 *pSize)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile) || (0 == pSize))
+ return osl_File_E_INVAL;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ *pSize = pImpl->getSize();
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError
+SAL_CALL osl_setFileSize (oslFileHandle Handle, sal_uInt64 uSize)
+{
+ FileHandle_Impl * pImpl = static_cast<FileHandle_Impl*>(Handle);
+
+ if ((0 == pImpl) || !IsValidHandle(pImpl->m_hFile))
+ return osl_File_E_INVAL;
+ if (0 == (pImpl->m_state & FileHandle_Impl::STATE_WRITEABLE))
+ return osl_File_E_BADF;
+
+ static sal_uInt64 const g_limit_longlong = std::numeric_limits< LONGLONG >::max();
+ if (g_limit_longlong < uSize)
+ return osl_File_E_OVERFLOW;
+
+ FileHandle_Impl::Guard lock (&(pImpl->m_mutex));
+ oslFileError result = pImpl->syncFile();
+ if (result != osl_File_E_None)
+ return (result);
+ pImpl->m_bufptr = -1, pImpl->m_buflen = 0;
+
+ return pImpl->setSize (uSize);
+}
+
+//##################################################################
+// File handling functions
+//##################################################################
+
+//#############################################
+oslFileError SAL_CALL osl_removeFile( rtl_uString* strPath )
+{
+ rtl_uString *strSysPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ if ( DeleteFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
+ error = osl_File_E_None;
+ else
+ error = oslTranslateFileError( GetLastError() );
+
+ rtl_uString_release( strSysPath );
+ }
+ return error;
+}
+
+//#############################################
+#define osl_File_CopyRecursive 0x0001
+#define osl_File_CopyOverwrite 0x0002
+
+oslFileError SAL_CALL osl_copyFile( rtl_uString* strPath, rtl_uString *strDestPath )
+{
+ rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath ));
+ LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath ));
+
+ if ( CopyFile( src, dst, FALSE ) )
+ error = osl_File_E_None;
+ else
+ error = oslTranslateFileError( GetLastError() );
+ }
+
+ if ( strSysPath )
+ rtl_uString_release( strSysPath );
+ if ( strSysDestPath )
+ rtl_uString_release( strSysDestPath );
+
+ return error;
+}
+
+//#############################################
+oslFileError SAL_CALL osl_moveFile( rtl_uString* strPath, rtl_uString *strDestPath )
+{
+ rtl_uString *strSysPath = NULL, *strSysDestPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ error = _osl_getSystemPathFromFileURL( strDestPath, &strSysDestPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ LPCTSTR src = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath ));
+ LPCTSTR dst = reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysDestPath ));
+
+ if ( MoveFileEx( src, dst, MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING ) )
+ error = osl_File_E_None;
+ else
+ error = oslTranslateFileError( GetLastError() );
+ }
+
+ if ( strSysPath )
+ rtl_uString_release( strSysPath );
+ if ( strSysDestPath )
+ rtl_uString_release( strSysDestPath );
+
+ return error;
+}
diff --git a/sal/osl/w32/file_dirvol.cxx b/sal/osl/w32/file_dirvol.cxx
new file mode 100644
index 000000000000..09bdec7988c3
--- /dev/null
+++ b/sal/osl/w32/file_dirvol.cxx
@@ -0,0 +1,1867 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT_0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "osl/file.h"
+
+#include "file_url.h"
+#include "file_error.h"
+
+#include "path_helper.hxx"
+
+#include "osl/diagnose.h"
+#include "osl/time.h"
+#include "rtl/alloc.h"
+#include "rtl/ustring.hxx"
+
+#include <tchar.h>
+#ifdef __MINGW32__
+#include <ctype.h>
+#endif
+
+//#####################################################
+#define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
+
+static const wchar_t UNC_PREFIX[] = L"\\\\";
+static const wchar_t BACKSLASH = '\\';
+static const wchar_t SLASH = '/';
+
+//#####################################################
+extern "C" BOOL TimeValueToFileTime(const TimeValue *cpTimeVal, FILETIME *pFTime)
+{
+ SYSTEMTIME BaseSysTime;
+ FILETIME BaseFileTime;
+ FILETIME FTime;
+ __int64 localTime;
+ BOOL fSuccess = FALSE;
+
+ BaseSysTime.wYear = 1970;
+ BaseSysTime.wMonth = 1;
+ BaseSysTime.wDayOfWeek = 0;
+ BaseSysTime.wDay = 1;
+ BaseSysTime.wHour = 0;
+ BaseSysTime.wMinute = 0;
+ BaseSysTime.wSecond = 0;
+ BaseSysTime.wMilliseconds = 0;
+
+ if (cpTimeVal==NULL)
+ return fSuccess;
+
+ if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
+ {
+ __int64 timeValue;
+ localTime=cpTimeVal->Seconds*(__int64)10000000+cpTimeVal->Nanosec/100;
+ *(__int64 *)&FTime=localTime;
+ fSuccess = 0 <= (timeValue= *((__int64 *)&BaseFileTime) + *((__int64 *) &FTime));
+ if (fSuccess)
+ *(__int64 *)pFTime=timeValue;
+ }
+ return fSuccess;
+}
+
+//#####################################################
+extern "C" BOOL FileTimeToTimeValue(const FILETIME *cpFTime, TimeValue *pTimeVal)
+{
+ SYSTEMTIME BaseSysTime;
+ FILETIME BaseFileTime;
+ BOOL fSuccess = FALSE; /* Assume failure */
+
+ BaseSysTime.wYear = 1970;
+ BaseSysTime.wMonth = 1;
+ BaseSysTime.wDayOfWeek = 0;
+ BaseSysTime.wDay = 1;
+ BaseSysTime.wHour = 0;
+ BaseSysTime.wMinute = 0;
+ BaseSysTime.wSecond = 0;
+ BaseSysTime.wMilliseconds = 0;
+
+ if ( SystemTimeToFileTime(&BaseSysTime, &BaseFileTime) )
+ {
+ __int64 Value;
+
+ fSuccess = 0 <= (Value = *((__int64 *)cpFTime) - *((__int64 *)&BaseFileTime));
+
+ if ( fSuccess )
+ {
+ pTimeVal->Seconds = (unsigned long) (Value / 10000000L);
+ pTimeVal->Nanosec = (unsigned long)((Value % 10000000L) * 100);
+ }
+ }
+ return fSuccess;
+}
+
+//#####################################################
+namespace /* private */
+{
+ //#####################################################
+ struct Component
+ {
+ Component() :
+ begin_(0), end_(0)
+ {}
+
+ bool isPresent() const
+ { return (static_cast<sal_IntPtr>(end_ - begin_) > 0); }
+
+ const sal_Unicode* begin_;
+ const sal_Unicode* end_;
+ };
+
+ //#####################################################
+ struct UNCComponents
+ {
+ Component server_;
+ Component share_;
+ Component resource_;
+ };
+
+ //#####################################################
+ inline bool is_UNC_path(const sal_Unicode* path)
+ { return (0 == wcsncmp(UNC_PREFIX, reinterpret_cast<LPCWSTR>(path), ELEMENTS_OF_ARRAY(UNC_PREFIX) - 1)); }
+
+ //#####################################################
+ inline bool is_UNC_path(const rtl::OUString& path)
+ { return is_UNC_path(path.getStr()); }
+
+ //#####################################################
+ void parse_UNC_path(const sal_Unicode* path, UNCComponents* puncc)
+ {
+ OSL_PRECOND(is_UNC_path(path), "Precondition violated: No UNC path");
+ OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) != -1, "Path must not contain slashes");
+
+ const sal_Unicode* pend = path + rtl_ustr_getLength(path);
+ const sal_Unicode* ppos = path + 2;
+
+ puncc->server_.begin_ = ppos;
+ while ((ppos < pend) && (*ppos != BACKSLASH))
+ ppos++;
+
+ puncc->server_.end_ = ppos;
+
+ if (BACKSLASH == *ppos)
+ {
+ puncc->share_.begin_ = ++ppos;
+ while ((ppos < pend) && (*ppos != BACKSLASH))
+ ppos++;
+
+ puncc->share_.end_ = ppos;
+
+ if (BACKSLASH == *ppos)
+ {
+ puncc->resource_.begin_ = ++ppos;
+ while (ppos < pend)
+ ppos++;
+
+ puncc->resource_.end_ = ppos;
+ }
+ }
+
+ OSL_POSTCOND(puncc->server_.isPresent() && puncc->share_.isPresent(), \
+ "Postcondition violated: Invalid UNC path detected");
+ }
+
+ //#####################################################
+ void parse_UNC_path(const rtl::OUString& path, UNCComponents* puncc)
+ { parse_UNC_path(path.getStr(), puncc); }
+
+
+ //#####################################################
+ bool has_path_parent(const sal_Unicode* path)
+ {
+ // Has the given path a parent or are we already there,
+ // e.g. 'c:\' or '\\server\share\'?
+
+ bool has_parent = false;
+ if (is_UNC_path(path))
+ {
+ UNCComponents unc_comp;
+ parse_UNC_path(path, &unc_comp);
+ has_parent = unc_comp.resource_.isPresent();
+ }
+ else
+ {
+ has_parent = !osl::systemPathIsLogicalDrivePattern(path);
+ }
+ return has_parent;
+ }
+
+ //#####################################################
+ inline bool has_path_parent(const rtl::OUString& path)
+ { return has_path_parent(path.getStr()); }
+
+} // end namespace private
+
+//#####################################################
+// volume handling functions
+//#####################################################
+
+//#####################################################
+oslFileError SAL_CALL osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ if ( Handle )
+ return osl_File_E_None;
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ if ( Handle )
+ return osl_File_E_None;
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ if ( Handle )
+ {
+ rtl_uString_acquire( (rtl_uString *)Handle );
+ return osl_File_E_None;
+ }
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ if ( Handle )
+ {
+ rtl_uString_release( (rtl_uString *)Handle );
+ return osl_File_E_None;
+ }
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
+{
+ if ( Handle && pstrPath )
+ {
+ rtl_uString_assign( pstrPath, (rtl_uString *)Handle );
+ return osl_File_E_None;
+ }
+ else
+ return osl_File_E_INVAL;
+}
+
+//##################################################################
+// directory handling functions
+//##################################################################
+
+#define DIRECTORYITEM_DRIVE 0
+#define DIRECTORYITEM_FILE 1
+#define DIRECTORYITEM_SERVER 2
+
+struct DirectoryItem_Impl
+{
+ UINT uType;
+ union {
+ WIN32_FIND_DATA FindData;
+ TCHAR cDriveString[MAX_PATH];
+ };
+ rtl_uString* m_pFullPath;
+ BOOL bFullPathNormalized;
+ int nRefCount;
+};
+
+//#####################################################
+
+#define DIRECTORYTYPE_LOCALROOT 0
+#define DIRECTORYTYPE_NETROOT 1
+#define DIRECTORYTYPE_NETRESORCE 2
+#define DIRECTORYTYPE_FILESYSTEM 3
+
+struct Directory_Impl
+{
+ UINT uType;
+ union {
+ HANDLE hDirectory;
+ HANDLE hEnumDrives;
+ };
+ rtl_uString* m_pDirectoryPath;
+};
+
+//#####################################################
+
+typedef struct tagDRIVEENUM
+{
+ LPCTSTR lpIdent;
+ TCHAR cBuffer[/*('Z' - 'A' + 1) * sizeof("A:\\") + 1*/256];
+ LPCTSTR lpCurrent;
+} DRIVEENUM, * PDRIVEENUM, FAR * LPDRIVEENUM;
+
+//#####################################################
+
+static HANDLE WINAPI OpenLogicalDrivesEnum(void)
+{
+ LPDRIVEENUM pEnum = (LPDRIVEENUM)HeapAlloc( GetProcessHeap(), 0, sizeof(DRIVEENUM) );
+ if ( pEnum )
+ {
+ DWORD dwNumCopied = GetLogicalDriveStrings( (sizeof(pEnum->cBuffer) - 1) / sizeof(TCHAR), pEnum->cBuffer );
+
+ if ( dwNumCopied && dwNumCopied < sizeof(pEnum->cBuffer) / sizeof(TCHAR) )
+ {
+ pEnum->lpCurrent = pEnum->cBuffer;
+ pEnum->lpIdent = L"tagDRIVEENUM";
+ }
+ else
+ {
+ HeapFree( GetProcessHeap(), 0, pEnum );
+ pEnum = NULL;
+ }
+ }
+ return pEnum ? (HANDLE)pEnum : INVALID_HANDLE_VALUE;
+}
+
+//#####################################################
+static BOOL WINAPI EnumLogicalDrives(HANDLE hEnum, LPTSTR lpBuffer)
+{
+ BOOL fSuccess = FALSE;
+ LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
+
+ if ( pEnum )
+ {
+ int nLen = _tcslen( pEnum->lpCurrent );
+
+ if ( nLen )
+ {
+ CopyMemory( lpBuffer, pEnum->lpCurrent, (nLen + 1) * sizeof(TCHAR) );
+ pEnum->lpCurrent += nLen + 1;
+ fSuccess = TRUE;
+ }
+ else
+ SetLastError( ERROR_NO_MORE_FILES );
+ }
+ else
+ SetLastError( ERROR_INVALID_HANDLE );
+
+ return fSuccess;
+}
+
+//#####################################################
+static BOOL WINAPI CloseLogicalDrivesEnum(HANDLE hEnum)
+{
+ BOOL fSuccess = FALSE;
+ LPDRIVEENUM pEnum = (LPDRIVEENUM)hEnum;
+
+ if ( pEnum )
+ {
+ HeapFree( GetProcessHeap(), 0, pEnum );
+ fSuccess = TRUE;
+ }
+ else
+ SetLastError( ERROR_INVALID_HANDLE );
+
+ return fSuccess;
+}
+
+//#####################################################
+typedef struct tagDIRECTORY
+{
+ HANDLE hFind;
+ WIN32_FIND_DATA aFirstData;
+} DIRECTORY, *PDIRECTORY, FAR *LPDIRECTORY;
+
+//#####################################################
+static HANDLE WINAPI OpenDirectory( rtl_uString* pPath)
+{
+ LPDIRECTORY pDirectory = NULL;
+
+ if ( pPath )
+ {
+ sal_uInt32 nLen = rtl_uString_getLength( pPath );
+ if ( nLen )
+ {
+ TCHAR* pSuffix = 0;
+ sal_uInt32 nSuffLen = 0;
+
+ if ( pPath->buffer[nLen - 1] != L'\\' )
+ {
+ pSuffix = L"\\*.*";
+ nSuffLen = 4;
+ }
+ else
+ {
+ pSuffix = L"*.*";
+ nSuffLen = 3;
+ }
+
+ TCHAR* szFileMask = reinterpret_cast< TCHAR* >( rtl_allocateMemory( sizeof( TCHAR ) * ( nLen + nSuffLen + 1 ) ) );
+
+ _tcscpy( szFileMask, reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pPath ) ) );
+ _tcscat( szFileMask, pSuffix );
+
+ pDirectory = (LPDIRECTORY)HeapAlloc(GetProcessHeap(), 0, sizeof(DIRECTORY));
+ pDirectory->hFind = FindFirstFile(szFileMask, &pDirectory->aFirstData);
+
+ if (!IsValidHandle(pDirectory->hFind))
+ {
+ if ( GetLastError() != ERROR_NO_MORE_FILES )
+ {
+ HeapFree(GetProcessHeap(), 0, pDirectory);
+ pDirectory = NULL;
+ }
+ }
+ }
+ }
+
+ return (HANDLE)pDirectory;
+}
+
+//#####################################################
+BOOL WINAPI EnumDirectory(HANDLE hDirectory, LPWIN32_FIND_DATA pFindData)
+{
+ BOOL fSuccess = FALSE;
+ LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
+
+ if ( pDirectory )
+ {
+ BOOL fValid;
+
+ do
+ {
+ if ( pDirectory->aFirstData.cFileName[0] )
+ {
+ *pFindData = pDirectory->aFirstData;
+ fSuccess = TRUE;
+ pDirectory->aFirstData.cFileName[0] = 0;
+ }
+ else if ( IsValidHandle( pDirectory->hFind ) )
+ fSuccess = FindNextFile( pDirectory->hFind, pFindData );
+ else
+ {
+ fSuccess = FALSE;
+ SetLastError( ERROR_NO_MORE_FILES );
+ }
+
+ fValid = fSuccess && _tcscmp( TEXT("."), pFindData->cFileName ) != 0 && _tcscmp( TEXT(".."), pFindData->cFileName ) != 0;
+
+ } while( fSuccess && !fValid );
+ }
+ else
+ SetLastError( ERROR_INVALID_HANDLE );
+
+ return fSuccess;
+}
+
+//#####################################################
+static BOOL WINAPI CloseDirectory(HANDLE hDirectory)
+{
+ BOOL fSuccess = FALSE;
+ LPDIRECTORY pDirectory = (LPDIRECTORY)hDirectory;
+
+ if (pDirectory)
+ {
+ if (IsValidHandle(pDirectory->hFind))
+ fSuccess = FindClose(pDirectory->hFind);
+
+ fSuccess = HeapFree(GetProcessHeap(), 0, pDirectory) && fSuccess;
+ }
+ else
+ SetLastError(ERROR_INVALID_HANDLE);
+
+ return fSuccess;
+}
+
+//#####################################################
+static oslFileError osl_openLocalRoot(
+ rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
+{
+ rtl_uString *strSysPath = NULL;
+ oslFileError error;
+
+ if ( !pDirectory )
+ return osl_File_E_INVAL;
+
+ *pDirectory = NULL;
+
+ error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysPath, sal_False );
+ if ( osl_File_E_None == error )
+ {
+ Directory_Impl *pDirImpl;
+
+ pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory( sizeof(Directory_Impl)));
+ ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
+ rtl_uString_newFromString( &pDirImpl->m_pDirectoryPath, strSysPath );
+
+ /* Append backslash if neccessary */
+
+ /* @@@ToDo
+ use function ensure backslash
+ */
+ sal_uInt32 nLen = rtl_uString_getLength( pDirImpl->m_pDirectoryPath );
+ if ( nLen && pDirImpl->m_pDirectoryPath->buffer[nLen - 1] != L'\\' )
+ {
+ rtl_uString* pCurDir = 0;
+ rtl_uString* pBackSlash = 0;
+
+ rtl_uString_assign( &pCurDir, pDirImpl->m_pDirectoryPath );
+ rtl_uString_newFromAscii( &pBackSlash, "\\" );
+ rtl_uString_newConcat( &pDirImpl->m_pDirectoryPath, pCurDir, pBackSlash );
+ rtl_uString_release( pBackSlash );
+ rtl_uString_release( pCurDir );
+ }
+
+ pDirImpl->uType = DIRECTORYTYPE_LOCALROOT;
+ pDirImpl->hEnumDrives = OpenLogicalDrivesEnum();
+
+ /* @@@ToDo
+ Use IsValidHandle(...)
+ */
+ if ( pDirImpl->hEnumDrives != INVALID_HANDLE_VALUE )
+ {
+ *pDirectory = (oslDirectory)pDirImpl;
+ error = osl_File_E_None;
+ }
+ else
+ {
+ if ( pDirImpl )
+ {
+ if ( pDirImpl->m_pDirectoryPath )
+ {
+ rtl_uString_release( pDirImpl->m_pDirectoryPath );
+ pDirImpl->m_pDirectoryPath = 0;
+ }
+
+ rtl_freeMemory(pDirImpl);
+ pDirImpl = 0;
+ }
+
+ error = oslTranslateFileError( GetLastError() );
+ }
+
+ rtl_uString_release( strSysPath );
+ }
+ return error;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_openFileDirectory(
+ rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
+{
+ oslFileError error = osl_File_E_None;
+
+ if ( !pDirectory )
+ return osl_File_E_INVAL;
+ *pDirectory = NULL;
+
+ Directory_Impl *pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
+ ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
+ rtl_uString_newFromString( &pDirImpl->m_pDirectoryPath, strDirectoryPath );
+
+ /* Append backslash if neccessary */
+
+ /* @@@ToDo
+ use function ensure backslash
+ */
+ sal_uInt32 nLen = rtl_uString_getLength( pDirImpl->m_pDirectoryPath );
+ if ( nLen && pDirImpl->m_pDirectoryPath->buffer[nLen - 1] != L'\\' )
+ {
+ rtl_uString* pCurDir = 0;
+ rtl_uString* pBackSlash = 0;
+
+ rtl_uString_assign( &pCurDir, pDirImpl->m_pDirectoryPath );
+ rtl_uString_newFromAscii( &pBackSlash, "\\" );
+ rtl_uString_newConcat( &pDirImpl->m_pDirectoryPath, pCurDir, pBackSlash );
+ rtl_uString_release( pBackSlash );
+ rtl_uString_release( pCurDir );
+ }
+
+
+ pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM;
+ pDirImpl->hDirectory = OpenDirectory( pDirImpl->m_pDirectoryPath );
+
+ if ( !pDirImpl->hDirectory )
+ {
+ error = oslTranslateFileError( GetLastError() );
+
+ if ( pDirImpl->m_pDirectoryPath )
+ {
+ rtl_uString_release( pDirImpl->m_pDirectoryPath );
+ pDirImpl->m_pDirectoryPath = 0;
+ }
+
+ rtl_freeMemory(pDirImpl), pDirImpl = 0;
+ }
+
+ *pDirectory = (oslDirectory)(pDirImpl);
+ return error;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_openNetworkServer(
+ rtl_uString *strSysDirPath, oslDirectory *pDirectory)
+{
+ NETRESOURCEW aNetResource;
+ HANDLE hEnum;
+ DWORD dwError;
+
+ ZeroMemory( &aNetResource, sizeof(aNetResource) );
+
+ aNetResource.lpRemoteName = reinterpret_cast<LPWSTR>(strSysDirPath->buffer);
+
+ dwError = WNetOpenEnumW(
+ RESOURCE_GLOBALNET,
+ RESOURCETYPE_DISK,
+ RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER,
+ &aNetResource,
+ &hEnum );
+
+ if ( ERROR_SUCCESS == dwError )
+ {
+ Directory_Impl *pDirImpl;
+
+ pDirImpl = reinterpret_cast<Directory_Impl*>(rtl_allocateMemory(sizeof(Directory_Impl)));
+ ZeroMemory( pDirImpl, sizeof(Directory_Impl) );
+ pDirImpl->uType = DIRECTORYTYPE_NETROOT;
+ pDirImpl->hDirectory = hEnum;
+ *pDirectory = (oslDirectory)pDirImpl;
+ }
+ return oslTranslateFileError( dwError );
+}
+
+//#############################################
+static DWORD create_dir_with_callback(
+ rtl_uString * dir_path,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ // Create the specified directory and call the
+ // user specified callback function. On success
+ // the function returns ERROR_SUCCESS else a Win32 error code.
+
+ BOOL bCreated = FALSE;
+
+ bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( dir_path )), NULL );
+
+ if ( bCreated )
+ {
+ if (aDirectoryCreationCallbackFunc)
+ {
+ rtl::OUString url;
+ _osl_getFileURLFromSystemPath(dir_path, &(url.pData));
+ aDirectoryCreationCallbackFunc(pData, url.pData);
+ }
+ return ERROR_SUCCESS;
+ }
+ return GetLastError();
+}
+
+//#############################################
+static int path_make_parent(sal_Unicode* path)
+{
+ /* Cut off the last part of the given path to
+ get the parent only, e.g. 'c:\dir\subdir' ->
+ 'c:\dir' or '\\share\sub\dir' -> '\\share\sub'
+ @return The position where the path has been cut
+ off (this is the posistion of the last backslash).
+ If there are no more parents 0 will be returned,
+ e.g. 'c:\' or '\\Share' have no more parents */
+
+ OSL_PRECOND(rtl_ustr_indexOfChar(path, SLASH) != -1, "Path must not contain slashes");
+ OSL_PRECOND(has_path_parent(path), "Path must have a parent");
+
+ sal_Unicode* pos_last_backslash = path + rtl_ustr_lastIndexOfChar(path, BACKSLASH);
+ *pos_last_backslash = 0;
+ return (pos_last_backslash - path);
+}
+
+//#############################################
+static DWORD create_dir_recursively_(
+ rtl_uString * dir_path,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ OSL_PRECOND(
+ rtl_ustr_lastIndexOfChar_WithLength(dir_path->buffer, dir_path->length, BACKSLASH) != dir_path->length,
+ "Path must not end with a backslash");
+
+ DWORD w32_error = create_dir_with_callback(
+ dir_path, aDirectoryCreationCallbackFunc, pData);
+ if (w32_error == ERROR_SUCCESS)
+ return ERROR_SUCCESS;
+
+ if ((w32_error != ERROR_PATH_NOT_FOUND) || !has_path_parent(dir_path->buffer))
+ return w32_error;
+
+ int pos = path_make_parent(dir_path->buffer); // dir_path->buffer[pos] = 0, restore below
+
+ w32_error = create_dir_recursively_(
+ dir_path, aDirectoryCreationCallbackFunc, pData);
+
+ dir_path->buffer[pos] = BACKSLASH; // restore
+
+ if (ERROR_SUCCESS != w32_error)
+ return w32_error;
+
+ return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
+}
+
+//#############################################
+oslFileError SAL_CALL osl_createDirectoryPath(
+ rtl_uString* aDirectoryUrl,
+ oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
+ void* pData)
+{
+ if (aDirectoryUrl == NULL)
+ return osl_File_E_INVAL;
+
+ rtl::OUString sys_path;
+ oslFileError osl_error =
+ _osl_getSystemPathFromFileURL(aDirectoryUrl, &sys_path.pData, sal_False);
+
+ if (osl_error != osl_File_E_None)
+ return osl_error;
+
+ osl::systemPathRemoveSeparator(sys_path);
+
+ // const_cast because sys_path is a local copy
+ // which we want to modify inplace instead of
+ // coyp it into another buffer on the heap again
+ return oslTranslateFileError(create_dir_recursively_(
+ sys_path.pData, aDirectoryCreationCallbackFunc, pData));
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_createDirectory(rtl_uString* strPath)
+{
+ rtl_uString *strSysPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ BOOL bCreated = FALSE;
+
+ bCreated = CreateDirectoryW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strSysPath )), NULL );
+
+ if ( !bCreated )
+ {
+ /*@@@ToDo
+ The following case is a hack because the ucb or the webtop had some
+ problems with the error code that CreateDirectory returns in
+ case the path is only a logical drive, should be removed!
+ */
+
+ const sal_Unicode *pBuffer = rtl_uString_getStr( strSysPath );
+ sal_Int32 nLen = rtl_uString_getLength( strSysPath );
+
+ if (
+ ( ( pBuffer[0] >= 'A' && pBuffer[0] <= 'Z' ) ||
+ ( pBuffer[0] >= 'a' && pBuffer[0] <= 'z' ) ) &&
+ pBuffer[1] == ':' && ( nLen ==2 || ( nLen == 3 && pBuffer[2] == '\\' ) )
+ )
+ SetLastError( ERROR_ALREADY_EXISTS );
+
+ error = oslTranslateFileError( GetLastError() );
+ }
+
+ rtl_uString_release( strSysPath );
+ }
+ return error;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_removeDirectory(rtl_uString* strPath)
+{
+ rtl_uString *strSysPath = NULL;
+ oslFileError error = _osl_getSystemPathFromFileURL( strPath, &strSysPath, sal_False );
+
+ if ( osl_File_E_None == error )
+ {
+ if ( RemoveDirectory( reinterpret_cast<LPCTSTR>(rtl_uString_getStr( strSysPath )) ) )
+ error = osl_File_E_None;
+ else
+ error = oslTranslateFileError( GetLastError() );
+
+ rtl_uString_release( strSysPath );
+ }
+ return error;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_openDirectory(rtl_uString *strDirectoryPath, oslDirectory *pDirectory)
+{
+ oslFileError error;
+
+ if ( 0 == rtl_ustr_ascii_compareIgnoreAsciiCase( strDirectoryPath->buffer, "file:///" ) )
+ error = osl_openLocalRoot( strDirectoryPath, pDirectory );
+ else
+ {
+ rtl_uString *strSysDirectoryPath = NULL;
+ DWORD dwPathType;
+
+ error = _osl_getSystemPathFromFileURL( strDirectoryPath, &strSysDirectoryPath, sal_False );
+
+ if ( osl_File_E_None != error )
+ return error;
+
+ dwPathType = IsValidFilePath( strSysDirectoryPath, NULL, VALIDATEPATH_NORMAL, NULL );
+
+ if ( dwPathType & PATHTYPE_IS_SERVER )
+ {
+ error = osl_openNetworkServer( strSysDirectoryPath, pDirectory );
+ }
+ else
+ error = osl_openFileDirectory( strSysDirectoryPath, pDirectory );
+
+ rtl_uString_release( strSysDirectoryPath );
+ }
+ return error;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getNextNetResource(
+ oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+ DirectoryItem_Impl *pItemImpl = NULL;
+ BYTE buffer[16384];
+ LPNETRESOURCEW lpNetResource = (LPNETRESOURCEW)buffer;
+ DWORD dwError, dwCount, dwBufSize;
+
+ uHint = uHint; /* to get no warning */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+ *pItem = NULL;
+
+ if ( !pDirImpl )
+ return osl_File_E_INVAL;
+
+ dwCount = 1;
+ dwBufSize = sizeof(buffer);
+ dwError = WNetEnumResource( pDirImpl->hDirectory, &dwCount, lpNetResource, &dwBufSize );
+
+ switch ( dwError )
+ {
+ case NO_ERROR:
+ case ERROR_MORE_DATA:
+ {
+ pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+ if ( !pItemImpl )
+ return osl_File_E_NOMEM;
+
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_DRIVE;
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+
+ wcscpy( pItemImpl->cDriveString, lpNetResource->lpRemoteName );
+
+ *pItem = pItemImpl;
+ }
+ return osl_File_E_None;
+ case ERROR_NO_MORE_ITEMS:
+ return osl_File_E_NOENT;
+ default:
+ return oslTranslateFileError( dwError );
+ }
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getNextDrive(
+ oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint )
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+ DirectoryItem_Impl *pItemImpl = NULL;
+ BOOL fSuccess;
+
+ uHint = uHint; /* avoid warnings */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+ *pItem = NULL;
+
+ if ( !pDirImpl )
+ return osl_File_E_INVAL;
+
+ pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+ if ( !pItemImpl )
+ return osl_File_E_NOMEM;
+
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_DRIVE;
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+ fSuccess = EnumLogicalDrives( pDirImpl->hEnumDrives, pItemImpl->cDriveString );
+
+ if ( fSuccess )
+ {
+ *pItem = pItemImpl;
+ return osl_File_E_None;
+ }
+ else
+ {
+ if ( pItemImpl->m_pFullPath )
+ {
+ rtl_uString_release( pItemImpl->m_pFullPath );
+ pItemImpl->m_pFullPath = 0;
+ }
+
+ rtl_freeMemory( pItemImpl );
+ return oslTranslateFileError( GetLastError() );
+ }
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getNextFileItem(
+ oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+ DirectoryItem_Impl *pItemImpl = NULL;
+ BOOL fFound;
+
+ uHint = uHint; /* avoid warnings */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+ *pItem = NULL;
+
+ if ( !pDirImpl )
+ return osl_File_E_INVAL;
+
+ pItemImpl = reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+ if ( !pItemImpl )
+ return osl_File_E_NOMEM;
+
+ memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) );
+ fFound = EnumDirectory( pDirImpl->hDirectory, &pItemImpl->FindData );
+
+ if ( fFound )
+ {
+ pItemImpl->uType = DIRECTORYITEM_FILE;
+ pItemImpl->nRefCount = 1;
+
+ rtl_uString* pTmpFileName = 0;
+ rtl_uString_newFromStr( &pTmpFileName, reinterpret_cast<const sal_Unicode *>(pItemImpl->FindData.cFileName) );
+ rtl_uString_newConcat( &pItemImpl->m_pFullPath, pDirImpl->m_pDirectoryPath, pTmpFileName );
+ rtl_uString_release( pTmpFileName );
+
+ pItemImpl->bFullPathNormalized = FALSE;
+ *pItem = (oslDirectoryItem)pItemImpl;
+ return osl_File_E_None;
+ }
+ else
+ {
+ if ( pItemImpl->m_pFullPath )
+ {
+ rtl_uString_release( pItemImpl->m_pFullPath );
+ pItemImpl->m_pFullPath = 0;
+ }
+
+ rtl_freeMemory( pItemImpl );
+ return oslTranslateFileError( GetLastError() );
+ }
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getNextDirectoryItem(
+ oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint)
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+
+ /* Assume failure */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+ *pItem = NULL;
+
+ if ( !pDirImpl )
+ return osl_File_E_INVAL;
+
+ switch ( pDirImpl->uType )
+ {
+ case DIRECTORYTYPE_LOCALROOT:
+ return osl_getNextDrive( Directory, pItem, uHint );
+ case DIRECTORYTYPE_NETROOT:
+ return osl_getNextNetResource( Directory, pItem, uHint );
+ case DIRECTORYTYPE_FILESYSTEM:
+ return osl_getNextFileItem( Directory, pItem, uHint );
+ default:
+ return osl_File_E_INVAL;
+ }
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_closeDirectory(oslDirectory Directory)
+{
+ Directory_Impl *pDirImpl = (Directory_Impl *)Directory;
+ oslFileError eError = osl_File_E_INVAL;
+
+ if ( pDirImpl )
+ {
+ switch ( pDirImpl->uType )
+ {
+ case DIRECTORYTYPE_FILESYSTEM:
+ eError = CloseDirectory( pDirImpl->hDirectory ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
+ break;
+ case DIRECTORYTYPE_LOCALROOT:
+ eError = CloseLogicalDrivesEnum( pDirImpl->hEnumDrives ) ? osl_File_E_None : oslTranslateFileError( GetLastError() );
+ break;
+ case DIRECTORYTYPE_NETROOT:
+ {
+ DWORD err = WNetCloseEnum(pDirImpl->hDirectory);
+ eError = (err == NO_ERROR) ? osl_File_E_None : oslTranslateFileError(err);
+ }
+ break;
+ default:
+ OSL_ENSURE( 0, "Invalid directory type" );
+ break;
+ }
+
+ if ( pDirImpl->m_pDirectoryPath )
+ {
+ rtl_uString_release( pDirImpl->m_pDirectoryPath );
+ pDirImpl->m_pDirectoryPath = 0;
+ }
+
+ rtl_freeMemory(pDirImpl);
+ }
+ return eError;
+}
+
+//#####################################################
+/* Different types of paths */
+typedef enum _PATHTYPE
+{
+ PATHTYPE_SYNTAXERROR = 0,
+ PATHTYPE_NETROOT,
+ PATHTYPE_NETSERVER,
+ PATHTYPE_VOLUME,
+ PATHTYPE_FILE
+} PATHTYPE;
+
+oslFileError SAL_CALL osl_getDirectoryItem(rtl_uString *strFilePath, oslDirectoryItem *pItem)
+{
+ oslFileError error = osl_File_E_None;
+ rtl_uString* strSysFilePath = NULL;
+ PATHTYPE type = PATHTYPE_FILE;
+ DWORD dwPathType;
+
+ /* Assume failure */
+
+ if ( !pItem )
+ return osl_File_E_INVAL;
+
+ *pItem = NULL;
+
+
+ error = _osl_getSystemPathFromFileURL( strFilePath, &strSysFilePath, sal_False );
+
+ if ( osl_File_E_None != error )
+ return error;
+
+ dwPathType = IsValidFilePath( strSysFilePath, NULL, VALIDATEPATH_NORMAL, NULL );
+
+ if ( dwPathType & PATHTYPE_IS_VOLUME )
+ type = PATHTYPE_VOLUME;
+ else if ( dwPathType & PATHTYPE_IS_SERVER )
+ type = PATHTYPE_NETSERVER;
+ else
+ type = PATHTYPE_FILE;
+
+ switch ( type )
+ {
+ case PATHTYPE_NETSERVER:
+ {
+ DirectoryItem_Impl* pItemImpl =
+ reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+
+ if ( !pItemImpl )
+ error = osl_File_E_NOMEM;
+
+ if ( osl_File_E_None == error )
+ {
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_SERVER;
+
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+ rtl_uString_newFromString( &pItemImpl->m_pFullPath, strSysFilePath );
+
+ // Assign a title anyway
+ {
+ int iSrc = 2;
+ int iDst = 0;
+
+ while( iSrc < strSysFilePath->length && strSysFilePath->buffer[iSrc] && strSysFilePath->buffer[iSrc] != '\\' )
+ {
+ pItemImpl->FindData.cFileName[iDst++] = strSysFilePath->buffer[iSrc++];
+ }
+ }
+
+ *pItem = pItemImpl;
+ }
+ }
+ break;
+ case PATHTYPE_VOLUME:
+ {
+ DirectoryItem_Impl* pItemImpl =
+ reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+
+ if ( !pItemImpl )
+ error = osl_File_E_NOMEM;
+
+ if ( osl_File_E_None == error )
+ {
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ pItemImpl->uType = DIRECTORYITEM_DRIVE;
+
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+
+ _tcscpy( pItemImpl->cDriveString, reinterpret_cast<LPCTSTR>(strSysFilePath->buffer) );
+ pItemImpl->cDriveString[0] = _toupper( pItemImpl->cDriveString[0] );
+
+ if ( pItemImpl->cDriveString[_tcslen(pItemImpl->cDriveString) - 1] != '\\' )
+ _tcscat( pItemImpl->cDriveString, TEXT( "\\" ) );
+
+ *pItem = pItemImpl;
+ }
+ }
+ break;
+ case PATHTYPE_SYNTAXERROR:
+ case PATHTYPE_NETROOT:
+ case PATHTYPE_FILE:
+ {
+ HANDLE hFind;
+ WIN32_FIND_DATA aFindData;
+
+ if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' )
+ rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 );
+
+ hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(strSysFilePath)), &aFindData );
+
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ DirectoryItem_Impl *pItemImpl =
+ reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl)));
+
+ ZeroMemory( pItemImpl, sizeof(DirectoryItem_Impl) );
+ osl_acquireDirectoryItem( (oslDirectoryItem)pItemImpl );
+
+ CopyMemory( &pItemImpl->FindData, &aFindData, sizeof(WIN32_FIND_DATA) );
+ rtl_uString_newFromString( &pItemImpl->m_pFullPath, strSysFilePath );
+
+ // MT: This costs 600ms startup time on fast v60x!
+ // GetCaseCorrectPathName( pItemImpl->szFullPath, pItemImpl->szFullPath, sizeof(pItemImpl->szFullPath) );
+
+ pItemImpl->uType = DIRECTORYITEM_FILE;
+ *pItem = pItemImpl;
+ FindClose( hFind );
+ }
+ else
+ error = oslTranslateFileError( GetLastError() );
+ }
+ break;
+ }
+
+ if ( strSysFilePath )
+ rtl_uString_release( strSysFilePath );
+
+ return error;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ pItemImpl->nRefCount++;
+ return osl_File_E_None;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ if ( ! --pItemImpl->nRefCount )
+ {
+ if ( pItemImpl->m_pFullPath )
+ {
+ rtl_uString_release( pItemImpl->m_pFullPath );
+ pItemImpl->m_pFullPath = 0;
+ }
+
+ rtl_freeMemory( pItemImpl );
+ }
+
+ return osl_File_E_None;
+}
+
+//#####################################################
+// volume / file info handling functions
+//#####################################################
+
+//#####################################################
+static inline bool is_floppy_A_present()
+{ return (GetLogicalDrives() & 1); }
+
+//#####################################################
+static inline bool is_floppy_B_present()
+{ return (GetLogicalDrives() & 2); }
+
+//#####################################################
+bool is_floppy_volume_mount_point(const rtl::OUString& path)
+{
+ // determines if a volume mount point shows to a floppy
+ // disk by comparing the unique volume names
+ static const LPCWSTR FLOPPY_A = L"A:\\";
+ static const LPCWSTR FLOPPY_B = L"B:\\";
+
+ rtl::OUString p(path);
+ osl::systemPathEnsureSeparator(p);
+
+ TCHAR vn[51];
+ if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
+ {
+ TCHAR vnfloppy[51];
+ if (is_floppy_A_present() &&
+ GetVolumeNameForVolumeMountPoint(FLOPPY_A, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
+ (0 == wcscmp(vn, vnfloppy)))
+ return true;
+
+ if (is_floppy_B_present() &&
+ GetVolumeNameForVolumeMountPoint(FLOPPY_B, vnfloppy, ELEMENTS_OF_ARRAY(vnfloppy)) &&
+ (0 == wcscmp(vn, vnfloppy)))
+ return true;
+ }
+ return false;
+}
+
+//################################################
+static bool is_floppy_drive(const rtl::OUString& path)
+{
+ static const LPCWSTR FLOPPY_DRV_LETTERS = TEXT("AaBb");
+
+ // we must take into account that even a floppy
+ // drive may be mounted to a directory so checking
+ // for the drive letter alone is not sufficient
+ // we must compare the unique volume name with
+ // that of the available floppy disks
+
+ const sal_Unicode* pszPath = path.getStr();
+ return ((wcschr(FLOPPY_DRV_LETTERS, pszPath[0]) && (L':' == pszPath[1])) || is_floppy_volume_mount_point(path));
+}
+
+//#####################################################
+static bool is_volume_mount_point(const rtl::OUString& path)
+{
+ rtl::OUString p(path);
+ osl::systemPathRemoveSeparator(p);
+
+ bool is_volume_root = false;
+
+ if (!is_floppy_drive(p))
+ {
+ DWORD fattr = GetFileAttributes(reinterpret_cast<LPCTSTR>(p.getStr()));
+
+ if ((INVALID_FILE_ATTRIBUTES != fattr) &&
+ (FILE_ATTRIBUTE_REPARSE_POINT & fattr))
+ {
+ WIN32_FIND_DATA find_data;
+ HANDLE h_find = FindFirstFile(reinterpret_cast<LPCTSTR>(p.getStr()), &find_data);
+
+ if (IsValidHandle(h_find) &&
+ (FILE_ATTRIBUTE_REPARSE_POINT & find_data.dwFileAttributes) &&
+ (IO_REPARSE_TAG_MOUNT_POINT == find_data.dwReserved0))
+ {
+ is_volume_root = true;
+ }
+ if (IsValidHandle(h_find))
+ FindClose(h_find);
+ }
+ }
+ return is_volume_root;
+}
+
+//#############################################
+static UINT get_volume_mount_point_drive_type(const rtl::OUString& path)
+{
+ if (0 == path.getLength())
+ return GetDriveType(NULL);
+
+ rtl::OUString p(path);
+ osl::systemPathEnsureSeparator(p);
+
+ TCHAR vn[51];
+ if (GetVolumeNameForVolumeMountPoint(reinterpret_cast<LPCTSTR>(p.getStr()), vn, ELEMENTS_OF_ARRAY(vn)))
+ return GetDriveType(vn);
+
+ return DRIVE_NO_ROOT_DIR;
+}
+
+//#############################################
+static inline bool is_drivetype_request(sal_uInt32 field_mask)
+{
+ return (field_mask & osl_VolumeInfo_Mask_Attributes);
+}
+
+//#############################################
+static oslFileError osl_get_drive_type(
+ const rtl::OUString& path, oslVolumeInfo* pInfo)
+{
+ // GetDriveType fails on empty volume mount points
+ // see Knowledge Base Q244089
+ UINT drive_type;
+ if (is_volume_mount_point(path))
+ drive_type = get_volume_mount_point_drive_type(path);
+ else
+ drive_type = GetDriveType(reinterpret_cast<LPCTSTR>(path.getStr()));
+
+ if (DRIVE_NO_ROOT_DIR == drive_type)
+ return oslTranslateFileError(ERROR_INVALID_DRIVE);
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+
+ switch (drive_type)
+ {
+ case DRIVE_CDROM:
+ pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable;
+ break;
+ case DRIVE_REMOVABLE:
+ pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
+ if (is_floppy_drive(path))
+ pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk;
+ break;
+ case DRIVE_FIXED:
+ pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk;
+ break;
+ case DRIVE_RAMDISK:
+ pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk;
+ break;
+ case DRIVE_REMOTE:
+ pInfo->uAttributes |= osl_Volume_Attribute_Remote;
+ break;
+ case DRIVE_UNKNOWN:
+ pInfo->uAttributes = 0;
+ break;
+ default:
+ pInfo->uValidFields &= ~osl_VolumeInfo_Mask_Attributes;
+ pInfo->uAttributes = 0;
+ break;
+ }
+ return osl_File_E_None;
+}
+
+//#############################################
+static inline bool is_volume_space_info_request(sal_uInt32 field_mask)
+{
+ return (field_mask &
+ (osl_VolumeInfo_Mask_TotalSpace |
+ osl_VolumeInfo_Mask_UsedSpace |
+ osl_VolumeInfo_Mask_FreeSpace));
+}
+
+//#############################################
+static void get_volume_space_information(
+ const rtl::OUString& path, oslVolumeInfo *pInfo)
+{
+ BOOL ret = GetDiskFreeSpaceEx(
+ reinterpret_cast<LPCTSTR>(path.getStr()),
+ (PULARGE_INTEGER)&(pInfo->uFreeSpace),
+ (PULARGE_INTEGER)&(pInfo->uTotalSpace),
+ NULL);
+
+ if (ret)
+ {
+ pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace |
+ osl_VolumeInfo_Mask_UsedSpace |
+ osl_VolumeInfo_Mask_FreeSpace;
+ }
+}
+
+//#############################################
+static inline bool is_filesystem_attributes_request(sal_uInt32 field_mask)
+{
+ return (field_mask &
+ (osl_VolumeInfo_Mask_MaxNameLength |
+ osl_VolumeInfo_Mask_MaxPathLength |
+ osl_VolumeInfo_Mask_FileSystemName |
+ osl_VolumeInfo_Mask_FileSystemCaseHandling));
+}
+
+//#############################################
+static oslFileError get_filesystem_attributes(
+ const rtl::OUString& path, sal_uInt32 field_mask, oslVolumeInfo* pInfo)
+{
+ pInfo->uAttributes = 0;
+
+ // osl_get_drive_type must be called first because
+ // this function resets osl_VolumeInfo_Mask_Attributes
+ // on failure
+ if (is_drivetype_request(field_mask))
+ {
+ oslFileError osl_error = osl_get_drive_type(path, pInfo);
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+ }
+ if (is_filesystem_attributes_request(field_mask))
+ {
+ /* the following two parameters can not be longer than MAX_PATH+1 */
+ WCHAR vn[MAX_PATH+1];
+ WCHAR fsn[MAX_PATH+1];
+
+ DWORD serial;
+ DWORD mcl;
+ DWORD flags;
+
+ LPCTSTR pszPath = reinterpret_cast<LPCTSTR>(path.getStr());
+ if (GetVolumeInformation(pszPath, vn, MAX_PATH+1, &serial, &mcl, &flags, fsn, MAX_PATH+1))
+ {
+ // Currently sal does not use this value, instead MAX_PATH is used
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
+ pInfo->uMaxNameLength = mcl;
+
+ // Should the uMaxPathLength be set to 32767, "\\?\" prefix allowes it
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
+ pInfo->uMaxPathLength = MAX_PATH;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
+ rtl_uString_newFromStr(&pInfo->ustrFileSystemName, reinterpret_cast<const sal_Unicode*>(fsn));
+
+ // volumes (even NTFS) will always be considered case
+ // insensitive because the Win32 API is not able to
+ // deal with case sensitive volumes see M$ Knowledge Base
+ // article 100625 that's why we never set the attribute
+ // osl_Volume_Attribute_Case_Sensitive
+
+ if (flags & FS_CASE_IS_PRESERVED)
+ pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+ }
+ return osl_File_E_None;
+}
+
+//#####################################################
+static bool path_get_parent(rtl::OUString& path)
+{
+ OSL_PRECOND(path.lastIndexOf(SLASH) == -1, "Path must not have slashes");
+
+ if (!has_path_parent(path))
+ {
+ sal_Int32 i = path.lastIndexOf(BACKSLASH);
+ if (-1 < i)
+ {
+ path = rtl::OUString(path.getStr(), i);
+ return true;
+ }
+ }
+ return false;
+}
+
+//#####################################################
+static void path_travel_to_volume_root(const rtl::OUString& system_path, rtl::OUString& volume_root)
+{
+ rtl::OUString sys_path(system_path);
+
+ while(!is_volume_mount_point(sys_path) && path_get_parent(sys_path))
+ /**/;
+
+ volume_root = sys_path;
+ osl::systemPathEnsureSeparator(volume_root);
+}
+
+//#############################################
+oslFileError SAL_CALL osl_getVolumeInformation(
+ rtl_uString *ustrURL, oslVolumeInfo *pInfo, sal_uInt32 uFieldMask )
+{
+ if (!pInfo)
+ return osl_File_E_INVAL;
+
+ rtl::OUString system_path;
+ oslFileError error = _osl_getSystemPathFromFileURL(ustrURL, &system_path.pData, sal_False);
+
+ if (osl_File_E_None != error)
+ return error;
+
+ rtl::OUString volume_root;
+ path_travel_to_volume_root(system_path, volume_root);
+
+ pInfo->uValidFields = 0;
+
+ if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None)
+ return error;
+
+ if (is_volume_space_info_request(uFieldMask))
+ get_volume_space_information(volume_root, pInfo);
+
+ if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
+ {
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
+ osl_getFileURLFromSystemPath(volume_root.pData, (rtl_uString**)&pInfo->pDeviceHandle);
+ }
+
+ return osl_File_E_None;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getDriveInfo(
+ oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask)
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+ TCHAR cDrive[3] = TEXT("A:");
+ TCHAR cRoot[4] = TEXT("A:\\");
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ pStatus->uValidFields = 0;
+
+ cDrive[0] = pItemImpl->cDriveString[0];
+ cRoot[0] = pItemImpl->cDriveString[0];
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileName )
+ {
+ if ( pItemImpl->cDriveString[0] == '\\' && pItemImpl->cDriveString[1] == '\\' )
+ {
+ LPCWSTR lpFirstBkSlash = wcschr( &pItemImpl->cDriveString[2], '\\' );
+
+ if ( lpFirstBkSlash && lpFirstBkSlash[1] )
+ {
+ LPCWSTR lpLastBkSlash = wcschr( &lpFirstBkSlash[1], '\\' );
+
+ if ( lpLastBkSlash )
+ rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]), lpLastBkSlash - lpFirstBkSlash - 1 );
+ else
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(&lpFirstBkSlash[1]) );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ }
+ }
+ else switch ( GetDriveType( cRoot ) )
+ {
+ case DRIVE_REMOTE:
+ {
+ TCHAR szBuffer[1024];
+ DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szBuffer);
+ DWORD dwBufsize = dwBufsizeConst;
+
+ DWORD dwResult = WNetGetConnection( cDrive, szBuffer, &dwBufsize );
+ if ( NO_ERROR == dwResult )
+ {
+ TCHAR szFileName[dwBufsizeConst + 16];
+
+ swprintf( szFileName, L"%s [%s]", cDrive, szBuffer );
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
+ }
+ else
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
+ }
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ break;
+ case DRIVE_FIXED:
+ {
+ TCHAR szVolumeNameBuffer[1024];
+ DWORD const dwBufsizeConst = ELEMENTS_OF_ARRAY(szVolumeNameBuffer);
+
+ if ( GetVolumeInformation( cRoot, szVolumeNameBuffer, dwBufsizeConst, NULL, NULL, NULL, NULL, 0 ) )
+ {
+ TCHAR szFileName[dwBufsizeConst + 16];
+
+ swprintf( szFileName, L"%s [%s]", cDrive, szVolumeNameBuffer );
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(szFileName) );
+ }
+ else
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cDrive) );
+ }
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ break;
+ case DRIVE_CDROM:
+ case DRIVE_REMOVABLE:
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(cRoot) );
+ break;
+ case DRIVE_UNKNOWN:
+ default:
+ break;
+ }
+ }
+
+ pStatus->eType = osl_File_Type_Volume;
+ pStatus->uValidFields |= osl_FileStatus_Mask_Type;
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileURL )
+ {
+ rtl_uString *ustrSystemPath = NULL;
+
+ rtl_uString_newFromStr( &ustrSystemPath, reinterpret_cast<const sal_Unicode*>(pItemImpl->cDriveString) );
+ osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL );
+ rtl_uString_release( ustrSystemPath );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+ return osl_File_E_None;
+}
+
+//#####################################################
+static oslFileError SAL_CALL osl_getServerInfo(
+ oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask )
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ pStatus->uValidFields = 0;
+
+ // pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+
+ // if ( _tcscmp( pItemImpl->FindData.cFileName, TEXT(".") ) == 0 )
+ // rtl_uString_newFromAscii( &pStatus->ustrFileName, "/" );
+ // else
+ // rtl_uString_newFromStr( &pStatus->ustrFileName, pItemImpl->FindData.cFileName );
+
+ pStatus->eType = osl_File_Type_Directory;
+ pStatus->uValidFields |= osl_FileStatus_Mask_Type;
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileURL )
+ {
+ osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrFileURL );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+ return osl_File_E_None;
+}
+
+//#############################################
+oslFileError SAL_CALL osl_getFileStatus(
+ oslDirectoryItem Item,
+ oslFileStatus *pStatus,
+ sal_uInt32 uFieldMask )
+{
+ DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item;
+
+ if ( !pItemImpl )
+ return osl_File_E_INVAL;
+
+ switch ( pItemImpl->uType )
+ {
+ case DIRECTORYITEM_DRIVE:
+ return osl_getDriveInfo( Item, pStatus, uFieldMask );
+ case DIRECTORYITEM_SERVER:
+ return osl_getServerInfo( Item, pStatus, uFieldMask );
+ default:
+ break;
+ }
+
+ if ( uFieldMask & osl_FileStatus_Mask_Validate )
+ {
+ HANDLE hFind = FindFirstFile( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ), &pItemImpl->FindData );
+
+ if ( hFind != INVALID_HANDLE_VALUE )
+ FindClose( hFind );
+ else
+ return oslTranslateFileError( GetLastError() );
+
+ uFieldMask &= ~ osl_FileStatus_Mask_Validate;
+ }
+
+ /* If no fields to retrieve left ignore pStatus */
+ if ( !uFieldMask )
+ return osl_File_E_None;
+
+ /* Otherwise, this must be a valid pointer */
+ if ( !pStatus )
+ return osl_File_E_INVAL;
+
+ if ( pStatus->uStructSize != sizeof(oslFileStatus) )
+ return osl_File_E_INVAL;
+
+ pStatus->uValidFields = 0;
+
+ /* File time stamps */
+
+ if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime) &&
+ FileTimeToTimeValue( &pItemImpl->FindData.ftLastWriteTime, &pStatus->aModifyTime ) )
+ pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime;
+
+ if ( (uFieldMask & osl_FileStatus_Mask_AccessTime) &&
+ FileTimeToTimeValue( &pItemImpl->FindData.ftLastAccessTime, &pStatus->aAccessTime ) )
+ pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime;
+
+ if ( (uFieldMask & osl_FileStatus_Mask_CreationTime) &&
+ FileTimeToTimeValue( &pItemImpl->FindData.ftCreationTime, &pStatus->aCreationTime ) )
+ pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime;
+
+ /* Most of the fields are already set, regardless of requiered fields */
+
+ rtl_uString_newFromStr( &pStatus->ustrFileName, reinterpret_cast<const sal_Unicode*>(pItemImpl->FindData.cFileName) );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileName;
+
+ if ((FILE_ATTRIBUTE_REPARSE_POINT & pItemImpl->FindData.dwFileAttributes) &&
+ (IO_REPARSE_TAG_MOUNT_POINT == pItemImpl->FindData.dwReserved0))
+ pStatus->eType = osl_File_Type_Volume;
+ else if (pItemImpl->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ pStatus->eType = osl_File_Type_Directory;
+ else
+ pStatus->eType = osl_File_Type_Regular;
+
+ pStatus->uValidFields |= osl_FileStatus_Mask_Type;
+
+ pStatus->uAttributes = pItemImpl->FindData.dwFileAttributes;
+ pStatus->uValidFields |= osl_FileStatus_Mask_Attributes;
+
+ pStatus->uFileSize = (sal_uInt64)pItemImpl->FindData.nFileSizeLow + ((sal_uInt64)pItemImpl->FindData.nFileSizeHigh << 32);
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileSize;
+
+ if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL )
+ {
+ osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrLinkTargetURL );
+
+ pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
+ }
+
+ if ( uFieldMask & osl_FileStatus_Mask_FileURL )
+ {
+ if ( !pItemImpl->bFullPathNormalized )
+ {
+ sal_uInt32 nLen = rtl_uString_getLength( pItemImpl->m_pFullPath );
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>( rtl_uString_getStr( pItemImpl->m_pFullPath ) ),
+ ::osl::mingw_reinterpret_cast<LPTSTR>( aBuffer ),
+ aBuffer.getBufSizeInSymbols(),
+ sal_True );
+
+ if ( nNewLen )
+ {
+ rtl_uString_newFromStr( &pItemImpl->m_pFullPath, aBuffer );
+ pItemImpl->bFullPathNormalized = TRUE;
+ }
+ }
+
+ osl_getFileURLFromSystemPath( pItemImpl->m_pFullPath, &pStatus->ustrFileURL );
+ pStatus->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+
+ return osl_File_E_None;
+}
+
+//#####################################################
+// file attributes handling functions
+//#####################################################
+
+//#############################################
+oslFileError SAL_CALL osl_setFileAttributes(
+ rtl_uString *ustrFileURL,
+ sal_uInt64 uAttributes )
+{
+ oslFileError error;
+ rtl_uString *ustrSysPath = NULL;
+ DWORD dwFileAttributes;
+ BOOL fSuccess;
+
+ // Converts the normalized path into a systempath
+ error = _osl_getSystemPathFromFileURL( ustrFileURL, &ustrSysPath, sal_False );
+
+ if ( osl_File_E_None != error )
+ return error;
+
+ dwFileAttributes = GetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)) );
+
+ if ( (DWORD)-1 != dwFileAttributes )
+ {
+ dwFileAttributes &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN);
+
+ if ( uAttributes & osl_File_Attribute_ReadOnly )
+ dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
+
+ if ( uAttributes & osl_File_Attribute_Hidden )
+ dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
+
+ fSuccess = SetFileAttributes( reinterpret_cast<LPCTSTR>(rtl_uString_getStr(ustrSysPath)), dwFileAttributes );
+ }
+ else
+ fSuccess = FALSE;
+
+ if ( !fSuccess )
+ error = oslTranslateFileError( GetLastError() );
+
+ rtl_uString_release( ustrSysPath );
+
+ return error;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_setFileTime(
+ rtl_uString *filePath,
+ const TimeValue *aCreationTime,
+ const TimeValue *aLastAccessTime,
+ const TimeValue *aLastWriteTime)
+{
+ oslFileError error;
+ rtl_uString *sysPath=NULL;
+ FILETIME *lpCreationTime=NULL;
+ FILETIME *lpLastAccessTime=NULL;
+ FILETIME *lpLastWriteTime=NULL;
+ FILETIME ftCreationTime;
+ FILETIME ftLastAccessTime;
+ FILETIME ftLastWriteTime;
+ HANDLE hFile;
+ BOOL fSuccess;
+
+
+ error=_osl_getSystemPathFromFileURL(filePath, &sysPath, sal_False);
+
+ if (error==osl_File_E_INVAL)
+ return error;
+
+ hFile=CreateFileW(reinterpret_cast<LPCWSTR>(rtl_uString_getStr(sysPath)), GENERIC_WRITE, 0, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ rtl_uString_release(sysPath);
+
+ if (hFile==INVALID_HANDLE_VALUE)
+ return osl_File_E_NOENT;
+
+ if (TimeValueToFileTime(aCreationTime, &ftCreationTime))
+ lpCreationTime=&ftCreationTime;
+
+ if (TimeValueToFileTime(aLastAccessTime, &ftLastAccessTime))
+ lpLastAccessTime=&ftLastAccessTime;
+
+ if (TimeValueToFileTime(aLastWriteTime, &ftLastWriteTime))
+ lpLastWriteTime=&ftLastWriteTime;
+
+ fSuccess=SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
+
+ CloseHandle(hFile);
+
+ if (!fSuccess)
+ return osl_File_E_INVAL;
+ else
+ return osl_File_E_None;
+}
diff --git a/sal/osl/w32/file_error.c b/sal/osl/w32/file_error.c
new file mode 100644
index 000000000000..26e749cc5451
--- /dev/null
+++ b/sal/osl/w32/file_error.c
@@ -0,0 +1,151 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT_0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "file_error.h"
+
+#include "osl/diagnose.h"
+#include "osl/thread.h"
+
+/* OS error to oslFileError values mapping table */
+struct osl_file_error_entry
+{
+ unsigned long oscode; /* OS return value */
+ int errnocode; /* oslFileError code */
+};
+
+static const struct osl_file_error_entry errtable[] = {
+ { ERROR_SUCCESS, osl_File_E_None }, /* 0 */
+ { ERROR_INVALID_FUNCTION, osl_File_E_INVAL }, /* 1 */
+ { ERROR_FILE_NOT_FOUND, osl_File_E_NOENT }, /* 2 */
+ { ERROR_PATH_NOT_FOUND, osl_File_E_NOENT }, /* 3 */
+ { ERROR_TOO_MANY_OPEN_FILES, osl_File_E_MFILE }, /* 4 */
+ { ERROR_ACCESS_DENIED, osl_File_E_ACCES }, /* 5 */
+ { ERROR_INVALID_HANDLE, osl_File_E_BADF }, /* 6 */
+ { ERROR_ARENA_TRASHED, osl_File_E_NOMEM }, /* 7 */
+ { ERROR_NOT_ENOUGH_MEMORY, osl_File_E_NOMEM }, /* 8 */
+ { ERROR_INVALID_BLOCK, osl_File_E_NOMEM }, /* 9 */
+ { ERROR_BAD_ENVIRONMENT, osl_File_E_2BIG }, /* 10 */
+ { ERROR_BAD_FORMAT, osl_File_E_NOEXEC }, /* 11 */
+ { ERROR_INVALID_ACCESS, osl_File_E_INVAL }, /* 12 */
+ { ERROR_INVALID_DATA, osl_File_E_INVAL }, /* 13 */
+ { ERROR_INVALID_DRIVE, osl_File_E_NOENT }, /* 15 */
+ { ERROR_CURRENT_DIRECTORY, osl_File_E_ACCES }, /* 16 */
+ { ERROR_NOT_SAME_DEVICE, osl_File_E_XDEV }, /* 17 */
+ { ERROR_NO_MORE_FILES, osl_File_E_NOENT }, /* 18 */
+ { ERROR_NOT_READY, osl_File_E_NOTREADY }, /* 21 */
+ { ERROR_LOCK_VIOLATION, osl_File_E_ACCES }, /* 33 */
+ { ERROR_BAD_NETPATH, osl_File_E_NOENT }, /* 53 */
+ { ERROR_NETWORK_ACCESS_DENIED, osl_File_E_ACCES }, /* 65 */
+ { ERROR_BAD_NET_NAME, osl_File_E_NOENT }, /* 67 */
+ { ERROR_FILE_EXISTS, osl_File_E_EXIST }, /* 80 */
+ { ERROR_CANNOT_MAKE, osl_File_E_ACCES }, /* 82 */
+ { ERROR_FAIL_I24, osl_File_E_ACCES }, /* 83 */
+ { ERROR_INVALID_PARAMETER, osl_File_E_INVAL }, /* 87 */
+ { ERROR_NO_PROC_SLOTS, osl_File_E_AGAIN }, /* 89 */
+ { ERROR_DRIVE_LOCKED, osl_File_E_ACCES }, /* 108 */
+ { ERROR_BROKEN_PIPE, osl_File_E_PIPE }, /* 109 */
+ { ERROR_DISK_FULL, osl_File_E_NOSPC }, /* 112 */
+ { ERROR_INVALID_TARGET_HANDLE, osl_File_E_BADF }, /* 114 */
+ { ERROR_INVALID_HANDLE, osl_File_E_INVAL }, /* 124 */
+ { ERROR_WAIT_NO_CHILDREN, osl_File_E_CHILD }, /* 128 */
+ { ERROR_CHILD_NOT_COMPLETE, osl_File_E_CHILD }, /* 129 */
+ { ERROR_DIRECT_ACCESS_HANDLE, osl_File_E_BADF }, /* 130 */
+ { ERROR_NEGATIVE_SEEK, osl_File_E_INVAL }, /* 131 */
+ { ERROR_SEEK_ON_DEVICE, osl_File_E_ACCES }, /* 132 */
+ { ERROR_DIR_NOT_EMPTY, osl_File_E_NOTEMPTY }, /* 145 */
+ { ERROR_NOT_LOCKED, osl_File_E_ACCES }, /* 158 */
+ { ERROR_BAD_PATHNAME, osl_File_E_NOENT }, /* 161 */
+ { ERROR_MAX_THRDS_REACHED, osl_File_E_AGAIN }, /* 164 */
+ { ERROR_LOCK_FAILED, osl_File_E_ACCES }, /* 167 */
+ { ERROR_ALREADY_EXISTS, osl_File_E_EXIST }, /* 183 */
+ { ERROR_FILENAME_EXCED_RANGE, osl_File_E_NOENT }, /* 206 */
+ { ERROR_NESTING_NOT_ALLOWED, osl_File_E_AGAIN }, /* 215 */
+ { ERROR_DIRECTORY, osl_File_E_NOENT }, /* 267 */
+ { ERROR_NOT_ENOUGH_QUOTA, osl_File_E_NOMEM }, /* 1816 */
+ { ERROR_UNEXP_NET_ERR, osl_File_E_NETWORK } /* 59 */
+};
+
+/* The following two constants must be the minimum and maximum
+ values in the (contiguous) range of osl_File_E_xec Failure errors.
+*/
+#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
+#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
+
+/* These are the low and high value in the range of errors that are
+ access violations
+*/
+#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
+#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
+
+oslFileError oslTranslateFileError (/*DWORD*/ unsigned long dwError)
+{
+ static const int n = sizeof(errtable)/sizeof(errtable[0]);
+
+ int i;
+ for (i = 0; i < n; ++i )
+ {
+ if (dwError == errtable[i].oscode)
+ return (oslFileError)(errtable[i].errnocode);
+ }
+
+ /* The error code wasn't in the table. We check for a range of
+ osl_File_E_ACCES errors or exec failure errors (ENOEXEC).
+ Otherwise osl_File_E_INVAL is returned.
+ */
+ if ( (dwError >= MIN_EACCES_RANGE) && (dwError <= MAX_EACCES_RANGE) )
+ return osl_File_E_ACCES;
+ else if ( (dwError >= MIN_EXEC_ERROR) && (dwError <= MAX_EXEC_ERROR) )
+ return osl_File_E_NOEXEC;
+ else
+ return osl_File_E_INVAL;
+}
+
+//#####################################################
+#if OSL_DEBUG_LEVEL > 0
+void _osl_warnFile( const char *message, rtl_uString *ustrFile )
+{
+ char szBuffer[2048];
+
+ if (ustrFile)
+ {
+ rtl_String *strFile = NULL;
+
+ rtl_uString2String( &strFile, rtl_uString_getStr( ustrFile ), rtl_uString_getLength( ustrFile ),
+ osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS );
+ snprintf( szBuffer, sizeof(szBuffer), message, strFile->buffer );
+ rtl_string_release( strFile );
+
+ message = szBuffer;
+ }
+ OSL_ENSURE( 0, message );
+}
+#endif /* OSL_DEBUG_LEVEL */
diff --git a/sal/osl/w32/file_error.h b/sal/osl/w32/file_error.h
new file mode 100644
index 000000000000..3815a021bb5e
--- /dev/null
+++ b/sal/osl/w32/file_error.h
@@ -0,0 +1,51 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_OSL_FILE_ERROR_H
+#define INCLUDED_OSL_FILE_ERROR_H
+
+#include "osl/file.h"
+#include "rtl/ustring.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+oslFileError oslTranslateFileError (/*DWORD*/ unsigned long dwError);
+
+#if OSL_DEBUG_LEVEL > 0
+void _osl_warnFile (const char * message, rtl_uString * ustrFile);
+#define OSL_ENSURE_FILE( cond, msg, file ) ( (cond) ? (void)0 : _osl_warnFile( msg, file ) )
+#else
+#define OSL_ENSURE_FILE( cond, msg, file ) ((void)0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_OSL_FILE_ERROR_H */
diff --git a/sal/osl/w32/file_url.cxx b/sal/osl/w32/file_url.cxx
new file mode 100644
index 000000000000..90140cda97c6
--- /dev/null
+++ b/sal/osl/w32/file_url.cxx
@@ -0,0 +1,1143 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT_0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "file_url.h"
+#include "file_error.h"
+
+#include "rtl/alloc.h"
+#include "osl/diagnose.h"
+#include "osl/file.h"
+#include "osl/mutex.h"
+
+#include "path_helper.hxx"
+
+#include <stdio.h>
+#include <tchar.h>
+
+#if OSL_DEBUG_LEVEL > 0
+#define OSL_ENSURE_FILE( cond, msg, file ) ( (cond) ? (void)0 : _osl_warnFile( msg, file ) )
+#else
+#define OSL_ENSURE_FILE( cond, msg, file ) ((void)0)
+#endif
+
+#define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
+
+#define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\"
+#define WSTR_LONG_PATH_PREFIX L"\\\\?\\"
+#define WSTR_LONG_PATH_PREFIX_UNC L"\\\\?\\UNC\\"
+
+
+//##################################################################
+// FileURL functions
+//##################################################################
+
+extern "C" oslMutex g_CurrentDirectoryMutex; /* Initialized in dllentry.c */
+oslMutex g_CurrentDirectoryMutex = 0;
+
+//#####################################################
+static BOOL IsValidFilePathComponent(
+ LPCTSTR lpComponent, LPCTSTR *lppComponentEnd, DWORD dwFlags)
+{
+ LPCTSTR lpComponentEnd = NULL;
+ LPCTSTR lpCurrent = lpComponent;
+ BOOL fValid = TRUE; /* Assume success */
+ TCHAR cLast = 0;
+
+ /* Path component length must not exceed MAX_PATH even if long path with "\\?\" prefix is used */
+
+ while ( !lpComponentEnd && lpCurrent && lpCurrent - lpComponent < MAX_PATH )
+ {
+ switch ( *lpCurrent )
+ {
+ /* Both backslash and slash determine the end of a path component */
+ case '\0':
+ case '/':
+ case '\\':
+ switch ( cLast )
+ {
+ /* Component must not end with '.' or blank and can't be empty */
+
+ case '.':
+ if ( dwFlags & VALIDATEPATH_ALLOW_ELLIPSE )
+ {
+ if ( 1 == lpCurrent - lpComponent )
+ {
+ /* Current directory is O.K. */
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ else if ( 2 == lpCurrent - lpComponent && '.' == *lpComponent )
+ {
+ /* Parent directory is O.K. */
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ }
+ case 0:
+ case ' ':
+ lpComponentEnd = lpCurrent - 1;
+ fValid = FALSE;
+ break;
+ default:
+ lpComponentEnd = lpCurrent;
+ break;
+ }
+ break;
+ /* '?' and '*' are valid wildcards but not valid file name characters */
+ case '?':
+ case '*':
+ if ( dwFlags & VALIDATEPATH_ALLOW_WILDCARDS )
+ break;
+ /* The following characters are reserved */
+ case '<':
+ case '>':
+ case '\"':
+ case '|':
+ case ':':
+ lpComponentEnd = lpCurrent;
+ fValid = FALSE;
+ break;
+ default:
+ /* Characters below ASCII 32 are not allowed */
+ if ( *lpCurrent < ' ' )
+ {
+ lpComponentEnd = lpCurrent;
+ fValid = FALSE;
+ }
+ break;
+ }
+ cLast = *lpCurrent++;
+ }
+
+ /* If we don't reached the end of the component the length of the component was to long
+ ( See condition of while loop ) */
+ if ( !lpComponentEnd )
+ {
+ fValid = FALSE;
+ lpComponentEnd = lpCurrent;
+ }
+
+ /* Test wether the component specifies a device name what is not allowed */
+
+ // MT: PERFORMANCE:
+ // This is very expensive. A lot of calls to _tcsicmp.
+ // in SRC6870m71 67.000 calls of this method while empty office start result into more than 1.500.00 calls of _tcsicmp!
+ // Possible optimizations
+ // - Array should be const static
+ // - Sorted array, use binary search
+ // - More intelligent check for com1-9, lpt1-9
+ // Maybe make szComponent upper case, don't search case intensitive
+ // Talked to HRO: Could be removed. Shouldn't be used in OOo, and if used for something like a filename, it will lead to an error anyway.
+ /*
+ if ( fValid )
+ {
+ LPCTSTR alpDeviceNames[] =
+ {
+ TEXT("CON"),
+ TEXT("PRN"),
+ TEXT("AUX"),
+ TEXT("CLOCK$"),
+ TEXT("NUL"),
+ TEXT("LPT1"),
+ TEXT("LPT2"),
+ TEXT("LPT3"),
+ TEXT("LPT4"),
+ TEXT("LPT5"),
+ TEXT("LPT6"),
+ TEXT("LPT7"),
+ TEXT("LPT8"),
+ TEXT("LPT9"),
+ TEXT("COM1"),
+ TEXT("COM2"),
+ TEXT("COM3"),
+ TEXT("COM4"),
+ TEXT("COM5"),
+ TEXT("COM6"),
+ TEXT("COM7"),
+ TEXT("COM8"),
+ TEXT("COM9")
+ };
+
+ TCHAR szComponent[MAX_PATH];
+ int nComponentLength;
+ LPCTSTR lpDot;
+ int i;
+
+ // A device name with an extension is also invalid
+ lpDot = _tcschr( lpComponent, '.' );
+
+ if ( !lpDot || lpDot > lpComponentEnd )
+ nComponentLength = lpComponentEnd - lpComponent;
+ else
+ nComponentLength = lpDot - lpComponent;
+
+ _tcsncpy( szComponent, lpComponent, nComponentLength );
+ szComponent[nComponentLength] = 0;
+
+ for ( i = 0; i < sizeof( alpDeviceNames ) / sizeof(LPCTSTR); i++ )
+ {
+ if ( 0 == _tcsicmp( szComponent, alpDeviceNames[i] ) )
+ {
+ lpComponentEnd = lpComponent;
+ fValid = FALSE;
+ break;
+ }
+ }
+ }
+ */
+
+ if ( fValid )
+ {
+ // Empty components are not allowed
+ if ( lpComponentEnd - lpComponent < 1 )
+ fValid = FALSE;
+
+ // If we reached the end of the string NULL is returned
+ else if ( !*lpComponentEnd )
+ lpComponentEnd = NULL;
+
+ }
+
+ if ( lppComponentEnd )
+ *lppComponentEnd = lpComponentEnd;
+
+ return fValid;
+}
+
+//#####################################################
+#define CHARSET_SEPARATOR TEXT("\\/")
+
+DWORD IsValidFilePath(rtl_uString *path, LPCTSTR *lppError, DWORD dwFlags, rtl_uString **corrected)
+{
+ LPCTSTR lpszPath = reinterpret_cast< LPCTSTR >(path->buffer);
+ LPCTSTR lpComponent = lpszPath;
+ BOOL fValid = TRUE;
+ DWORD dwPathType = PATHTYPE_ERROR;
+ sal_Int32 nLength = rtl_uString_getLength( path );
+
+ if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
+ dwFlags |= VALIDATEPATH_ALLOW_ELLIPSE;
+
+ if ( !lpszPath )
+ fValid = FALSE;
+
+ DWORD dwCandidatPathType = PATHTYPE_ERROR;
+
+ if ( 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( path->buffer, nLength, reinterpret_cast<const sal_Unicode *>(WSTR_LONG_PATH_PREFIX_UNC), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1 ) )
+ {
+ /* This is long path in UNC notation */
+ lpComponent = lpszPath + ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX_UNC) - 1;
+ dwCandidatPathType = PATHTYPE_ABSOLUTE_UNC | PATHTYPE_IS_LONGPATH;
+ }
+ else if ( 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( path->buffer, nLength, reinterpret_cast<const sal_Unicode *>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1 ) )
+ {
+ /* This is long path */
+ lpComponent = lpszPath + ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1;
+
+ if ( _istalpha( lpComponent[0] ) && ':' == lpComponent[1] )
+ {
+ lpComponent += 2;
+ dwCandidatPathType = PATHTYPE_ABSOLUTE_LOCAL | PATHTYPE_IS_LONGPATH;
+ }
+ }
+ else if ( 2 == _tcsspn( lpszPath, CHARSET_SEPARATOR ) )
+ {
+ /* The UNC path notation */
+ lpComponent = lpszPath + 2;
+ dwCandidatPathType = PATHTYPE_ABSOLUTE_UNC;
+ }
+ else if ( _istalpha( lpszPath[0] ) && ':' == lpszPath[1] )
+ {
+ /* Local path verification. Must start with <drive>: */
+ lpComponent = lpszPath + 2;
+ dwCandidatPathType = PATHTYPE_ABSOLUTE_LOCAL;
+ }
+
+ if ( ( dwCandidatPathType & PATHTYPE_MASK_TYPE ) == PATHTYPE_ABSOLUTE_UNC )
+ {
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, VALIDATEPATH_ALLOW_ELLIPSE );
+
+ /* So far we have a valid servername. Now let's see if we also have a network resource */
+
+ dwPathType = dwCandidatPathType;
+
+ if ( fValid )
+ {
+ if ( lpComponent && !*++lpComponent )
+ lpComponent = NULL;
+
+ if ( !lpComponent )
+ {
+ #if 0
+ /* We only have a Server specification what is invalid */
+
+ lpComponent = lpszPath;
+ fValid = FALSE;
+ #else
+ dwPathType |= PATHTYPE_IS_SERVER;
+ #endif
+ }
+ else
+ {
+ /* Now test the network resource */
+
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, 0 );
+
+ /* If we now reached the end of the path, everything is O.K. */
+
+
+ if ( fValid && (!lpComponent || lpComponent && !*++lpComponent ) )
+ {
+ lpComponent = NULL;
+ dwPathType |= PATHTYPE_IS_VOLUME;
+ }
+ }
+ }
+ }
+ else if ( ( dwCandidatPathType & PATHTYPE_MASK_TYPE ) == PATHTYPE_ABSOLUTE_LOCAL )
+ {
+ if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
+ lpComponent++;
+ else if ( *lpComponent )
+ fValid = FALSE;
+
+ dwPathType = dwCandidatPathType;
+
+ /* Now we are behind the backslash or it was a simple drive without backslash */
+
+ if ( fValid && !*lpComponent )
+ {
+ lpComponent = NULL;
+ dwPathType |= PATHTYPE_IS_VOLUME;
+ }
+ }
+ else if ( dwFlags & VALIDATEPATH_ALLOW_RELATIVE )
+ {
+ /* Can be a relative path */
+ lpComponent = lpszPath;
+
+ /* Relative path can start with a backslash */
+
+ if ( 1 == _tcsspn( lpComponent, CHARSET_SEPARATOR ) )
+ {
+ lpComponent++;
+ if ( !*lpComponent )
+ lpComponent = NULL;
+ }
+
+ dwPathType = PATHTYPE_RELATIVE;
+ }
+ else
+ {
+ /* Anything else is an error */
+ fValid = FALSE;
+ lpComponent = lpszPath;
+ }
+
+ /* Now validate each component of the path */
+ while ( fValid && lpComponent )
+ {
+ // Correct path by merging consecutive slashes:
+ if (*lpComponent == '\\' && corrected != NULL) {
+ sal_Int32 i = lpComponent - lpszPath;
+ rtl_uString_newReplaceStrAt(corrected, path, i, 1, NULL);
+ //TODO: handle out-of-memory
+ lpszPath = reinterpret_cast< LPCTSTR >((*corrected)->buffer);
+ lpComponent = lpszPath + i;
+ }
+
+ fValid = IsValidFilePathComponent( lpComponent, &lpComponent, dwFlags );
+
+ if ( fValid && lpComponent )
+ {
+ lpComponent++;
+
+ /* If the string behind the backslash is empty, we've done */
+
+ if ( !*lpComponent )
+ lpComponent = NULL;
+ }
+ }
+
+ /* The path can be longer than MAX_PATH only in case it has the longpath prefix */
+ if ( fValid && !( dwPathType & PATHTYPE_IS_LONGPATH ) && _tcslen( lpszPath ) >= MAX_PATH )
+ {
+ fValid = FALSE;
+ lpComponent = lpszPath + MAX_PATH;
+ }
+
+ if ( lppError )
+ *lppError = lpComponent;
+
+ return fValid ? dwPathType : PATHTYPE_ERROR;
+}
+
+//#####################################################
+static sal_Int32 PathRemoveFileSpec(LPTSTR lpPath, LPTSTR lpFileName, sal_Int32 nFileBufLen )
+{
+ sal_Int32 nRemoved = 0;
+
+ if ( nFileBufLen )
+ {
+ lpFileName[0] = 0;
+ LPTSTR lpLastBkSlash = _tcsrchr( lpPath, '\\' );
+ LPTSTR lpLastSlash = _tcsrchr( lpPath, '/' );
+ LPTSTR lpLastDelimiter = lpLastSlash > lpLastBkSlash ? lpLastSlash : lpLastBkSlash;
+
+ if ( lpLastDelimiter )
+ {
+ sal_Int32 nDelLen = _tcslen( lpLastDelimiter );
+ if ( 1 == nDelLen )
+ {
+ if ( lpLastDelimiter > lpPath && *(lpLastDelimiter - 1) != ':' )
+ {
+ *lpLastDelimiter = 0;
+ *lpFileName = 0;
+ nRemoved = nDelLen;
+ }
+ }
+ else if ( nDelLen && nDelLen - 1 < nFileBufLen )
+ {
+ _tcscpy( lpFileName, lpLastDelimiter + 1 );
+ *(++lpLastDelimiter) = 0;
+ nRemoved = nDelLen - 1;
+ }
+ }
+ }
+
+ return nRemoved;
+}
+
+//#####################################################
+// Undocumented in SHELL32.DLL ordinal 32
+static LPTSTR PathAddBackslash(LPTSTR lpPath, sal_Int32 nBufLen)
+{
+ LPTSTR lpEndPath = NULL;
+
+ if ( lpPath )
+ {
+ int nLen = _tcslen(lpPath);
+
+ if ( !nLen || lpPath[nLen-1] != '\\' && lpPath[nLen-1] != '/' && nLen < nBufLen - 1 )
+ {
+ lpEndPath = lpPath + nLen;
+ *lpEndPath++ = '\\';
+ *lpEndPath = 0;
+ }
+ }
+ return lpEndPath;
+}
+
+//#####################################################
+// Same as GetLongPathName but also 95/NT4
+static DWORD GetCaseCorrectPathNameEx(
+ LPTSTR lpszPath, // path buffer to convert
+ DWORD cchBuffer, // size of path buffer
+ DWORD nSkipLevels,
+ BOOL bCheckExistence )
+{
+ ::osl::LongPathBuffer< WCHAR > szFile( MAX_PATH + 1 );
+ sal_Int32 nRemoved = PathRemoveFileSpec( lpszPath, szFile, MAX_PATH + 1 );
+ sal_Int32 nLastStepRemoved = nRemoved;
+ while ( nLastStepRemoved && szFile[0] == 0 )
+ {
+ // remove separators
+ nLastStepRemoved = PathRemoveFileSpec( lpszPath, szFile, MAX_PATH + 1 );
+ nRemoved += nLastStepRemoved;
+ }
+
+ if ( nRemoved )
+ {
+ BOOL bSkipThis = FALSE;
+
+ if ( 0 == _tcscmp( szFile, TEXT("..") ) )
+ {
+ bSkipThis = TRUE;
+ nSkipLevels += 1;
+ }
+ else if ( 0 == _tcscmp( szFile, TEXT(".") ) )
+ {
+ bSkipThis = TRUE;
+ }
+ else if ( nSkipLevels )
+ {
+ bSkipThis = TRUE;
+ nSkipLevels--;
+ }
+ else
+ bSkipThis = FALSE;
+
+ GetCaseCorrectPathNameEx( lpszPath, cchBuffer, nSkipLevels, bCheckExistence );
+
+ PathAddBackslash( lpszPath, cchBuffer );
+
+ /* Analyze parent if not only a trailing backslash was cutted but a real file spec */
+ if ( !bSkipThis )
+ {
+ if ( bCheckExistence )
+ {
+ ::osl::LongPathBuffer< WCHAR > aShortPath( MAX_LONG_PATH );
+ _tcscpy( aShortPath, lpszPath );
+ _tcscat( aShortPath, szFile );
+
+ WIN32_FIND_DATA aFindFileData;
+ HANDLE hFind = FindFirstFile( aShortPath, &aFindFileData );
+
+ if ( IsValidHandle(hFind) )
+ {
+ _tcscat( lpszPath, aFindFileData.cFileName[0] ? aFindFileData.cFileName : aFindFileData.cAlternateFileName );
+
+ FindClose( hFind );
+ }
+ else
+ lpszPath[0] = 0;
+ }
+ else
+ {
+ /* add the segment name back */
+ _tcscat( lpszPath, szFile );
+ }
+ }
+ }
+ else
+ {
+ /* File specification can't be removed therefore the short path is either a drive
+ or a network share. If still levels to skip are left, the path specification
+ tries to travel below the file system root */
+ if ( nSkipLevels )
+ lpszPath[0] = 0;
+ else
+ _tcsupr( lpszPath );
+ }
+
+ return _tcslen( lpszPath );
+}
+
+//#####################################################
+#define WSTR_SYSTEM_ROOT_PATH L"\\\\.\\"
+
+DWORD GetCaseCorrectPathName(
+ LPCTSTR lpszShortPath, // file name
+ LPTSTR lpszLongPath, // path buffer
+ DWORD cchBuffer, // size of path buffer
+ BOOL bCheckExistence
+)
+{
+ /* Special handling for "\\.\" as system root */
+ if ( lpszShortPath && 0 == wcscmp( lpszShortPath, WSTR_SYSTEM_ROOT_PATH ) )
+ {
+ if ( cchBuffer >= ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) )
+ {
+ wcscpy( lpszLongPath, WSTR_SYSTEM_ROOT_PATH );
+ return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1;
+ }
+ else
+ {
+ return ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1;
+ }
+ }
+ else if ( lpszShortPath )
+ {
+ if ( _tcslen( lpszShortPath ) <= cchBuffer )
+ {
+ _tcscpy( lpszLongPath, lpszShortPath );
+ return GetCaseCorrectPathNameEx( lpszLongPath, cchBuffer, 0, bCheckExistence );
+ }
+ }
+
+ return 0;
+}
+
+
+//#############################################
+static sal_Bool _osl_decodeURL( rtl_String* strUTF8, rtl_uString** pstrDecodedURL )
+{
+ sal_Char *pBuffer;
+ const sal_Char *pSrcEnd;
+ const sal_Char *pSrc;
+ sal_Char *pDest;
+ sal_Int32 nSrcLen;
+ sal_Bool bValidEncoded = sal_True; /* Assume success */
+
+ /* The resulting decoded string length is shorter or equal to the source length */
+
+ nSrcLen = rtl_string_getLength(strUTF8);
+ pBuffer = reinterpret_cast<sal_Char*>(rtl_allocateMemory(nSrcLen + 1));
+
+ pDest = pBuffer;
+ pSrc = rtl_string_getStr(strUTF8);
+ pSrcEnd = pSrc + nSrcLen;
+
+ /* Now decode the URL what should result in an UTF8 string */
+ while ( bValidEncoded && pSrc < pSrcEnd )
+ {
+ switch ( *pSrc )
+ {
+ case '%':
+ {
+ sal_Char aToken[3];
+ sal_Char aChar;
+
+ pSrc++;
+ aToken[0] = *pSrc++;
+ aToken[1] = *pSrc++;
+ aToken[2] = 0;
+
+ aChar = (sal_Char)strtoul( aToken, NULL, 16 );
+
+ /* The chars are path delimiters and must not be encoded */
+
+ if ( 0 == aChar || '\\' == aChar || '/' == aChar || ':' == aChar )
+ bValidEncoded = sal_False;
+ else
+ *pDest++ = aChar;
+ }
+ break;
+ default:
+ *pDest++ = *pSrc++;
+ break;
+ }
+ }
+
+ *pDest++ = 0;
+
+ if ( bValidEncoded )
+ {
+ rtl_string2UString( pstrDecodedURL, pBuffer, rtl_str_getLength(pBuffer), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pstrDecodedURL != 0);
+ }
+
+ rtl_freeMemory( pBuffer );
+
+ return bValidEncoded;
+}
+
+//#############################################
+static void _osl_encodeURL( rtl_uString *strURL, rtl_String **pstrEncodedURL )
+{
+ /* Encode non ascii characters within the URL */
+
+ rtl_String *strUTF8 = NULL;
+ sal_Char *pszEncodedURL;
+ const sal_Char *pURLScan;
+ sal_Char *pURLDest;
+ sal_Int32 nURLScanLen;
+ sal_Int32 nURLScanCount;
+
+ rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ pszEncodedURL = (sal_Char*) rtl_allocateMemory( (rtl_string_getLength( strUTF8 ) * 3 + 1) * sizeof(sal_Char) );
+
+ pURLDest = pszEncodedURL;
+ pURLScan = rtl_string_getStr( strUTF8 );
+ nURLScanLen = rtl_string_getLength( strUTF8 );
+ nURLScanCount = 0;
+
+ while ( nURLScanCount < nURLScanLen )
+ {
+ sal_Char cCurrent = *pURLScan;
+ switch ( cCurrent )
+ {
+ default:
+ if (!( ( cCurrent >= 'a' && cCurrent <= 'z' ) || ( cCurrent >= 'A' && cCurrent <= 'Z' ) || ( cCurrent >= '0' && cCurrent <= '9' ) ) )
+ {
+ sprintf( pURLDest, "%%%02X", (unsigned char)cCurrent );
+ pURLDest += 3;
+ break;
+ }
+ case '!':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '-':
+ case '.':
+ case '_':
+ case '~':
+ case '$':
+ case '&':
+ case '+':
+ case ',':
+ case '=':
+ case '@':
+ case ':':
+ case '/':
+ case '\\':
+ case '|':
+ *pURLDest++ = cCurrent;
+ break;
+ case 0:
+ break;
+ }
+
+ pURLScan++;
+ nURLScanCount++;
+ }
+
+ *pURLDest = 0;
+
+ rtl_string_release( strUTF8 );
+ rtl_string_newFromStr( pstrEncodedURL, pszEncodedURL );
+ rtl_freeMemory( pszEncodedURL );
+}
+
+//#############################################
+
+oslFileError _osl_getSystemPathFromFileURL( rtl_uString *strURL, rtl_uString **pustrPath, sal_Bool bAllowRelative )
+{
+ rtl_String *strUTF8 = NULL;
+ rtl_uString *strDecodedURL = NULL;
+ rtl_uString *strTempPath = NULL;
+ const sal_Unicode *pDecodedURL;
+ sal_uInt32 nDecodedLen;
+ sal_Bool bValidEncoded;
+ oslFileError nError = osl_File_E_INVAL; /* Assume failure */
+
+ /* If someone hasn't encoded the complete URL we convert it to UTF8 now to prevent from
+ having a mixed encoded URL later */
+
+ rtl_uString2String( &strUTF8, rtl_uString_getStr( strURL ), rtl_uString_getLength( strURL ), RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS );
+
+ /* If the length of strUTF8 and strURL differs it indicates that the URL was not correct encoded */
+
+ OSL_ENSURE_FILE(
+ strUTF8->length == strURL->length ||
+ 0 != rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( strURL->buffer, strURL->length, "file:\\\\", 7 )
+ ,"osl_getSystemPathFromFileURL: \"%s\" is not encoded !!!", strURL );
+
+ bValidEncoded = _osl_decodeURL( strUTF8, &strDecodedURL );
+
+ /* Release the encoded UTF8 string */
+ rtl_string_release( strUTF8 );
+
+ if ( bValidEncoded )
+ {
+ /* Replace backslashes and pipes */
+
+ rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '/', '\\' );
+ rtl_uString_newReplace( &strDecodedURL, strDecodedURL, '|', ':' );
+
+ pDecodedURL = rtl_uString_getStr( strDecodedURL );
+ nDecodedLen = rtl_uString_getLength( strDecodedURL );
+
+ /* Must start with "file://" */
+ if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\", 7 ) )
+ {
+ sal_uInt32 nSkip;
+
+ if ( 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\\\", 8 ) )
+ nSkip = 8;
+ else if (
+ 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\localhost\\", 17 ) ||
+ 0 == rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL, nDecodedLen, "file:\\\\127.0.0.1\\", 17 )
+ )
+ nSkip = 17;
+ else
+ nSkip = 5;
+
+ /* Indicates local root */
+ if ( nDecodedLen == nSkip )
+ rtl_uString_newFromStr_WithLength( &strTempPath, reinterpret_cast<const sal_Unicode*>(WSTR_SYSTEM_ROOT_PATH), ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 );
+ else
+ {
+ /* do not separate the directory and file case, so the maximal path lengs without prefix is MAX_PATH-12 */
+ if ( nDecodedLen - nSkip <= MAX_PATH - 12 )
+ {
+ rtl_uString_newFromStr_WithLength( &strTempPath, pDecodedURL + nSkip, nDecodedLen - nSkip );
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Unicode > aBuf( MAX_LONG_PATH );
+ sal_uInt32 nNewLen = GetCaseCorrectPathName( reinterpret_cast<LPCTSTR>(pDecodedURL + nSkip),
+ ::osl::mingw_reinterpret_cast<LPTSTR>(aBuf),
+ aBuf.getBufSizeInSymbols(),
+ sal_False );
+
+ if ( nNewLen <= MAX_PATH - 12
+ || 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL + nSkip, nDecodedLen - nSkip, reinterpret_cast<const sal_Unicode*>(WSTR_SYSTEM_ROOT_PATH), ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1, ELEMENTS_OF_ARRAY(WSTR_SYSTEM_ROOT_PATH) - 1 )
+ || 0 == rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength( pDecodedURL + nSkip, nDecodedLen - nSkip, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1, ELEMENTS_OF_ARRAY(WSTR_LONG_PATH_PREFIX) - 1 ) )
+ {
+ rtl_uString_newFromStr_WithLength( &strTempPath, aBuf, nNewLen );
+ }
+ else if ( pDecodedURL[nSkip] == (sal_Unicode)'\\' && pDecodedURL[nSkip+1] == (sal_Unicode)'\\' )
+ {
+ /* it should be an UNC path, use the according prefix */
+ rtl_uString *strSuffix = NULL;
+ rtl_uString *strPrefix = NULL;
+ rtl_uString_newFromStr_WithLength( &strPrefix, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX_UNC), ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX_UNC ) - 1 );
+ rtl_uString_newFromStr_WithLength( &strSuffix, aBuf + 2, nNewLen - 2 );
+
+ rtl_uString_newConcat( &strTempPath, strPrefix, strSuffix );
+
+ rtl_uString_release( strPrefix );
+ rtl_uString_release( strSuffix );
+ }
+ else
+ {
+ rtl_uString *strSuffix = NULL;
+ rtl_uString *strPrefix = NULL;
+ rtl_uString_newFromStr_WithLength( &strPrefix, reinterpret_cast<const sal_Unicode*>(WSTR_LONG_PATH_PREFIX), ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX ) - 1 );
+ rtl_uString_newFromStr_WithLength( &strSuffix, aBuf, nNewLen );
+
+ rtl_uString_newConcat( &strTempPath, strPrefix, strSuffix );
+
+ rtl_uString_release( strPrefix );
+ rtl_uString_release( strSuffix );
+ }
+ }
+ }
+
+ if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) )
+ nError = osl_File_E_None;
+ }
+ else if ( bAllowRelative ) /* This maybe a relative file URL */
+ {
+ /* In future the relative path could be converted to absolute if it is too long */
+ rtl_uString_assign( &strTempPath, strDecodedURL );
+
+ if ( IsValidFilePath( strTempPath, NULL, VALIDATEPATH_ALLOW_RELATIVE | VALIDATEPATH_ALLOW_ELLIPSE, &strTempPath ) )
+ nError = osl_File_E_None;
+ }
+ /*
+ else
+ OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not an absolute FileURL !!!", strURL );
+ */
+
+ }
+
+ if ( strDecodedURL )
+ rtl_uString_release( strDecodedURL );
+
+ if ( osl_File_E_None == nError )
+ rtl_uString_assign( pustrPath, strTempPath );
+
+ if ( strTempPath )
+ rtl_uString_release( strTempPath );
+
+ /*
+ OSL_ENSURE_FILE( !nError, "osl_getSystemPathFromFileURL: \"%s\" is not a FileURL !!!", strURL );
+ */
+
+ return nError;
+}
+
+//#############################################
+oslFileError _osl_getFileURLFromSystemPath( rtl_uString* strPath, rtl_uString** pstrURL )
+{
+ oslFileError nError = osl_File_E_INVAL; /* Assume failure */
+ rtl_uString *strTempURL = NULL;
+ DWORD dwPathType = PATHTYPE_ERROR;
+
+ if (strPath)
+ dwPathType = IsValidFilePath(strPath, NULL, VALIDATEPATH_ALLOW_RELATIVE, NULL);
+
+ if (dwPathType)
+ {
+ rtl_uString *strTempPath = NULL;
+
+ if ( dwPathType & PATHTYPE_IS_LONGPATH )
+ {
+ rtl_uString *strBuffer = NULL;
+ sal_uInt32 nIgnore = 0;
+ sal_uInt32 nLength = 0;
+
+ /* the path has the longpath prefix, lets remove it */
+ switch ( dwPathType & PATHTYPE_MASK_TYPE )
+ {
+ case PATHTYPE_ABSOLUTE_UNC:
+ nIgnore = ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX_UNC ) - 1;
+ OSL_ENSURE( nIgnore == 8, "Unexpected long path UNC prefix!" );
+
+ /* generate the normal UNC path */
+ nLength = rtl_uString_getLength( strPath );
+ rtl_uString_newFromStr_WithLength( &strBuffer, strPath->buffer + nIgnore - 2, nLength - nIgnore + 2 );
+ strBuffer->buffer[0] = '\\';
+
+ rtl_uString_newReplace( &strTempPath, strBuffer, '\\', '/' );
+ rtl_uString_release( strBuffer );
+ break;
+
+ case PATHTYPE_ABSOLUTE_LOCAL:
+ nIgnore = ELEMENTS_OF_ARRAY( WSTR_LONG_PATH_PREFIX ) - 1;
+ OSL_ENSURE( nIgnore == 4, "Unexpected long path prefix!" );
+
+ /* generate the normal path */
+ nLength = rtl_uString_getLength( strPath );
+ rtl_uString_newFromStr_WithLength( &strBuffer, strPath->buffer + nIgnore, nLength - nIgnore );
+
+ rtl_uString_newReplace( &strTempPath, strBuffer, '\\', '/' );
+ rtl_uString_release( strBuffer );
+ break;
+
+ default:
+ OSL_ASSERT( "Unexpected long path format!" );
+ rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
+ break;
+ }
+ }
+ else
+ {
+ /* Replace backslashes */
+ rtl_uString_newReplace( &strTempPath, strPath, '\\', '/' );
+ }
+
+ switch ( dwPathType & PATHTYPE_MASK_TYPE )
+ {
+ case PATHTYPE_RELATIVE:
+ rtl_uString_assign( &strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ case PATHTYPE_ABSOLUTE_UNC:
+ rtl_uString_newFromAscii( &strTempURL, "file:" );
+ rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ case PATHTYPE_ABSOLUTE_LOCAL:
+ rtl_uString_newFromAscii( &strTempURL, "file:///" );
+ rtl_uString_newConcat( &strTempURL, strTempURL, strTempPath );
+ nError = osl_File_E_None;
+ break;
+ default:
+ break;
+ }
+
+ /* Release temp path */
+ rtl_uString_release( strTempPath );
+ }
+
+ if ( osl_File_E_None == nError )
+ {
+ rtl_String *strEncodedURL = NULL;
+
+ /* Encode the URL */
+ _osl_encodeURL( strTempURL, &strEncodedURL );
+
+ /* Provide URL via unicode string */
+ rtl_string2UString( pstrURL, rtl_string_getStr(strEncodedURL), rtl_string_getLength(strEncodedURL), RTL_TEXTENCODING_ASCII_US, OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*pstrURL != 0);
+ rtl_string_release( strEncodedURL );
+ }
+
+ /* Release temp URL */
+ if ( strTempURL )
+ rtl_uString_release( strTempURL );
+
+ /*
+ OSL_ENSURE_FILE( !nError, "osl_getFileURLFromSystemPath: \"%s\" is not a systemPath !!!", strPath );
+ */
+ return nError;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getFileURLFromSystemPath(
+ rtl_uString* ustrPath, rtl_uString** pustrURL )
+{
+ return _osl_getFileURLFromSystemPath( ustrPath, pustrURL );
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getSystemPathFromFileURL(
+ rtl_uString *ustrURL, rtl_uString **pustrPath)
+{
+ return _osl_getSystemPathFromFileURL( ustrURL, pustrPath, sal_True );
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_searchFileURL(
+ rtl_uString *ustrFileName,
+ rtl_uString *ustrSystemSearchPath,
+ rtl_uString **pustrPath)
+{
+ rtl_uString *ustrUNCPath = NULL;
+ rtl_uString *ustrSysPath = NULL;
+ oslFileError error;
+
+ /* First try to interpret the file name as an URL even a relative one */
+ error = _osl_getSystemPathFromFileURL( ustrFileName, &ustrUNCPath, sal_True );
+
+ /* So far we either have an UNC path or something invalid
+ Now create a system path */
+ if ( osl_File_E_None == error )
+ error = _osl_getSystemPathFromFileURL( ustrUNCPath, &ustrSysPath, sal_True );
+
+ if ( osl_File_E_None == error )
+ {
+ DWORD nBufferLength;
+ DWORD dwResult;
+ LPTSTR lpBuffer = NULL;
+ LPTSTR lpszFilePart;
+
+ /* Repeat calling SearchPath ...
+ Start with MAX_PATH for the buffer. In most cases this
+ will be enough and does not force the loop to runtwice */
+ dwResult = MAX_PATH;
+
+ do
+ {
+ /* If search path is empty use a NULL pointer instead according to MSDN documentation of SearchPath */
+ LPCTSTR lpszSearchPath = ustrSystemSearchPath && ustrSystemSearchPath->length ? reinterpret_cast<LPCTSTR>(ustrSystemSearchPath->buffer) : NULL;
+ LPCTSTR lpszSearchFile = reinterpret_cast<LPCTSTR>(ustrSysPath->buffer);
+
+ /* Allocate space for buffer according to previous returned count of required chars */
+ /* +1 is not neccessary if we follow MSDN documentation but for robustness we do so */
+ nBufferLength = dwResult + 1;
+ lpBuffer = lpBuffer ?
+ reinterpret_cast<LPTSTR>(rtl_reallocateMemory(lpBuffer, nBufferLength * sizeof(TCHAR))) :
+ reinterpret_cast<LPTSTR>(rtl_allocateMemory(nBufferLength * sizeof(TCHAR)));
+
+ dwResult = SearchPath( lpszSearchPath, lpszSearchFile, NULL, nBufferLength, lpBuffer, &lpszFilePart );
+ } while ( dwResult && dwResult >= nBufferLength );
+
+ /* ... until an error occures or buffer is large enough.
+ dwResult == nBufferLength can not happen according to documentation but lets be robust ;-) */
+
+ if ( dwResult )
+ {
+ rtl_uString_newFromStr( &ustrSysPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) );
+ error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath );
+ }
+ else
+ {
+ WIN32_FIND_DATA aFindFileData;
+ HANDLE hFind;
+
+ /* Somthing went wrong, perhaps the path was absolute */
+ error = oslTranslateFileError( GetLastError() );
+
+ hFind = FindFirstFile( reinterpret_cast<LPCTSTR>(ustrSysPath->buffer), &aFindFileData );
+
+ if ( IsValidHandle(hFind) )
+ {
+ error = osl_getFileURLFromSystemPath( ustrSysPath, pustrPath );
+ FindClose( hFind );
+ }
+ }
+
+ rtl_freeMemory( lpBuffer );
+ }
+
+ if ( ustrSysPath )
+ rtl_uString_release( ustrSysPath );
+
+ if ( ustrUNCPath )
+ rtl_uString_release( ustrUNCPath );
+
+ return error;
+}
+
+//#####################################################
+
+oslFileError SAL_CALL osl_getAbsoluteFileURL( rtl_uString* ustrBaseURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL )
+{
+ oslFileError eError;
+ rtl_uString *ustrRelSysPath = NULL;
+ rtl_uString *ustrBaseSysPath = NULL;
+
+ if ( ustrBaseURL && ustrBaseURL->length )
+ {
+ eError = _osl_getSystemPathFromFileURL( ustrBaseURL, &ustrBaseSysPath, sal_False );
+ OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with relative or invalid base URL" );
+
+ eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_True );
+ }
+ else
+ {
+ eError = _osl_getSystemPathFromFileURL( ustrRelativeURL, &ustrRelSysPath, sal_False );
+ OSL_ENSURE( osl_File_E_None == eError, "osl_getAbsoluteFileURL called with empty base URL and/or invalid relative URL" );
+ }
+
+ if ( !eError )
+ {
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ ::osl::LongPathBuffer< sal_Unicode > aCurrentDir( MAX_LONG_PATH );
+ LPTSTR lpFilePart = NULL;
+ DWORD dwResult;
+
+/*@@@ToDo
+ Bad, bad hack, this only works if the base path
+ really exists which is not necessary according
+ to RFC2396
+ The whole FileURL implementation should be merged
+ with the rtl/uri class.
+*/
+ if ( ustrBaseSysPath )
+ {
+ osl_acquireMutex( g_CurrentDirectoryMutex );
+
+ GetCurrentDirectoryW( aCurrentDir.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aCurrentDir) );
+ SetCurrentDirectoryW( reinterpret_cast<LPCWSTR>(ustrBaseSysPath->buffer) );
+ }
+
+ dwResult = GetFullPathNameW( reinterpret_cast<LPCWSTR>(ustrRelSysPath->buffer), aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), &lpFilePart );
+
+ if ( ustrBaseSysPath )
+ {
+ SetCurrentDirectoryW( ::osl::mingw_reinterpret_cast<LPCWSTR>(aCurrentDir) );
+
+ osl_releaseMutex( g_CurrentDirectoryMutex );
+ }
+
+ if ( dwResult )
+ {
+ if ( dwResult >= aBuffer.getBufSizeInSymbols() )
+ eError = osl_File_E_INVAL;
+ else
+ {
+ rtl_uString *ustrAbsSysPath = NULL;
+
+ rtl_uString_newFromStr( &ustrAbsSysPath, aBuffer );
+
+ eError = osl_getFileURLFromSystemPath( ustrAbsSysPath, pustrAbsoluteURL );
+
+ if ( ustrAbsSysPath )
+ rtl_uString_release( ustrAbsSysPath );
+ }
+ }
+ else
+ eError = oslTranslateFileError( GetLastError() );
+ }
+
+ if ( ustrBaseSysPath )
+ rtl_uString_release( ustrBaseSysPath );
+
+ if ( ustrRelSysPath )
+ rtl_uString_release( ustrRelSysPath );
+
+ return eError;
+}
+
+//#####################################################
+oslFileError SAL_CALL osl_getCanonicalName( rtl_uString *strRequested, rtl_uString **strValid )
+{
+ rtl_uString_newFromString(strValid, strRequested);
+ return osl_File_E_None;
+}
diff --git a/sal/osl/w32/file_url.h b/sal/osl/w32/file_url.h
new file mode 100644
index 000000000000..d9137c8c2fcc
--- /dev/null
+++ b/sal/osl/w32/file_url.h
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_OSL_FILE_URL_H
+#define INCLUDED_OSL_FILE_URL_H
+
+#include "sal/types.h"
+#include "rtl/ustring.h"
+#include "osl/file.h"
+
+#ifdef _MSC_VER
+#pragma warning(push,1)
+#endif
+
+#define WINDOWS_LEAN_AND_MEAN
+#include <windows.h>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PATHTYPE_ERROR 0
+#define PATHTYPE_RELATIVE 1
+#define PATHTYPE_ABSOLUTE_UNC 2
+#define PATHTYPE_ABSOLUTE_LOCAL 3
+#define PATHTYPE_MASK_TYPE 0xFF
+#define PATHTYPE_IS_VOLUME 0x0100
+#define PATHTYPE_IS_SERVER 0x0200
+#define PATHTYPE_IS_LONGPATH 0x0400
+
+#define VALIDATEPATH_NORMAL 0x0000
+#define VALIDATEPATH_ALLOW_WILDCARDS 0x0001
+#define VALIDATEPATH_ALLOW_ELLIPSE 0x0002
+#define VALIDATEPATH_ALLOW_RELATIVE 0x0004
+#define VALIDATEPATH_ALLOW_UNC 0x0008
+
+#define MAX_LONG_PATH 32767
+
+DWORD IsValidFilePath (
+ rtl_uString * path,
+ LPCTSTR * lppError,
+ DWORD dwFlags,
+ rtl_uString ** corrected
+);
+
+DWORD GetCaseCorrectPathName (
+ LPCTSTR lpszShortPath, // file name
+ LPTSTR lpszLongPath, // path buffer
+ DWORD cchBuffer, // size of path buffer
+ BOOL bCheckExistence
+);
+
+oslFileError _osl_getSystemPathFromFileURL (
+ rtl_uString * strURL,
+ rtl_uString ** pustrPath,
+ sal_Bool bAllowRelative
+);
+
+oslFileError _osl_getFileURLFromSystemPath (
+ rtl_uString * strPath,
+ rtl_uString ** pstrURL
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INCLUDED_OSL_FILE_URL_H */
diff --git a/sal/osl/w32/interlck.c b/sal/osl/w32/interlck.c
new file mode 100644
index 000000000000..14589e56184a
--- /dev/null
+++ b/sal/osl/w32/interlck.c
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/interlck.h>
+#include <osl/diagnose.h>
+
+extern int osl_isSingleCPU;
+
+/* For all Intel x86 above x486 we use a spezial inline assembler implementation.
+ The main reason is that WIN9? does not return the result of the operation.
+ Instead there is only returned a value greater than zero is the increment
+ result is greater than zero, but not the the result of the addition.
+ For Windows NT the native function could be used, because the correct result
+ is returned. Beacuse of simpler code maintance and performace reasons we use
+ on every x86-Windows-Platform the inline assembler implementation.
+*/
+
+/*****************************************************************************/
+/* osl_incrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
+#ifdef _M_IX86
+#ifdef __MINGW32__
+{
+ asm
+ (
+ " movl %0, %%ecx\n"
+ " movl $1, %%eax\n"
+ " movl %1, %%edx\n"
+ " cmpl $0, %%edx\n"
+ " je 1f\n"
+ " xadd %%eax, (%%ecx)\n"
+ " jmp 2f\n"
+ "1:\n"
+ " lock xadd %%eax, (%%ecx)\n"
+ "2:\n"
+ " incl %%eax\n"
+ ::"m"(pCount),"m"(osl_isSingleCPU)
+ );
+}
+#else
+#pragma warning(disable: 4035)
+{
+ __asm
+ {
+ mov ecx, pCount
+ mov eax, 1
+ mov edx, osl_isSingleCPU
+ cmp edx, 0
+ je is_not_single
+ xadd dword ptr [ecx],eax
+ jmp cont
+ is_not_single:
+ lock xadd dword ptr [ecx],eax
+ cont:
+ inc eax
+ }
+}
+#pragma warning(default: 4035)
+#endif
+#else
+#pragma message("WARNING: Using system InterlockedIncrement")
+{
+ return (InterlockedIncrement(pCount));
+}
+#endif
+
+/*****************************************************************************/
+/* osl_decrementInterlockedCount */
+/*****************************************************************************/
+oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
+#ifdef _M_IX86
+#ifdef __MINGW32__
+{
+ asm
+ (
+ " movl %0, %%ecx\n"
+ " orl $-1, %%eax\n"
+ " movl %1, %%edx\n"
+ " cmpl $0, %%edx\n"
+ " je 1f\n"
+ " xadd %%eax, (%%ecx)\n"
+ " jmp 2f\n"
+ "1:\n"
+ " lock xadd %%eax, (%%ecx)\n"
+ "2:\n"
+ " decl %%eax\n"
+ ::"m"(pCount),"m"(osl_isSingleCPU)
+ );
+}
+#else
+#pragma warning(disable: 4035)
+{
+ __asm
+ {
+ mov ecx, pCount
+ or eax, -1
+ mov edx, osl_isSingleCPU
+ cmp edx, 0
+ je is_not_single
+ xadd dword ptr [ecx],eax
+ jmp cont
+ is_not_single:
+ lock xadd dword ptr [ecx],eax
+ cont:
+ dec eax
+ }
+}
+#pragma warning(default: 4035)
+#endif
+#else
+#pragma message("WARNING: Using system InterlockedDecrement")
+{
+ return (InterlockedDecrement(pCount));
+}
+#endif
diff --git a/sal/osl/w32/libutil.c b/sal/osl/w32/libutil.c
new file mode 100644
index 000000000000..e00aef2e158d
--- /dev/null
+++ b/sal/osl/w32/libutil.c
@@ -0,0 +1,54 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+static BOOL g_bInit = FALSE;
+static DWORD g_dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
+
+DWORD GetPlatformId()
+{
+
+ if (!g_bInit)
+ {
+ OSVERSIONINFO aInfo;
+
+ aInfo.dwOSVersionInfoSize = sizeof(aInfo);
+ if (GetVersionEx(&aInfo))
+ g_dwPlatformId = aInfo.dwPlatformId;
+
+ g_bInit = TRUE;
+ }
+
+ return g_dwPlatformId;
+}
diff --git a/sal/osl/w32/module.cxx b/sal/osl/w32/module.cxx
new file mode 100644
index 000000000000..b730bd3347df
--- /dev/null
+++ b/sal/osl/w32/module.cxx
@@ -0,0 +1,480 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "system.h"
+#include <tlhelp32.h>
+
+#include "file_url.h"
+#include "path_helper.hxx"
+
+#include <osl/module.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <rtl/logfile.h>
+
+/*
+ under WIN32, we use the void* oslModule
+ as a WIN32 HANDLE (which is also a 32-bit value)
+*/
+
+/*****************************************************************************/
+/* osl_loadModule */
+/*****************************************************************************/
+oslModule SAL_CALL osl_loadModule(rtl_uString *strModuleName, sal_Int32 nRtldMode )
+{
+ HINSTANCE hInstance;
+ UINT errorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
+ rtl_uString* Module = NULL;
+ oslModule ret = 0;
+ oslFileError nError;
+
+ RTL_LOGFILE_TRACE1( "{ osl_loadModule start: %S", (LPTSTR)&strModuleName->buffer );
+
+ OSL_ASSERT(strModuleName);
+
+ nRtldMode = nRtldMode; /* avoid warnings */
+
+ nError = osl_getSystemPathFromFileURL(strModuleName, &Module);
+
+ if ( osl_File_E_None != nError )
+ rtl_uString_assign(&Module, strModuleName);
+
+ hInstance = LoadLibraryW(reinterpret_cast<LPCWSTR>(Module->buffer));
+ if (hInstance == NULL)
+ hInstance = LoadLibraryExW(reinterpret_cast<LPCWSTR>(Module->buffer), NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH);
+
+ if (hInstance <= (HINSTANCE)HINSTANCE_ERROR)
+ hInstance = 0;
+
+ ret = (oslModule) hInstance;
+ rtl_uString_release(Module);
+ SetErrorMode(errorMode);
+
+ RTL_LOGFILE_TRACE1( "} osl_loadModule end: %S", (LPTSTR)&strModuleName->buffer );
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* osl_getModuleHandle */
+/*****************************************************************************/
+
+sal_Bool SAL_CALL
+osl_getModuleHandle(rtl_uString *pModuleName, oslModule *pResult)
+{
+ HINSTANCE hInstance = GetModuleHandleW(reinterpret_cast<LPCWSTR>(pModuleName->buffer));
+ if( hInstance )
+ {
+ *pResult = (oslModule) hInstance;
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_unloadModule */
+/*****************************************************************************/
+void SAL_CALL osl_unloadModule(oslModule Module)
+{
+ FreeLibrary((HINSTANCE)Module);
+}
+
+/*****************************************************************************/
+/* osl_getSymbol */
+/*****************************************************************************/
+void* SAL_CALL osl_getSymbol(oslModule Module, rtl_uString *strSymbolName)
+{
+ /* casting from a function pointer to a data pointer is invalid
+ be in this case unavoidable because the API has to stay
+ compitable we need to keep this function which returns a
+ void* by definition */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4054)
+#endif
+ return (void*)(osl_getFunctionSymbol(Module, strSymbolName));
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+}
+
+/*****************************************************************************/
+/* osl_getFunctionSymbol */
+/*****************************************************************************/
+oslGenericFunction SAL_CALL osl_getFunctionSymbol( oslModule Module, rtl_uString *strSymbolName )
+{
+ rtl_String *symbolName = NULL;
+ oslGenericFunction address;
+
+ OSL_ASSERT(Module);
+ OSL_ASSERT(strSymbolName);
+
+ rtl_uString2String(
+ &symbolName,
+ strSymbolName->buffer,
+ strSymbolName->length,
+ RTL_TEXTENCODING_UTF8,
+ OUSTRING_TO_OSTRING_CVTFLAGS
+ );
+
+ address=osl_getAsciiFunctionSymbol(Module, rtl_string_getStr(symbolName));
+ rtl_string_release(symbolName);
+
+ return address;
+}
+
+/*****************************************************************************/
+/* osl_getAsciiFunctionSymbol */
+/*****************************************************************************/
+oslGenericFunction SAL_CALL
+osl_getAsciiFunctionSymbol( oslModule Module, const sal_Char *pSymbol )
+{
+ oslGenericFunction fncAddr = NULL;
+
+ if( pSymbol )
+ fncAddr=(oslGenericFunction)GetProcAddress((HINSTANCE) Module, pSymbol);
+
+ return fncAddr;
+}
+
+
+
+/*****************************************************************************/
+/* osl_addressGetModuleURL */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* Implementation for Windows 95, 98 and Me */
+/*****************************************************************************/
+
+/* Undefine because there is no explicit "A" definition */
+
+#ifdef MODULEENTRY32
+#undef MODULEENTRY32
+#endif
+
+#ifdef LPMODULEENTRY32
+#undef LPMODULEENTRY32
+#endif
+
+typedef HANDLE (WINAPI *CreateToolhelp32Snapshot_PROC)( DWORD dwFlags, DWORD th32ProcessID );
+typedef BOOL (WINAPI *Module32First_PROC)( HANDLE hSnapshot, LPMODULEENTRY32 lpme32 );
+typedef BOOL (WINAPI *Module32Next_PROC)( HANDLE hSnapshot, LPMODULEENTRY32 lpme32 );
+
+static sal_Bool SAL_CALL _osl_addressGetModuleURL_Windows( void *pv, rtl_uString **pustrURL )
+{
+ sal_Bool bSuccess = sal_False; /* Assume failure */
+ HMODULE hModKernel32 = GetModuleHandleA( "KERNEL32.DLL" );
+
+ if ( hModKernel32 )
+ {
+ CreateToolhelp32Snapshot_PROC lpfnCreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_PROC)GetProcAddress( hModKernel32, "CreateToolhelp32Snapshot" );
+ Module32First_PROC lpfnModule32First = (Module32First_PROC)GetProcAddress( hModKernel32, "Module32First" );
+ Module32Next_PROC lpfnModule32Next = (Module32Next_PROC)GetProcAddress( hModKernel32, "Module32Next" );
+
+ if ( lpfnCreateToolhelp32Snapshot && lpfnModule32First && lpfnModule32Next )
+ {
+ HANDLE hModuleSnap = NULL;
+ DWORD dwProcessId = GetCurrentProcessId();
+
+ // Take a snapshot of all modules in the specified process.
+
+ hModuleSnap = lpfnCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId );
+
+ if ( INVALID_HANDLE_VALUE != hModuleSnap )
+ {
+ MODULEENTRY32 me32 = {0};
+
+ // Fill the size of the structure before using it.
+
+ me32.dwSize = sizeof(MODULEENTRY32);
+
+ // Walk the module list of the process, and find the module of
+ // interest. Then copy the information to the buffer pointed
+ // to by lpMe32 so that it can be returned to the caller.
+
+ if ( lpfnModule32First(hModuleSnap, &me32) )
+ {
+ do
+ {
+ if ( (BYTE *)pv >= (BYTE *)me32.hModule && (BYTE *)pv < (BYTE *)me32.hModule + me32.modBaseSize )
+ {
+ rtl_uString *ustrSysPath = NULL;
+
+ rtl_string2UString( &ustrSysPath, me32.szExePath, strlen(me32.szExePath), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(ustrSysPath != NULL);
+ osl_getFileURLFromSystemPath( ustrSysPath, pustrURL );
+ rtl_uString_release( ustrSysPath );
+
+ bSuccess = sal_True;
+ }
+
+ } while ( !bSuccess && lpfnModule32Next( hModuleSnap, &me32 ) );
+ }
+
+
+ // Do not forget to clean up the snapshot object.
+
+ CloseHandle (hModuleSnap);
+ }
+
+ }
+ }
+
+ return bSuccess;
+}
+
+/***************************************************************************************/
+/* Implementation for Windows NT, 2K and XP (2K and XP could use the above method too) */
+/***************************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <imagehlp.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+typedef BOOL (WINAPI *SymInitialize_PROC)(
+ HANDLE hProcess,
+ LPSTR UserSearchPath,
+ BOOL fInvadeProcess
+ );
+
+typedef BOOL (WINAPI *SymCleanup_PROC)(
+ HANDLE hProcess
+ );
+
+typedef BOOL (WINAPI *SymGetModuleInfo_PROC)(
+ HANDLE hProcess,
+ DWORD dwAddr,
+ PIMAGEHLP_MODULE ModuleInfo
+ );
+
+/* Seems that IMAGEHLP.DLL is always availiable on NT 4. But MSDN from Platform SDK says Win 2K is required. MSDN from VS 6.0a says
+ it's O.K on NT 4 ???!!!
+ BTW: We are using ANSI function because not all version of IMAGEHLP.DLL contain Unicode support
+*/
+
+static sal_Bool SAL_CALL _osl_addressGetModuleURL_NT4( void *pv, rtl_uString **pustrURL )
+{
+ sal_Bool bSuccess = sal_False; /* Assume failure */
+
+ /* IMAGEHELP.DLL has a bug that it recursivly scans subdirectories of
+ the root when calling SymInitialize(), so we preferr DBGHELP.DLL
+ which exports the same symbols and is shipped with OOo */
+
+ HMODULE hModImageHelp = LoadLibrary( "DBGHELP.DLL" );
+
+ if ( !hModImageHelp )
+ hModImageHelp = LoadLibrary( "IMAGEHLP.DLL" );
+
+ if ( hModImageHelp )
+ {
+ SymGetModuleInfo_PROC lpfnSymGetModuleInfo;
+ SymInitialize_PROC lpfnSymInitialize;
+ SymCleanup_PROC lpfnSymCleanup;
+
+
+ lpfnSymInitialize = (SymInitialize_PROC)GetProcAddress( hModImageHelp, "SymInitialize" );
+ lpfnSymCleanup = (SymCleanup_PROC)GetProcAddress( hModImageHelp, "SymCleanup" );
+ lpfnSymGetModuleInfo = (SymGetModuleInfo_PROC)GetProcAddress( hModImageHelp, "SymGetModuleInfo" );
+
+
+ if ( lpfnSymInitialize && lpfnSymCleanup && lpfnSymGetModuleInfo )
+ {
+ IMAGEHLP_MODULE ModuleInfo;
+ ::osl::LongPathBuffer< sal_Char > aModuleFileName( MAX_LONG_PATH );
+ LPSTR lpSearchPath = NULL;
+
+ if ( GetModuleFileNameA( NULL, aModuleFileName, aModuleFileName.getBufSizeInSymbols() ) )
+ {
+ char *pLastBkSlash = strrchr( aModuleFileName, '\\' );
+
+ if (
+ pLastBkSlash &&
+ pLastBkSlash > (sal_Char*)aModuleFileName
+ && *(pLastBkSlash - 1) != ':'
+ && *(pLastBkSlash - 1) != '\\'
+ )
+ {
+ *pLastBkSlash = 0;
+ lpSearchPath = aModuleFileName;
+ }
+ }
+
+ lpfnSymInitialize( GetCurrentProcess(), lpSearchPath, TRUE );
+
+ ZeroMemory( &ModuleInfo, sizeof(ModuleInfo) );
+ ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
+
+ bSuccess = (sal_Bool)(!!lpfnSymGetModuleInfo( GetCurrentProcess(), (DWORD)pv, &ModuleInfo ));
+
+ if ( bSuccess )
+ {
+ /* #99182 On localized (non-english) NT4 and XP (!!!) for some libraries the LoadedImageName member of ModuleInfo isn't filled. Because
+ other members ModuleName and ImageName do not contain the full path we can cast the Member
+ BaseOfImage to a HMODULE (on NT it's the same) and use GetModuleFileName to retrieve the full
+ path of the loaded image */
+
+ if ( ModuleInfo.LoadedImageName[0] || GetModuleFileNameA( (HMODULE)ModuleInfo.BaseOfImage, ModuleInfo.LoadedImageName, sizeof(ModuleInfo.LoadedImageName) ) )
+ {
+ rtl_uString *ustrSysPath = NULL;
+
+ rtl_string2UString( &ustrSysPath, ModuleInfo.LoadedImageName, strlen(ModuleInfo.LoadedImageName), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
+ OSL_ASSERT(ustrSysPath != NULL);
+ osl_getFileURLFromSystemPath( ustrSysPath, pustrURL );
+ rtl_uString_release( ustrSysPath );
+ }
+ else
+ bSuccess = sal_False;
+ }
+
+ lpfnSymCleanup( GetCurrentProcess() );
+ }
+
+ FreeLibrary( hModImageHelp );
+ }
+
+ return bSuccess;
+}
+
+
+typedef struct _MODULEINFO {
+ LPVOID lpBaseOfDll;
+ DWORD SizeOfImage;
+ LPVOID EntryPoint;
+} MODULEINFO, *LPMODULEINFO;
+
+typedef BOOL (WINAPI *EnumProcessModules_PROC)(
+ HANDLE hProcess, // handle to the process
+ HMODULE * lphModule, // array to receive the module handles
+ DWORD cb, // size of the array
+ LPDWORD lpcbNeeded // receives the number of bytes returned
+);
+
+typedef BOOL (WINAPI *GetModuleInformation_PROC)(
+ HANDLE hProcess, // handle to the process
+ HMODULE hModule, // handle to the module
+ LPMODULEINFO lpmodinfo, // structure that receives information
+ DWORD cb // size of the structure
+);
+
+#define bufsizeof(buffer) (sizeof(buffer) / sizeof((buffer)[0]))
+
+/* This version can fail because PSAPI.DLL is not always part of NT 4 despite MSDN Libary 6.0a say so */
+
+static sal_Bool SAL_CALL _osl_addressGetModuleURL_NT( void *pv, rtl_uString **pustrURL )
+{
+ sal_Bool bSuccess = sal_False; /* Assume failure */
+ static HMODULE hModPsapi = NULL;
+
+ if ( !hModPsapi )
+ hModPsapi = LoadLibrary( "PSAPI.DLL" );
+
+ if ( hModPsapi )
+ {
+ EnumProcessModules_PROC lpfnEnumProcessModules = (EnumProcessModules_PROC)GetProcAddress( hModPsapi, "EnumProcessModules" );
+ GetModuleInformation_PROC lpfnGetModuleInformation = (GetModuleInformation_PROC)GetProcAddress( hModPsapi, "GetModuleInformation" );
+
+ if ( lpfnEnumProcessModules && lpfnGetModuleInformation )
+ {
+ DWORD cbNeeded = 0;
+ HMODULE *lpModules = NULL;
+ DWORD nModules = 0;
+ UINT iModule = 0;
+ MODULEINFO modinfo;
+
+ lpfnEnumProcessModules( GetCurrentProcess(), NULL, 0, &cbNeeded );
+
+ lpModules = (HMODULE *)_alloca( cbNeeded );
+ lpfnEnumProcessModules( GetCurrentProcess(), lpModules, cbNeeded, &cbNeeded );
+
+ nModules = cbNeeded / sizeof(HMODULE);
+
+ for ( iModule = 0; !bSuccess && iModule < nModules; iModule++ )
+ {
+ lpfnGetModuleInformation( GetCurrentProcess(), lpModules[iModule], &modinfo, sizeof(modinfo) );
+
+ if ( (BYTE *)pv >= (BYTE *)modinfo.lpBaseOfDll && (BYTE *)pv < (BYTE *)modinfo.lpBaseOfDll + modinfo.SizeOfImage )
+ {
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ rtl_uString *ustrSysPath = NULL;
+
+ GetModuleFileNameW( lpModules[iModule], ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), aBuffer.getBufSizeInSymbols() );
+
+ rtl_uString_newFromStr( &ustrSysPath, aBuffer );
+ osl_getFileURLFromSystemPath( ustrSysPath, pustrURL );
+ rtl_uString_release( ustrSysPath );
+
+ bSuccess = sal_True;
+ }
+ }
+ }
+
+ }
+
+ return bSuccess;
+}
+
+/*****************************************************************************/
+/* Dispatcher for osl_osl_addressGetModuleURL */
+/*****************************************************************************/
+
+sal_Bool SAL_CALL osl_getModuleURLFromAddress( void *pv, rtl_uString **pustrURL )
+{
+ /* Use ..._NT first because ..._NT4 is much slower */
+ if ( IS_NT )
+ return _osl_addressGetModuleURL_NT( pv, pustrURL ) || _osl_addressGetModuleURL_NT4( pv, pustrURL );
+ else
+ return _osl_addressGetModuleURL_Windows( pv, pustrURL );
+}
+
+/*****************************************************************************/
+/* osl_getModuleURLFromFunctionAddress */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_getModuleURLFromFunctionAddress( oslGenericFunction addr, rtl_uString ** ppLibraryUrl )
+{
+ /* casting a function pointer to a data pointer (void*) is
+ not allowed according to the C/C++ standards. In this case
+ it is unavoidable because we have to stay compatible we
+ cannot remove any function. */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4054)
+#endif
+ return osl_getModuleURLFromAddress((void*)addr, ppLibraryUrl);
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+}
+
+
diff --git a/sal/osl/w32/mutex.c b/sal/osl/w32/mutex.c
new file mode 100644
index 000000000000..db16459d7fe7
--- /dev/null
+++ b/sal/osl/w32/mutex.c
@@ -0,0 +1,206 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/mutex.h>
+#include <osl/diagnose.h>
+
+/*
+ Implementation notes:
+ The void* hidden by oslMutex points to a WIN32
+ CRITICAL_SECTION structure.
+*/
+
+typedef struct _oslMutexImpl {
+ CRITICAL_SECTION m_Mutex;
+ int m_Locks;
+ DWORD m_Owner;
+ DWORD m_Requests;
+} oslMutexImpl;
+
+static BOOL (WINAPI *lpfTryEnterCriticalSection)(LPCRITICAL_SECTION)
+ = (BOOL (WINAPI *)(LPCRITICAL_SECTION))0xFFFFFFFF;
+
+static CRITICAL_SECTION MutexLock;
+
+/*****************************************************************************/
+/* osl_createMutex */
+/*****************************************************************************/
+oslMutex SAL_CALL osl_createMutex(void)
+{
+ oslMutexImpl *pMutexImpl;
+
+ /* Window 95 does not support "TryEnterCriticalSection" */
+
+ if (lpfTryEnterCriticalSection ==
+ (BOOL (WINAPI *)(LPCRITICAL_SECTION))0xFFFFFFFF)
+ {
+ OSVERSIONINFO VersionInformation =
+
+ {
+ sizeof(OSVERSIONINFO),
+ 0,
+ 0,
+ 0,
+ 0,
+ "",
+ };
+
+ /* ts: Window 98 does not support "TryEnterCriticalSection" but export the symbol !!!
+ calls to that symbol always returns FALSE */
+ if (
+ GetVersionEx(&VersionInformation) &&
+ (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ )
+ {
+ lpfTryEnterCriticalSection = (BOOL (WINAPI *)(LPCRITICAL_SECTION))
+ GetProcAddress(GetModuleHandle("KERNEL32"),
+ "TryEnterCriticalSection");
+ }
+ else
+ {
+ lpfTryEnterCriticalSection = (BOOL (WINAPI *)(LPCRITICAL_SECTION))NULL;
+ }
+
+
+ InitializeCriticalSection(&MutexLock);
+ }
+
+ pMutexImpl= calloc(sizeof(oslMutexImpl), 1);
+
+ OSL_ASSERT(pMutexImpl); /* alloc successful? */
+
+ InitializeCriticalSection(&pMutexImpl->m_Mutex);
+
+ return (oslMutex)pMutexImpl;
+}
+
+/*****************************************************************************/
+/* osl_destroyMutex */
+/*****************************************************************************/
+void SAL_CALL osl_destroyMutex(oslMutex Mutex)
+{
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+
+ if (pMutexImpl)
+ {
+ DeleteCriticalSection(&pMutexImpl->m_Mutex);
+ free(pMutexImpl);
+ }
+}
+
+/*****************************************************************************/
+/* osl_acquireMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_acquireMutex(oslMutex Mutex)
+{
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+
+ OSL_ASSERT(Mutex);
+
+ if (lpfTryEnterCriticalSection == NULL)
+ {
+ EnterCriticalSection(&MutexLock);
+ pMutexImpl->m_Requests++;
+ LeaveCriticalSection(&MutexLock);
+
+ EnterCriticalSection(&pMutexImpl->m_Mutex);
+
+ EnterCriticalSection(&MutexLock);
+ pMutexImpl->m_Requests--;
+ if (pMutexImpl->m_Locks++ == 0)
+ pMutexImpl->m_Owner = GetCurrentThreadId();
+ LeaveCriticalSection(&MutexLock);
+ }
+ else
+ EnterCriticalSection(&pMutexImpl->m_Mutex);
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_tryToAcquireMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_tryToAcquireMutex(oslMutex Mutex)
+{
+ sal_Bool ret = sal_False;
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+
+ OSL_ASSERT(Mutex);
+
+ if (lpfTryEnterCriticalSection != NULL)
+ return (sal_Bool)(lpfTryEnterCriticalSection(&pMutexImpl->m_Mutex) != FALSE);
+ else
+ {
+ EnterCriticalSection(&MutexLock);
+
+ if ( ((pMutexImpl->m_Requests == 0) && (pMutexImpl->m_Locks == 0)) ||
+ (pMutexImpl->m_Owner == GetCurrentThreadId()) )
+ ret = osl_acquireMutex(Mutex);
+
+ LeaveCriticalSection(&MutexLock);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/* osl_releaseMutex */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_releaseMutex(oslMutex Mutex)
+{
+ oslMutexImpl *pMutexImpl = (oslMutexImpl *)Mutex;
+
+ OSL_ASSERT(Mutex);
+
+ if (lpfTryEnterCriticalSection == NULL)
+ {
+ EnterCriticalSection(&MutexLock);
+
+ if (--(pMutexImpl->m_Locks) == 0)
+ pMutexImpl->m_Owner = 0;
+
+ LeaveCriticalSection(&MutexLock);
+ }
+
+ LeaveCriticalSection(&pMutexImpl->m_Mutex);
+
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_getGlobalMutex */
+/*****************************************************************************/
+
+/* initialized in dllentry.c */
+oslMutex g_Mutex;
+
+oslMutex * SAL_CALL osl_getGlobalMutex(void)
+{
+ return &g_Mutex;
+}
diff --git a/sal/osl/w32/nlsupport.c b/sal/osl/w32/nlsupport.c
new file mode 100644
index 000000000000..ad9de5f8492c
--- /dev/null
+++ b/sal/osl/w32/nlsupport.c
@@ -0,0 +1,231 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <windows.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#include <wchar.h>
+
+#include <osl/mutex.h>
+#include <osl/nlsupport.h>
+#include <osl/diagnose.h>
+#include <osl/process.h>
+#include <rtl/tencinfo.h>
+
+struct EnumLocalesParams
+{
+ WCHAR Language[3];
+ WCHAR Country[3];
+ LCID Locale;
+};
+
+static DWORD g_dwTLSLocaleEncId = (DWORD) -1;
+
+/*****************************************************************************/
+/* callback function test
+/*
+/* osl_getTextEncodingFromLocale calls EnumSystemLocalesA, so that we don't
+/* need to provide a unicode wrapper for this function under Win9x
+/* that means the callback function has an ansi prototype and receives
+/* the locale strings as ansi strings
+/*****************************************************************************/
+
+BOOL CALLBACK EnumLocalesProcA( LPSTR lpLocaleStringA )
+{
+ struct EnumLocalesParams * params;
+
+ LCID localeId;
+ LPSTR pszEndA;
+
+ WCHAR langCode[4];
+
+ /* convert hex-string to LCID */
+ localeId = strtol( lpLocaleStringA, &pszEndA, 16 );
+
+ /* check params received via TLS */
+ params = (struct EnumLocalesParams *) TlsGetValue( g_dwTLSLocaleEncId );
+ if( NULL == params || '\0' == params->Language[0] )
+ return FALSE;
+
+ /*
+ get the ISO language code for this locale
+
+ remeber: we call the GetLocaleInfoW function
+ because the ansi version of this function returns
+ an error under WinNT/2000 when called with an
+ unicode only lcid
+ */
+ if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) )
+ {
+ WCHAR ctryCode[4];
+
+ /* continue if language code does not match */
+ if( 0 != wcscmp( langCode, params->Language ) )
+ return TRUE;
+
+ /* check if country code is set and equals the current locale */
+ if( '\0' != params->Country[0] && GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
+ {
+ /* save return value in TLS and break if found desired locale */
+ if( 0 == wcscmp( ctryCode, params->Country ) )
+ {
+ params->Locale = localeId;
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* fill with default values for that language */
+ LANGID langId = LANGIDFROMLCID( localeId );
+
+ /* exchange sublanguage with SUBLANG_NEUTRAL */
+ langId = MAKELANGID( PRIMARYLANGID( langId ), SUBLANG_NEUTRAL );
+
+ /* and use default sorting order */
+ params->Locale = MAKELCID( langId, SORT_DEFAULT );
+
+ return FALSE;
+ }
+ }
+
+ /* retry by going on */
+ return TRUE;
+}
+
+
+/*****************************************************************************/
+/* GetTextEncodingFromLCID
+/*****************************************************************************/
+
+rtl_TextEncoding GetTextEncodingFromLCID( LCID localeId )
+{
+ rtl_TextEncoding Encoding = RTL_TEXTENCODING_DONTKNOW;
+ WCHAR ansiCP[6];
+
+ /* query ansi codepage for given locale */
+ if( localeId && GetLocaleInfo( localeId, LOCALE_IDEFAULTANSICODEPAGE, ansiCP, 6 ) )
+ {
+ /* if GetLocaleInfo returns "0", it is a UNICODE only locale */
+ if( 0 != wcscmp( ansiCP, L"0" ) )
+ {
+ WCHAR *pwcEnd;
+ UINT codepage;
+
+ /* values returned from GetLocaleInfo are dezimal based */
+ codepage = wcstol( ansiCP, &pwcEnd, 10 );
+
+ /* find matching rtl encoding */
+ Encoding = rtl_getTextEncodingFromWindowsCodePage( codepage );
+ }
+ else
+ Encoding = RTL_TEXTENCODING_UNICODE;
+ }
+
+ return Encoding;
+}
+
+
+/*****************************************************************************/
+/* osl_getTextEncodingFromLocale
+/*****************************************************************************/
+
+rtl_TextEncoding SAL_CALL osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
+{
+ struct EnumLocalesParams params = { L"", L"", 0 };
+
+ /* initialise global TLS id */
+ if( (DWORD) -1 == g_dwTLSLocaleEncId )
+ {
+ oslMutex globalMutex = * osl_getGlobalMutex();
+
+ /* initializing must be thread save */
+ osl_acquireMutex( globalMutex );
+
+ if( (DWORD) -1 == g_dwTLSLocaleEncId )
+ g_dwTLSLocaleEncId = TlsAlloc();
+
+ osl_releaseMutex( globalMutex );
+ }
+
+ /* if pLocale is NULL, use process locale as default */
+ if( NULL == pLocale )
+ osl_getProcessLocale( &pLocale );
+
+ /* copy in parameters to structure */
+ if( pLocale && pLocale->Language )
+ {
+ wcscpy( params.Language, pLocale->Language->buffer );
+
+ if( pLocale->Country )
+ wcscpy( params.Country, pLocale->Country->buffer );
+
+ /* save pointer to local structure in TLS */
+ TlsSetValue( g_dwTLSLocaleEncId, &params );
+
+ /* enum all locales known to Windows */
+ EnumSystemLocalesA( EnumLocalesProcA, LCID_SUPPORTED );
+
+ /* use the LCID found in iteration */
+ return GetTextEncodingFromLCID( params.Locale );
+ }
+
+ return RTL_TEXTENCODING_DONTKNOW;
+}
+
+/*****************************************************************************/
+/* imp_getProcessLocale
+/*****************************************************************************/
+
+void _imp_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ WCHAR langCode[4];
+ WCHAR ctryCode[4];
+ LCID localeId;
+
+ OSL_ASSERT( ppLocale );
+
+ /* get the LCID to retrieve information from */
+ localeId = GetUserDefaultLCID();
+
+ /* call GetLocaleInfo to retrieve the iso codes */
+ if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) &&
+ GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
+ {
+ *ppLocale = rtl_locale_register( langCode, ctryCode, L"" );
+ }
+ else
+ {
+ *ppLocale = rtl_locale_register( L"C", L"", L"" );
+ }
+}
+
+
diff --git a/sal/osl/w32/path_helper.cxx b/sal/osl/w32/path_helper.cxx
new file mode 100644
index 000000000000..a43ff8bca1d8
--- /dev/null
+++ b/sal/osl/w32/path_helper.cxx
@@ -0,0 +1,118 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+/*******************************************************************
+ Includes
+ ******************************************************************/
+
+#include "path_helper.hxx"
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+
+#include <algorithm>
+#include <wchar.h>
+
+/*******************************************************************
+ Constants
+ ******************************************************************/
+
+const rtl::OUString BACKSLASH = rtl::OUString::createFromAscii("\\");
+const rtl::OUString SLASH = rtl::OUString::createFromAscii("/");
+
+/*******************************************************************
+ osl_systemPathEnsureSeparator
+ ******************************************************************/
+
+void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath)
+{
+ OSL_PRECOND(ppustrPath && (NULL != *ppustrPath), \
+ "osl_systemPathEnsureSeparator: Invalid parameter");
+
+ rtl::OUString path(*ppustrPath);
+ sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH));
+
+ if (i < (path.getLength()-1))
+ {
+ path += BACKSLASH;
+ rtl_uString_assign(ppustrPath, path.pData);
+ }
+
+ OSL_POSTCOND(path.lastIndexOf(BACKSLASH) == (path.getLength() - 1), \
+ "osl_systemPathEnsureSeparator: Post condition failed");
+}
+
+/*******************************************************************
+ osl_systemPathRemoveSeparator
+ ******************************************************************/
+
+void SAL_CALL osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath)
+{
+ rtl::OUString path(*ppustrPath);
+
+ if (!osl::systemPathIsLogicalDrivePattern(path))
+ {
+ sal_Int32 i = std::max<sal_Int32>(path.lastIndexOf(BACKSLASH), path.lastIndexOf(SLASH));
+
+ if (i > -1 && (i == (path.getLength() - 1)))
+ {
+ path = rtl::OUString(path.getStr(), path.getLength() - 1);
+ rtl_uString_assign(ppustrPath, path.pData);
+ }
+ }
+}
+
+/*******************************************************************
+ osl_is_logical_drive_pattern
+ ******************************************************************/
+
+// is [A-Za-z]:[/|\]\0
+const sal_Char* LDP = ":";
+const sal_Char* LDP_WITH_BACKSLASH = ":\\";
+const sal_Char* LDP_WITH_SLASH = ":/";
+
+// degenerated case returned by the Windows FileOpen dialog
+// when someone enters for instance "x:filename", the Win32
+// API accepts this case
+const sal_Char* LDP_WITH_DOT_BACKSLASH = ":.\\";
+
+sal_Int32 osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath)
+{
+ const sal_Unicode* p = rtl_uString_getStr(const_cast<rtl_uString*>(pustrPath));
+ if (iswalpha(*p++))
+ {
+ return ((0 == rtl_ustr_ascii_compare(p, LDP)) ||
+ (0 == rtl_ustr_ascii_compare(p, LDP_WITH_BACKSLASH)) ||
+ (0 == rtl_ustr_ascii_compare(p, LDP_WITH_SLASH)) ||
+ (0 == rtl_ustr_ascii_compare(p, LDP_WITH_DOT_BACKSLASH)));
+ }
+ return 0;
+}
+
+
diff --git a/sal/osl/w32/path_helper.h b/sal/osl/w32/path_helper.h
new file mode 100644
index 000000000000..79341f538667
--- /dev/null
+++ b/sal/osl/w32/path_helper.h
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _PATH_HELPER_H_
+#define _PATH_HELPER_H_
+
+#include <sal/types.h>
+#include <rtl/ustring.h>
+#include <osl/file.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************
+ osl_systemPathEnsureSeparator
+ Adds a trailing path separator to the given system path if not
+ already there and if the path is not the root path or a logical
+ drive alone
+ ******************************************************************/
+
+void osl_systemPathEnsureSeparator(/*inout*/ rtl_uString** ppustrPath);
+
+/*******************************************************************
+ osl_systemPathRemoveSeparator
+ Removes the last separator from the given system path if any and
+ if the path is not the root path '\'
+ ******************************************************************/
+
+void SAL_CALL osl_systemPathRemoveSeparator(/*inout*/ rtl_uString** ppustrPath);
+
+/*******************************************************************
+ osl_is_logical_drive_pattern
+ Returns whether a given path is only a logical drive pattern or not.
+ A logical drive pattern is something like "a:\", "c:\".
+ No logical drive pattern is something like "c:\test"
+ ******************************************************************/
+
+sal_Int32 osl_systemPathIsLogicalDrivePattern(/*in*/ const rtl_uString* pustrPath);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/sal/osl/w32/path_helper.hxx b/sal/osl/w32/path_helper.hxx
new file mode 100644
index 000000000000..d157b42aa428
--- /dev/null
+++ b/sal/osl/w32/path_helper.hxx
@@ -0,0 +1,118 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4800)
+#endif
+
+#ifndef _PATH_HELPER_HXX_
+#define _PATH_HELPER_HXX_
+
+#include "path_helper.h"
+#include <rtl/ustring.hxx>
+#include <rtl/allocator.hxx>
+
+namespace osl
+{
+
+/*******************************************************************
+ osl_systemPathEnsureSeparator
+ Adds a trailing path separator to the given system path if not
+ already there and if the path is not the root path or a logical
+ drive alone
+ ******************************************************************/
+
+inline void systemPathEnsureSeparator(/*inout*/ rtl::OUString& Path)
+{
+ osl_systemPathEnsureSeparator(&Path.pData);
+}
+
+/*******************************************************************
+ osl_systemPathRemoveSeparator
+ Removes the last separator from the given system path if any and
+ if the path is not the root path '\'
+ ******************************************************************/
+
+inline void systemPathRemoveSeparator(/*inout*/ rtl::OUString& Path)
+{
+ osl_systemPathRemoveSeparator(&Path.pData);
+}
+
+/*******************************************************************
+ osl_systemPathIsLogicalDrivePattern
+ ******************************************************************/
+
+inline bool systemPathIsLogicalDrivePattern(/*in*/ const rtl::OUString& path)
+{
+ return osl_systemPathIsLogicalDrivePattern(path.pData);
+}
+
+/*******************************************************************
+ LongPathBuffer
+ ******************************************************************/
+template< class T >
+class LongPathBuffer
+{
+ T* m_pBuffer;
+ sal_uInt32 m_nCharNum;
+
+ LongPathBuffer();
+ LongPathBuffer( const LongPathBuffer& );
+ LongPathBuffer& operator=( const LongPathBuffer& );
+
+public:
+ LongPathBuffer( sal_uInt32 nCharNum )
+ : m_pBuffer( reinterpret_cast<T*>( rtl_allocateMemory( nCharNum * sizeof( T ) ) ) )
+ , m_nCharNum( nCharNum )
+ {
+ OSL_ENSURE( m_pBuffer, "Can not allocate the buffer!" );
+ }
+
+ ~LongPathBuffer()
+ {
+ if ( m_pBuffer )
+ rtl_freeMemory( m_pBuffer );
+ m_pBuffer = 0;
+ }
+
+ sal_uInt32 getBufSizeInSymbols()
+ {
+ return m_nCharNum;
+ }
+
+ operator T* ()
+ {
+ return m_pBuffer;
+ }
+
+};
+
+ template< class U, class T > U mingw_reinterpret_cast(LongPathBuffer<T>& a) { return reinterpret_cast<U>(static_cast<T*>(a)); }
+
+} // end namespace osl
+
+#endif
diff --git a/sal/osl/w32/pipe.c b/sal/osl/w32/pipe.c
new file mode 100644
index 000000000000..bd5185a2ba2b
--- /dev/null
+++ b/sal/osl/w32/pipe.c
@@ -0,0 +1,636 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include "pipeimpl.h"
+
+#include <osl/pipe.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/mutex.h>
+#include <osl/semaphor.h>
+#include <osl/conditn.h>
+#include <osl/interlck.h>
+#include <osl/process.h>
+
+#include <rtl/alloc.h>
+#include <rtl/memory.h>
+
+#define PIPESYSTEM "\\\\.\\pipe\\"
+#define PIPEPREFIX "OSL_PIPE_"
+
+typedef struct
+{
+ sal_uInt32 m_Size;
+ sal_uInt32 m_ReadPos;
+ sal_uInt32 m_WritePos;
+ BYTE m_Data[1];
+
+} oslPipeBuffer;
+
+/*****************************************************************************/
+/* oslPipeImpl */
+/*****************************************************************************/
+
+struct oslPipeImpl {
+ oslInterlockedCount m_Reference;
+ HANDLE m_File;
+ HANDLE m_NamedObject;
+ PSECURITY_ATTRIBUTES m_Security;
+ HANDLE m_ReadEvent;
+ HANDLE m_WriteEvent;
+ HANDLE m_AcceptEvent;
+ rtl_uString* m_Name;
+ oslPipeError m_Error;
+ sal_Bool m_bClosed;
+};
+
+
+/*****************************************************************************/
+/* osl_create/destroy-PipeImpl */
+/*****************************************************************************/
+
+static oslInterlockedCount nPipes = 0;
+
+oslPipe __osl_createPipeImpl(void)
+{
+ oslPipe pPipe;
+
+ pPipe = (oslPipe) rtl_allocateZeroMemory(sizeof(struct oslPipeImpl));
+
+ pPipe->m_bClosed = sal_False;
+ pPipe->m_Reference = 0;
+ pPipe->m_Name = NULL;
+ pPipe->m_File = INVALID_HANDLE_VALUE;
+ pPipe->m_NamedObject = INVALID_HANDLE_VALUE;
+
+ pPipe->m_ReadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ pPipe->m_WriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ pPipe->m_AcceptEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ return pPipe;
+}
+
+void __osl_destroyPipeImpl(oslPipe pPipe)
+{
+ if (pPipe != NULL)
+ {
+ if ( pPipe->m_NamedObject != INVALID_HANDLE_VALUE && pPipe->m_NamedObject != NULL )
+ CloseHandle( pPipe->m_NamedObject );
+
+ if (pPipe->m_Security != NULL)
+ {
+ rtl_freeMemory(pPipe->m_Security->lpSecurityDescriptor);
+ rtl_freeMemory(pPipe->m_Security);
+ }
+
+ CloseHandle(pPipe->m_ReadEvent);
+ CloseHandle(pPipe->m_WriteEvent);
+ CloseHandle(pPipe->m_AcceptEvent);
+
+ if (pPipe->m_Name)
+ rtl_uString_release(pPipe->m_Name);
+
+ rtl_freeMemory(pPipe);
+ }
+}
+
+
+
+/*****************************************************************************/
+/* osl_createPipe */
+/*****************************************************************************/
+oslPipe SAL_CALL osl_createPipe(rtl_uString *strPipeName, oslPipeOptions Options,
+ oslSecurity Security)
+{
+ rtl_uString* name = NULL;
+ rtl_uString* path = NULL;
+ rtl_uString* temp = NULL;
+ oslPipe pPipe;
+
+ PSECURITY_ATTRIBUTES pSecAttr = NULL;
+
+ rtl_uString_newFromAscii(&path, PIPESYSTEM);
+ rtl_uString_newFromAscii(&name, PIPEPREFIX);
+
+ if ( /*IS_NT &&*/ Security)
+ {
+ rtl_uString *Ident = NULL;
+ rtl_uString *Delim = NULL;
+
+ OSL_VERIFY(osl_getUserIdent(Security, &Ident));
+ rtl_uString_newFromAscii(&Delim, "_");
+
+ rtl_uString_newConcat(&temp, name, Ident);
+ rtl_uString_newConcat(&name, temp, Delim);
+
+ rtl_uString_release(Ident);
+ rtl_uString_release(Delim);
+ }
+ else
+ {
+ if (Options & osl_Pipe_CREATE)
+ {
+ PSECURITY_DESCRIPTOR pSecDesc;
+
+ pSecDesc = (PSECURITY_DESCRIPTOR) rtl_allocateMemory(SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+ /* add a NULL disc. ACL to the security descriptor */
+ OSL_VERIFY(InitializeSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION));
+ OSL_VERIFY(SetSecurityDescriptorDacl(pSecDesc, TRUE, (PACL) NULL, FALSE));
+
+ pSecAttr = rtl_allocateMemory(sizeof(SECURITY_ATTRIBUTES));
+ pSecAttr->nLength = sizeof(SECURITY_ATTRIBUTES);
+ pSecAttr->lpSecurityDescriptor = pSecDesc;
+ pSecAttr->bInheritHandle = TRUE;
+ }
+ }
+
+ rtl_uString_assign(&temp, name);
+ rtl_uString_newConcat(&name, temp, strPipeName);
+
+ /* alloc memory */
+ pPipe= __osl_createPipeImpl();
+ osl_incrementInterlockedCount(&(pPipe->m_Reference));
+
+ /* build system pipe name */
+ rtl_uString_assign(&temp, path);
+ rtl_uString_newConcat(&path, temp, name);
+ rtl_uString_release(temp);
+ temp = NULL;
+
+ if (Options & osl_Pipe_CREATE)
+ {
+ SetLastError( ERROR_SUCCESS );
+
+ if ( IS_NT )
+ pPipe->m_NamedObject = CreateMutexW( NULL, FALSE, name->buffer );
+ else
+ {
+ LPSTR pszTempBuffer = NULL;
+ int nCharsNeeded;
+
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, name->buffer, name->length, NULL, 0, NULL, NULL );
+ pszTempBuffer = alloca( nCharsNeeded * sizeof(CHAR) );
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, name->buffer, name->length, pszTempBuffer, nCharsNeeded, NULL, NULL );
+ pszTempBuffer[nCharsNeeded-1] = 0;
+
+ pPipe->m_NamedObject = CreateMutexA( NULL, FALSE, pszTempBuffer );
+ }
+
+ if ( pPipe->m_NamedObject != INVALID_HANDLE_VALUE && pPipe->m_NamedObject != NULL )
+ {
+ if ( GetLastError() != ERROR_ALREADY_EXISTS )
+ {
+ pPipe->m_Security = pSecAttr;
+ rtl_uString_assign(&pPipe->m_Name, name);
+
+ if (IS_NT)
+ {
+ /* try to open system pipe */
+ pPipe->m_File = CreateNamedPipeW(
+ path->buffer,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
+ PIPE_UNLIMITED_INSTANCES,
+ 4096, 4096,
+ NMPWAIT_WAIT_FOREVER,
+ pPipe->m_Security);
+
+ if (pPipe->m_File != INVALID_HANDLE_VALUE)
+ {
+ rtl_uString_release( name );
+ rtl_uString_release( path );
+
+ return pPipe;
+ }
+ }
+ else /* Win 9x */
+ {
+ LPSTR pszTempBuffer = NULL;
+ int nCharsNeeded;
+
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, NULL, 0, NULL, NULL );
+ pszTempBuffer = alloca( nCharsNeeded * sizeof(CHAR) );
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, pszTempBuffer, nCharsNeeded, NULL, NULL );
+ pszTempBuffer[nCharsNeeded-1] = 0;
+
+ pPipe->m_File = CreateSimplePipe( pszTempBuffer );
+
+ if ( IsValidHandle(pPipe->m_File) )
+ {
+ rtl_uString_release( name );
+ rtl_uString_release( path );
+
+ return pPipe;
+ }
+ }
+ }
+ else
+ {
+ CloseHandle( pPipe->m_NamedObject );
+ pPipe->m_NamedObject = INVALID_HANDLE_VALUE;
+ }
+ }
+ }
+ else
+ {
+ if (IS_NT)
+ {
+ BOOL fPipeAvailable;
+
+ do
+ {
+ /* free instance should be available first */
+ fPipeAvailable = WaitNamedPipeW(path->buffer, NMPWAIT_WAIT_FOREVER);
+
+ /* first try to open system pipe */
+ if ( fPipeAvailable )
+ {
+ pPipe->m_File = CreateFileW(
+ path->buffer,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL);
+
+ if ( pPipe->m_File != INVALID_HANDLE_VALUE )
+ {
+ // We got it !
+ rtl_uString_release( name );
+ rtl_uString_release( path );
+
+ return (pPipe);
+ }
+ else
+ {
+ // Pipe instance maybe catched by another client -> try again
+ }
+ }
+ } while ( fPipeAvailable );
+ }
+ else /* Win 9x */
+ {
+ LPSTR pszTempBuffer = NULL;
+ int nCharsNeeded;
+
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, NULL, 0, NULL, NULL );
+ pszTempBuffer = alloca( nCharsNeeded * sizeof(CHAR) );
+ nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, pszTempBuffer, nCharsNeeded, NULL, NULL );
+ pszTempBuffer[nCharsNeeded-1] = 0;
+
+ pPipe->m_File = OpenSimplePipe( pszTempBuffer );
+
+ if ( IsValidHandle(pPipe->m_File) )
+ {
+ // We got it !
+ rtl_uString_release( name );
+ rtl_uString_release( path );
+
+ return (pPipe);
+ }
+ }
+ }
+
+ /* if we reach here something went wrong */
+ __osl_destroyPipeImpl(pPipe);
+
+ return NULL;
+}
+
+void SAL_CALL osl_acquirePipe( oslPipe pPipe )
+{
+ osl_incrementInterlockedCount( &(pPipe->m_Reference) );
+}
+
+void SAL_CALL osl_releasePipe( oslPipe pPipe )
+{
+// OSL_ASSERT( pPipe );
+
+ if( 0 == pPipe )
+ return;
+
+ if( 0 == osl_decrementInterlockedCount( &(pPipe->m_Reference) ) )
+ {
+ if( ! pPipe->m_bClosed )
+ osl_closePipe( pPipe );
+
+ __osl_destroyPipeImpl( pPipe );
+ }
+}
+
+void SAL_CALL osl_closePipe( oslPipe pPipe )
+{
+ if( pPipe && ! pPipe->m_bClosed )
+ {
+ pPipe->m_bClosed = sal_True;
+ if (IS_NT)
+ {
+ /* if we have a system pipe close it */
+ if (pPipe->m_File != INVALID_HANDLE_VALUE)
+ {
+ /* FlushFileBuffers(pPipe->m_File); */
+ DisconnectNamedPipe(pPipe->m_File);
+ CloseHandle(pPipe->m_File);
+ }
+ }
+ else
+ {
+ CloseSimplePipe( pPipe->m_File );
+ }
+
+ }
+}
+
+/*****************************************************************************/
+/* osl_acceptPipe */
+/*****************************************************************************/
+oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe)
+{
+ oslPipe pAcceptedPipe = NULL;
+
+ HANDLE Event;
+ OVERLAPPED os;
+
+ OSL_ASSERT(pPipe);
+
+ if (IS_NT)
+ {
+ DWORD nBytesTransfered;
+ rtl_uString* path = NULL;
+ rtl_uString* temp = NULL;
+
+ OSL_ASSERT (pPipe->m_File != INVALID_HANDLE_VALUE);
+
+ Event = pPipe->m_AcceptEvent;
+ rtl_zeroMemory(&os, sizeof(OVERLAPPED));
+ os.hEvent = pPipe->m_AcceptEvent;
+ ResetEvent(pPipe->m_AcceptEvent);
+
+ if ( !ConnectNamedPipe(pPipe->m_File, &os))
+ {
+ switch ( GetLastError() )
+ {
+ case ERROR_PIPE_CONNECTED: // Client already connected to pipe
+ case ERROR_NO_DATA: // Client was connected but has already closed pipe end
+ // should only appear in nonblocking mode but in fact does
+ // in blocking asynchronous mode.
+ break;
+ case ERROR_PIPE_LISTENING: // Only for nonblocking mode but see ERROR_NO_DATA
+ case ERROR_IO_PENDING: // This is normal if not client is connected yet
+ case ERROR_MORE_DATA: // Should not happen
+ // blocking call to accept
+ if( !GetOverlappedResult( pPipe->m_File, &os, &nBytesTransfered, TRUE ) )
+ {
+ // Possible error could be that between ConnectNamedPipe and GetOverlappedResult a connect
+ // took place.
+
+ switch ( GetLastError() )
+ {
+ case ERROR_PIPE_CONNECTED: // Pipe was already connected
+ case ERROR_NO_DATA: // Pipe was connected but client has already closed -> ver fast client ;-)
+ break; // Everything's fine !!!
+ default:
+ // Something went wrong
+ return 0;
+ }
+ }
+ break;
+ default: // All other error say that somethings going wrong.
+ return 0;
+ }
+ }
+
+
+ pAcceptedPipe = __osl_createPipeImpl();
+ OSL_ASSERT(pAcceptedPipe);
+
+ osl_incrementInterlockedCount(&(pAcceptedPipe->m_Reference));
+ rtl_uString_assign(&pAcceptedPipe->m_Name, pPipe->m_Name);
+ pAcceptedPipe->m_File = pPipe->m_File;
+
+ rtl_uString_newFromAscii(&temp, PIPESYSTEM);
+ rtl_uString_newConcat(&path, temp, pPipe->m_Name);
+ rtl_uString_release(temp);
+
+ // prepare for next accept
+ pPipe->m_File =
+ CreateNamedPipeW(path->buffer,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
+ PIPE_UNLIMITED_INSTANCES,
+ 4096, 4096,
+ NMPWAIT_WAIT_FOREVER,
+ pAcceptedPipe->m_Security);
+ rtl_uString_release( path );
+ }
+ else /* Win9x */
+ {
+ pAcceptedPipe = __osl_createPipeImpl();
+ OSL_ASSERT(pAcceptedPipe);
+
+ osl_incrementInterlockedCount(&(pAcceptedPipe->m_Reference));
+ rtl_uString_assign(&pAcceptedPipe->m_Name, pPipe->m_Name);
+ pAcceptedPipe->m_File = pPipe->m_File;
+
+ pAcceptedPipe->m_File = AcceptSimplePipeConnection( pPipe->m_File );
+ }
+
+ return pAcceptedPipe;
+}
+
+/*****************************************************************************/
+/* osl_receivePipe */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe,
+ void* pBuffer,
+ sal_Int32 BytesToRead)
+{
+ DWORD nBytes;
+
+ OSL_ASSERT(pPipe);
+
+ /* if we have a system pipe use it */
+ if ( IS_NT /*pPipe->m_File != INVALID_HANDLE_VALUE*/)
+ {
+ OVERLAPPED os;
+ rtl_zeroMemory(&os,sizeof(OVERLAPPED));
+ os.hEvent = pPipe->m_ReadEvent;
+
+ ResetEvent(pPipe->m_ReadEvent);
+
+ if (! ReadFile(pPipe->m_File, pBuffer, BytesToRead, &nBytes, &os) &&
+ ((GetLastError() != ERROR_IO_PENDING) ||
+ ! GetOverlappedResult(pPipe->m_File, &os, &nBytes, TRUE)))
+ {
+ DWORD lastError = GetLastError();
+
+ if (lastError == ERROR_MORE_DATA)
+ nBytes = BytesToRead;
+ else
+ {
+ if (lastError == ERROR_PIPE_NOT_CONNECTED)
+ nBytes = 0;
+ else
+ nBytes = (DWORD) -1;
+
+ pPipe->m_Error = osl_Pipe_E_ConnectionAbort;
+ }
+ }
+ }
+ else
+ {
+ BOOL fSuccess = ReadSimplePipe( pPipe->m_File, pBuffer, BytesToRead, &nBytes, TRUE );
+
+ if ( !fSuccess )
+ {
+ nBytes = 0;
+ pPipe->m_Error = osl_Pipe_E_ConnectionAbort;
+ }
+
+ }
+
+ return (nBytes);
+}
+
+/*****************************************************************************/
+/* osl_sendPipe */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe,
+ const void* pBuffer,
+ sal_Int32 BytesToSend)
+{
+ DWORD nBytes;
+ OSL_ASSERT(pPipe);
+
+ if (IS_NT/*pPipe->m_File != INVALID_HANDLE_VALUE*/)
+ {
+ OVERLAPPED os;
+ rtl_zeroMemory(&os, sizeof(OVERLAPPED));
+ os.hEvent = pPipe->m_WriteEvent;
+ ResetEvent(pPipe->m_WriteEvent);
+
+ if (! WriteFile(pPipe->m_File, pBuffer, BytesToSend, &nBytes, &os) &&
+ ((GetLastError() != ERROR_IO_PENDING) ||
+ ! GetOverlappedResult(pPipe->m_File, &os, &nBytes, TRUE)))
+ {
+ if (GetLastError() == ERROR_PIPE_NOT_CONNECTED)
+ nBytes = 0;
+ else
+ nBytes = (DWORD) -1;
+
+ pPipe->m_Error = osl_Pipe_E_ConnectionAbort;
+ }
+ }
+ else
+ {
+ BOOL fSuccess = WriteSimplePipe( pPipe->m_File, pBuffer, BytesToSend, &nBytes, TRUE );
+
+ if ( !fSuccess )
+ {
+ nBytes = 0;
+ pPipe->m_Error = osl_Pipe_E_ConnectionAbort;
+ }
+ }
+
+ return (nBytes);
+}
+
+sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n )
+{
+ /* loop until all desired bytes were send or an error occured */
+ sal_Int32 BytesSend= 0;
+ sal_Int32 BytesToSend= n;
+
+ OSL_ASSERT(pPipe);
+ while (BytesToSend > 0)
+ {
+ sal_Int32 RetVal;
+
+ RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend);
+
+ /* error occured? */
+ 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 occured */
+ sal_Int32 BytesRead= 0;
+ sal_Int32 BytesToRead= n;
+
+ OSL_ASSERT( pPipe );
+ while (BytesToRead > 0)
+ {
+ sal_Int32 RetVal;
+ RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToRead -= RetVal;
+ BytesRead += RetVal;
+ pBuffer= (sal_Char*)pBuffer + RetVal;
+ }
+ return BytesRead;
+}
+
+
+/*****************************************************************************/
+/* osl_getLastPipeError */
+/*****************************************************************************/
+oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe)
+{
+ oslPipeError Error;
+
+ if (pPipe != NULL)
+ {
+ Error = pPipe->m_Error;
+ pPipe->m_Error = osl_Pipe_E_None;
+ }
+ else
+ Error = osl_Pipe_E_NotFound;
+
+ return (Error);
+}
+
diff --git a/sal/osl/w32/pipeimpl.cxx b/sal/osl/w32/pipeimpl.cxx
new file mode 100644
index 000000000000..1d492115e8c5
--- /dev/null
+++ b/sal/osl/w32/pipeimpl.cxx
@@ -0,0 +1,785 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+# include "pipeimpl.h"
+
+#ifndef _INC_MALLOC
+# include <malloc.h>
+#endif
+
+#ifndef _INC_TCHAR
+# ifdef UNICODE
+# define _UNICODE
+# endif
+# include <tchar.h>
+#endif
+
+const TCHAR PIPE_NAME_PREFIX_MAPPING[] = TEXT("PIPE_FILE_MAPPING_");
+const TCHAR PIPE_NAME_PREFIX_SYNCHRONIZE[] = TEXT("PIPE_SYNCHRONIZE_MUTEX_");
+const TCHAR PIPE_NAME_PREFIX_CONNECTION[] = TEXT("PIPE_CONNECTION_SEMAPHORE_");
+
+const DWORD PIPE_BUFFER_SIZE = 4096;
+
+
+//============================================================================
+// PipeData
+//============================================================================
+
+struct PipeData
+{
+ DWORD dwProcessId;
+ HANDLE hReadPipe;
+ HANDLE hWritePipe;
+};
+
+//============================================================================
+// Pipe
+//============================================================================
+
+#ifdef UNICODE
+#define Pipe PipeW
+#define ClientPipe ClientPipeW
+#define ServerPipe ServerPipeW
+#else
+#define Pipe PipeA
+#define ClientPipe ClientPipeA
+#define ServerPipe ServerPipeA
+#endif
+
+class Pipe
+{
+protected:
+ HANDLE m_hReadPipe; // Handle to use for reading
+ HANDLE m_hWritePipe; // Handle to use for writing
+
+ Pipe( HANDLE hReadPipe, HANDLE hWritePipe );
+
+ static HANDLE CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner );
+ static HANDLE CreatePipeDataMapping( LPCTSTR lpName );
+ static HANDLE OpenPipeDataMapping( LPCTSTR lpName );
+ static HANDLE CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumcount );
+
+public:
+ Pipe( const Pipe& );
+ const Pipe& operator = ( const Pipe& );
+ virtual ~Pipe();
+
+ virtual bool Close();
+ virtual bool Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait = true );
+ virtual bool Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait = true );
+
+ virtual Pipe *AcceptConnection()
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return NULL;
+ }
+
+ void * operator new( size_t nBytes )
+ {
+ return HeapAlloc( GetProcessHeap(), 0, nBytes );
+ }
+
+ void operator delete( void *ptr )
+ {
+ HeapFree( GetProcessHeap(), 0, ptr );
+ }
+
+ bool is() const
+ {
+ return (FALSE != HeapValidate( GetProcessHeap(), 0, this ));
+ }
+
+};
+
+//============================================================================
+// ClientPipe
+//============================================================================
+
+class ClientPipe : public Pipe
+{
+protected:
+ ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe );
+public:
+ static ClientPipe* Create( LPCTSTR lpName );
+};
+
+//============================================================================
+// ServerPipe
+//============================================================================
+
+class ServerPipe : public Pipe
+{
+protected:
+ HANDLE m_hMapping;
+ HANDLE m_hSynchronize;
+ LPTSTR m_lpName;
+
+ ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe );
+public:
+ virtual ~ServerPipe();
+
+ static ServerPipe *Create( LPCTSTR lpName );
+
+ virtual Pipe *AcceptConnection();
+};
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeDataMapping( LPCTSTR lpName )
+{
+ HANDLE hMapping = NULL;
+ LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
+
+ if ( lpMappingName )
+ {
+ _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
+ _tcscat( lpMappingName, lpName );
+
+ LPTSTR lpMappingFileName = (LPTSTR)alloca( MAX_PATH * sizeof(TCHAR) );
+
+ if ( lpMappingFileName )
+ {
+ DWORD nChars = GetTempPath( MAX_PATH, lpMappingFileName );
+
+ if ( MAX_PATH + _tcslen(lpName) < nChars + 1 )
+ {
+ lpMappingFileName = (LPTSTR)alloca( (nChars + 1 + _tcslen(lpName)) * sizeof(TCHAR) );
+ if ( lpMappingFileName )
+ nChars = GetTempPath( nChars, lpMappingFileName );
+ else
+ {
+ nChars = 0;
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ }
+ }
+
+ if ( nChars )
+ {
+ _tcscat( lpMappingFileName, lpMappingName );
+
+ HANDLE hFile = CreateFile(
+ lpMappingFileName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
+ NULL );
+
+ if ( IsValidHandle(hFile) )
+ {
+ hMapping = CreateFileMapping(
+ (HANDLE)hFile,
+ (LPSECURITY_ATTRIBUTES)NULL,
+ PAGE_READWRITE,
+ 0,
+ sizeof(PipeData),
+ lpMappingName );
+
+ CloseHandle( hFile );
+ }
+ }
+ }
+ else
+ SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+ }
+
+ return hMapping;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::OpenPipeDataMapping( LPCTSTR lpName )
+{
+ HANDLE hMapping = NULL;
+ LPTSTR lpMappingName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_MAPPING) );
+
+ if ( lpMappingName )
+ {
+ _tcscpy( lpMappingName, PIPE_NAME_PREFIX_MAPPING );
+ _tcscat( lpMappingName, lpName );
+
+ hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpMappingName );
+ }
+
+ return hMapping;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeDataMutex( LPCTSTR lpName, BOOL bInitialOwner )
+{
+ HANDLE hMutex = NULL;
+ LPTSTR lpMutexName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_SYNCHRONIZE) );
+
+ if ( lpMutexName )
+ {
+ _tcscpy( lpMutexName, PIPE_NAME_PREFIX_SYNCHRONIZE );
+ _tcscat( lpMutexName, lpName );
+
+ hMutex = CreateMutex( NULL, bInitialOwner, lpMutexName );
+ }
+
+ return hMutex;
+}
+
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+
+HANDLE Pipe::CreatePipeConnectionSemaphore( LPCTSTR lpName, LONG lInitialCount, LONG lMaximumCount )
+{
+ HANDLE hSemaphore = NULL;
+ LPTSTR lpSemaphoreName = (LPTSTR)alloca( _tcslen(lpName) * sizeof(TCHAR) + sizeof(PIPE_NAME_PREFIX_CONNECTION) );
+
+ if ( lpSemaphoreName )
+ {
+ _tcscpy( lpSemaphoreName, PIPE_NAME_PREFIX_CONNECTION );
+ _tcscat( lpSemaphoreName, lpName );
+
+ hSemaphore = CreateSemaphore( NULL, lInitialCount, lMaximumCount, lpSemaphoreName );
+ }
+
+ return hSemaphore;
+}
+
+
+//----------------------------------------------------------------------------
+// Pipe copy ctor
+//----------------------------------------------------------------------------
+
+Pipe::Pipe( const Pipe& rPipe ) :
+m_hReadPipe( INVALID_HANDLE_VALUE ),
+m_hWritePipe( INVALID_HANDLE_VALUE )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+}
+
+//----------------------------------------------------------------------------
+// Pipe assignment operator
+//----------------------------------------------------------------------------
+
+const Pipe& Pipe::operator = ( const Pipe& rPipe )
+{
+ Close();
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ rPipe.m_hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+// Pipe ctor
+//----------------------------------------------------------------------------
+
+Pipe::Pipe( HANDLE hReadPipe, HANDLE hWritePipe ) :
+m_hReadPipe( INVALID_HANDLE_VALUE ),
+m_hWritePipe( INVALID_HANDLE_VALUE )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hReadPipe,
+ GetCurrentProcess(),
+ &m_hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hWritePipe,
+ GetCurrentProcess(),
+ &m_hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+}
+
+//----------------------------------------------------------------------------
+// Pipe dtor
+//----------------------------------------------------------------------------
+
+Pipe::~Pipe()
+{
+ Close();
+}
+
+//----------------------------------------------------------------------------
+// Pipe Close
+//----------------------------------------------------------------------------
+
+bool Pipe::Close()
+{
+ bool fSuccess = false; // Assume failure
+
+ if ( IsValidHandle(m_hReadPipe) )
+ {
+ CloseHandle( m_hReadPipe );
+ m_hReadPipe = INVALID_HANDLE_VALUE;
+ }
+
+ if ( IsValidHandle(m_hWritePipe) )
+ {
+ CloseHandle( m_hWritePipe );
+ m_hWritePipe = INVALID_HANDLE_VALUE;
+ }
+
+ return fSuccess;
+}
+
+//----------------------------------------------------------------------------
+// Pipe Write
+//----------------------------------------------------------------------------
+
+bool Pipe::Write( LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, bool bWait )
+{
+ DWORD dwBytesAvailable = 0;
+ BOOL fSuccess = TRUE;
+
+ if ( !bWait )
+ fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
+
+ if ( fSuccess )
+ {
+ if ( !bWait && dwBytesToWrite > PIPE_BUFFER_SIZE - dwBytesAvailable )
+ dwBytesToWrite = PIPE_BUFFER_SIZE - dwBytesAvailable ;
+
+ return !!WriteFile( m_hWritePipe, lpBuffer, dwBytesToWrite, lpBytesWritten, NULL );
+ }
+
+ return false;
+}
+
+//----------------------------------------------------------------------------
+// Pipe Read
+//----------------------------------------------------------------------------
+
+bool Pipe::Read( LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, bool bWait )
+{
+ DWORD dwBytesAvailable = 0;
+ BOOL fSuccess = TRUE;
+
+ if ( !bWait )
+ fSuccess = PeekNamedPipe( m_hReadPipe, NULL, 0, NULL, &dwBytesAvailable, NULL );
+
+ if ( fSuccess )
+ {
+ if ( bWait || dwBytesAvailable )
+ return !!ReadFile( m_hReadPipe, lpBuffer, dwBytesToRead, lpBytesRead, NULL );
+ else
+ {
+ *lpBytesRead = 0;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+
+//----------------------------------------------------------------------------
+// Client pipe dtor
+//----------------------------------------------------------------------------
+
+ClientPipe::ClientPipe( HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe )
+{
+}
+
+//----------------------------------------------------------------------------
+// Client pipe creation
+//----------------------------------------------------------------------------
+
+ClientPipe *ClientPipe::Create( LPCTSTR lpName )
+{
+ ClientPipe *pPipe = NULL; // Assume failure
+
+ HANDLE hMapping = OpenPipeDataMapping( lpName );
+
+ if ( IsValidHandle(hMapping) )
+ {
+ PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
+
+ if ( pData )
+ {
+ HANDLE hSourceProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, pData->dwProcessId );
+
+ if ( IsValidHandle(hSourceProcess) )
+ {
+ BOOL fSuccess;
+ HANDLE hReadPipe = INVALID_HANDLE_VALUE, hWritePipe = INVALID_HANDLE_VALUE;
+
+ fSuccess = DuplicateHandle(
+ hSourceProcess,
+ pData->hReadPipe,
+ GetCurrentProcess(),
+ &hReadPipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ fSuccess = fSuccess && DuplicateHandle(
+ hSourceProcess,
+ pData->hWritePipe,
+ GetCurrentProcess(),
+ &hWritePipe,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ if ( fSuccess )
+ pPipe = new ClientPipe( hReadPipe, hWritePipe );
+
+ if ( IsValidHandle(hWritePipe) )
+ CloseHandle( hWritePipe );
+
+ if ( IsValidHandle(hReadPipe) )
+ CloseHandle( hReadPipe );
+
+ HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( lpName, 0, 1 );
+
+ ReleaseSemaphore( hConnectionRequest, 1, NULL );
+
+ CloseHandle( hConnectionRequest );
+
+ CloseHandle( hSourceProcess );
+ }
+
+ UnmapViewOfFile( pData );
+ }
+
+ CloseHandle( hMapping );
+ }
+
+ return pPipe;
+}
+
+
+
+//----------------------------------------------------------------------------
+// ServerPipe ctor
+//----------------------------------------------------------------------------
+
+ServerPipe::ServerPipe( LPCTSTR lpName, HANDLE hMapping, HANDLE hSynchronize, HANDLE hReadPipe, HANDLE hWritePipe ) : Pipe( hReadPipe, hWritePipe ),
+m_hMapping( NULL ),
+m_hSynchronize( NULL ),
+m_lpName( NULL )
+{
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hMapping,
+ GetCurrentProcess(),
+ &m_hMapping,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS );
+
+ DuplicateHandle(
+ GetCurrentProcess(),
+ hSynchronize,
+ GetCurrentProcess(),
+ &m_hSynchronize,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS
+ );
+ m_lpName = new TCHAR[_tcslen(lpName) + 1];
+ if ( m_lpName )
+ _tcscpy( m_lpName, lpName );
+}
+
+//----------------------------------------------------------------------------
+// ServerPipe dtor
+//----------------------------------------------------------------------------
+
+ServerPipe::~ServerPipe()
+{
+ if ( IsValidHandle(m_hMapping) )
+ CloseHandle( m_hMapping );
+ if ( m_lpName )
+ delete[]m_lpName;
+}
+
+//----------------------------------------------------------------------------
+// ServerPipe AcceptConnection
+//----------------------------------------------------------------------------
+
+Pipe *ServerPipe::AcceptConnection()
+{
+ Pipe *pPipe = NULL; // Assume failure;
+
+ HANDLE hConnectionRequest = CreatePipeConnectionSemaphore( m_lpName, 0, 1 );
+
+ if ( WAIT_OBJECT_0 == WaitForSingleObject( hConnectionRequest, INFINITE ) )
+ {
+ pPipe = new Pipe( *this );
+ Close();
+
+ // Create new inbound Pipe
+
+ HANDLE hClientWritePipe = NULL, hServerReadPipe = NULL;
+
+ BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+
+ if ( fSuccess )
+ {
+ // Create outbound pipe
+
+ HANDLE hClientReadPipe = NULL, hServerWritePipe = NULL;
+
+ if ( CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE ) )
+ {
+ m_hReadPipe = hServerReadPipe;
+ m_hWritePipe = hServerWritePipe;
+
+ PipeData *pData = (PipeData *)MapViewOfFile( m_hMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(PipeData) );
+
+ HANDLE hSynchronize = CreatePipeDataMutex( m_lpName, TRUE );
+
+ CloseHandle( pData->hReadPipe );
+ CloseHandle( pData->hWritePipe );
+
+ pData->hReadPipe = hClientReadPipe;
+ pData->hWritePipe = hClientWritePipe;
+
+ ReleaseMutex( hSynchronize );
+
+ CloseHandle( hSynchronize );
+
+ }
+ else
+ {
+ CloseHandle( hClientWritePipe );
+ CloseHandle( hServerWritePipe );
+ }
+ }
+
+ ReleaseMutex( hConnectionRequest );
+ }
+
+ CloseHandle( hConnectionRequest );
+
+ return pPipe;
+}
+
+//----------------------------------------------------------------------------
+// Pipe creation
+//----------------------------------------------------------------------------
+
+ServerPipe *ServerPipe::Create( LPCTSTR lpName )
+{
+ ServerPipe *pPipe = NULL;
+
+ HANDLE hMapping = CreatePipeDataMapping( lpName );
+
+ if ( IsValidHandle(hMapping) )
+ {
+ if ( ERROR_FILE_EXISTS != GetLastError() )
+ {
+ HANDLE hSynchronize = CreatePipeDataMutex( lpName, FALSE);
+
+ WaitForSingleObject( hSynchronize, INFINITE );
+
+ PipeData *pData = (PipeData*)MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
+
+ if ( pData )
+ {
+
+ // Initialize pipe data
+
+ pData->dwProcessId = 0;
+ pData->hReadPipe = NULL;
+ pData->hWritePipe = NULL;
+
+ // Create inbound pipe
+
+ HANDLE hServerReadPipe = NULL, hClientWritePipe = NULL;
+
+ BOOL fSuccess = CreatePipe( &hServerReadPipe, &hClientWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+ if ( fSuccess )
+ {
+ // Create outbound pipe
+
+ HANDLE hServerWritePipe = NULL, hClientReadPipe = NULL;
+
+ fSuccess = CreatePipe( &hClientReadPipe, &hServerWritePipe, NULL, PIPE_BUFFER_SIZE );
+
+ if ( fSuccess )
+ {
+ pData->dwProcessId = GetCurrentProcessId();
+ pData->hReadPipe = hClientReadPipe;
+ pData->hWritePipe = hClientWritePipe;
+ pPipe = new ServerPipe( lpName, hMapping, hSynchronize, hServerReadPipe, hServerWritePipe );
+
+ CloseHandle( hServerWritePipe );
+ CloseHandle( hServerReadPipe );
+ }
+ else
+ {
+ CloseHandle( hServerReadPipe );
+ CloseHandle( hClientWritePipe );
+ }
+ }
+
+ UnmapViewOfFile( pData );
+ }
+
+ ReleaseMutex( hSynchronize );
+ CloseHandle( hSynchronize );
+ }
+
+ CloseHandle( hMapping );
+ }
+
+ return pPipe;
+}
+
+
+//----------------------------------------------------------------------------
+// C style API
+//----------------------------------------------------------------------------
+
+const TCHAR LOCAL_PIPE_PREFIX[] = TEXT("\\\\.\\PIPE\\" );
+
+extern "C" HANDLE WINAPI CreateSimplePipe( LPCTSTR lpName )
+{
+ int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
+ if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
+ lpName += nPrefixLen;
+ return (HANDLE)ServerPipe::Create( lpName );
+}
+
+extern "C" HANDLE WINAPI OpenSimplePipe( LPCTSTR lpName )
+{
+ int nPrefixLen = _tcslen( LOCAL_PIPE_PREFIX );
+ if ( 0 == _tcsnicmp( lpName, LOCAL_PIPE_PREFIX, nPrefixLen ) )
+ lpName += nPrefixLen;
+ return (HANDLE)ClientPipe::Create( lpName );
+}
+
+extern "C" HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return (HANDLE)pPipe->AcceptConnection();
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return NULL;
+ }
+}
+
+extern "C" BOOL WINAPI WaitForSimplePipe( LPCTSTR /*lpName*/, DWORD /*dwTimeOut*/ )
+{
+ return FALSE;
+}
+
+extern "C" BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return pPipe->Write( lpBuffer, dwBytesToWrite, lpBytesWritten, bWait );
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
+
+extern "C" BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ return pPipe->Read( lpBuffer, dwBytesToRead, lpBytesRead, bWait );
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
+
+extern "C" BOOL WINAPI CloseSimplePipe( HANDLE hPipe )
+{
+ Pipe *pPipe = (Pipe *)hPipe;
+
+ if ( pPipe->is() )
+ {
+ delete pPipe;
+ return TRUE;
+ }
+ else
+ {
+ SetLastError( ERROR_INVALID_HANDLE );
+ return FALSE;
+ }
+}
diff --git a/sal/osl/w32/pipeimpl.h b/sal/osl/w32/pipeimpl.h
new file mode 100644
index 000000000000..83f678f6c49d
--- /dev/null
+++ b/sal/osl/w32/pipeimpl.h
@@ -0,0 +1,88 @@
+#ifndef _PIPEIMPL_H_
+#define _PIPEIMPL_H_
+
+#ifndef _WINDOWS_
+# ifdef _MSC_VER
+# pragma warning(push,1) /* disable warnings within system headers */
+# endif
+# include <windows.h>
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif
+#endif
+
+#ifndef _INC_MALLOC
+# include <malloc.h>
+#endif
+
+#ifndef _INC_TCHAR
+# ifdef UNICODE
+# define _UNICODE
+# endif
+# include <tchar.h>
+#endif
+
+#define EXPORT_PIPE_API
+
+//============================================================================
+// Helper functions
+//============================================================================
+
+// Because the value of an invalid HANDLE returned by API functions differs
+// between different functions and differs on different Windows platforms,
+// this function checks wether the handle has a meaningfull value.
+#ifndef __cplusplus
+
+#define IsValidHandle( handle ) ((DWORD)(handle) + 1 > 1)
+
+#else
+
+inline bool IsValidHandle( HANDLE handle )
+{
+ return INVALID_HANDLE_VALUE != handle && NULL != handle;
+}
+
+extern "C" {
+
+#endif // __cplusplus
+
+
+EXPORT_PIPE_API HANDLE WINAPI CreateSimplePipeA( LPCSTR lpName );
+EXPORT_PIPE_API HANDLE WINAPI CreateSimplePipeW( LPCWSTR lpName );
+
+#ifdef UNICODE
+#define CreateSimplePipe CreateSimplePipeW
+#else
+#define CreateSimplePipe CreateSimplePipeA
+#endif
+
+EXPORT_PIPE_API HANDLE WINAPI OpenSimplePipeA( LPCSTR lpName );
+EXPORT_PIPE_API HANDLE WINAPI OpenSimplePipeW( LPCWSTR lpName );
+
+#ifdef UNICODE
+#define OpenSimplePipe OpenSimplePipeW
+#else
+#define OpenSimplePipe OpenSimplePipeA
+#endif
+
+EXPORT_PIPE_API HANDLE WINAPI AcceptSimplePipeConnection( HANDLE hPipe );
+
+EXPORT_PIPE_API BOOL WINAPI WaitForSimplePipeA( LPCSTR lpName, DWORD dwTimeOut );
+EXPORT_PIPE_API BOOL WINAPI WaitForSimplePipeW( LPCWSTR lpName, DWORD dwTimeOut );
+
+#ifdef UNICODE
+#define WaitForSimplePipe WaitForSimplePipeW
+#else
+#define WaitForSimplePipe WaitForSimplePipeA
+#endif
+
+
+EXPORT_PIPE_API BOOL WINAPI WriteSimplePipe( HANDLE hPipe, LPCVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten, BOOL bWait );
+EXPORT_PIPE_API BOOL WINAPI ReadSimplePipe( HANDLE hPipe, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesRead, BOOL bWait );
+EXPORT_PIPE_API BOOL WINAPI CloseSimplePipe( HANDLE hPipe );
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PIPEIMPL_H_
diff --git a/sal/osl/w32/process.cxx b/sal/osl/w32/process.cxx
new file mode 100644
index 000000000000..96187be7e203
--- /dev/null
+++ b/sal/osl/w32/process.cxx
@@ -0,0 +1,620 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#define UNICODE
+#include "system.h"
+#ifdef _MSC_VER
+#pragma warning(push,1) /* disable warnings within system headers */
+#endif
+#include <shellapi.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#include <osl/diagnose.h>
+#include <osl/security.h>
+#include <osl/nlsupport.h>
+#include <osl/mutex.h>
+#include <osl/thread.h>
+
+#include "procimpl.h"
+#include "sockimpl.h"
+#include "file_url.h"
+#include "path_helper.hxx"
+#include <rtl/ustrbuf.h>
+#include <rtl/alloc.h>
+
+/***************************************************************************
+ * Process.
+ ***************************************************************************/
+
+oslProcessError SAL_CALL osl_terminateProcess(oslProcess Process)
+{
+ if (Process == NULL)
+ return osl_Process_E_Unknown;
+
+ if (TerminateProcess(((oslProcessImpl*)Process)->m_hProcess, 0))
+ return osl_Process_E_None;
+
+
+ return osl_Process_E_Unknown;
+}
+
+/***************************************************************************/
+
+oslProcess SAL_CALL osl_getProcess(oslProcessIdentifier Ident)
+{
+ oslProcessImpl* pProcImpl;
+ HANDLE hProcess = OpenProcess(
+ STANDARD_RIGHTS_REQUIRED | PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, (DWORD)Ident);
+
+ if (hProcess)
+ {
+ pProcImpl = reinterpret_cast< oslProcessImpl*>( rtl_allocateMemory(sizeof(oslProcessImpl)) );
+ pProcImpl->m_hProcess = hProcess;
+ pProcImpl->m_IdProcess = Ident;
+ }
+ else
+ pProcImpl = NULL;
+
+ return (pProcImpl);
+}
+
+/***************************************************************************/
+
+void SAL_CALL osl_freeProcessHandle(oslProcess Process)
+{
+ if (Process != NULL)
+ {
+ CloseHandle(((oslProcessImpl*)Process)->m_hProcess);
+
+ rtl_freeMemory((oslProcessImpl*)Process);
+ }
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_getProcessInfo(oslProcess Process, oslProcessData Fields,
+ oslProcessInfo* pInfo)
+{
+ HANDLE hProcess;
+ DWORD IdProcess;
+
+ if (Process == NULL)
+ {
+ hProcess = GetCurrentProcess();
+ IdProcess = GetCurrentProcessId();
+ }
+ else
+ {
+ hProcess = ((oslProcessImpl*)Process)->m_hProcess;
+ IdProcess = ((oslProcessImpl*)Process)->m_IdProcess;
+ }
+
+ if (! pInfo || (pInfo->Size != sizeof(oslProcessInfo)))
+ return osl_Process_E_Unknown;
+
+ pInfo->Fields = 0;
+
+ if (Fields & osl_Process_IDENTIFIER)
+ {
+ pInfo->Ident = IdProcess;
+ pInfo->Fields |= osl_Process_IDENTIFIER;
+ }
+
+ if (Fields & osl_Process_EXITCODE)
+ {
+ if (GetExitCodeProcess(hProcess, &(pInfo->Code)) && (pInfo->Code != STILL_ACTIVE))
+ pInfo->Fields |= osl_Process_EXITCODE;
+ }
+
+ if (Fields & osl_Process_HEAPUSAGE)
+ {
+ void* lpAddress=0;
+ MEMORY_BASIC_INFORMATION Info;
+
+ pInfo->HeapUsage = 0;
+
+ do
+ {
+ if (VirtualQueryEx(hProcess, lpAddress, &Info, sizeof(Info)) == 0)
+ break;
+
+ if ((Info.State == MEM_COMMIT) && (Info.Type == MEM_PRIVATE))
+ pInfo->HeapUsage += Info.RegionSize;
+
+ lpAddress = (LPBYTE)lpAddress + Info.RegionSize;
+ }
+ while (lpAddress < (void *)0x80000000); // 2GB address space
+
+ pInfo->Fields |= osl_Process_HEAPUSAGE;
+ }
+
+ if (Fields & osl_Process_CPUTIMES)
+ {
+ FILETIME CreationTime, ExitTime, KernelTime, UserTime;
+
+ if (GetProcessTimes(hProcess, &CreationTime, &ExitTime,
+ &KernelTime, &UserTime))
+ {
+ __int64 Value;
+
+ Value = *((__int64 *)&UserTime);
+ pInfo->UserTime.Seconds = (unsigned long) (Value / 10000000L);
+ pInfo->UserTime.Nanosec = (unsigned long)((Value % 10000000L) * 100);
+
+ Value = *((__int64 *)&KernelTime);
+ pInfo->SystemTime.Seconds = (unsigned long) (Value / 10000000L);
+ pInfo->SystemTime.Nanosec = (unsigned long)((Value % 10000000L) * 100);
+
+ pInfo->Fields |= osl_Process_CPUTIMES;
+ }
+ }
+
+ return (pInfo->Fields == Fields) ? osl_Process_E_None : osl_Process_E_Unknown;
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_joinProcess(oslProcess Process)
+{
+ return osl_joinProcessWithTimeout(Process, NULL);
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_joinProcessWithTimeout(oslProcess Process, const TimeValue* pTimeout)
+{
+ DWORD timeout = INFINITE;
+ oslProcessError osl_error = osl_Process_E_None;
+ DWORD ret;
+
+ if (NULL == Process)
+ return osl_Process_E_Unknown;
+
+ if (pTimeout)
+ timeout = pTimeout->Seconds * 1000 + pTimeout->Nanosec / 1000000L;
+
+ ret = WaitForSingleObject(((oslProcessImpl*)Process)->m_hProcess, timeout);
+
+ if (WAIT_FAILED == ret)
+ osl_error = osl_Process_E_Unknown;
+ else if (WAIT_TIMEOUT == ret)
+ osl_error = osl_Process_E_TimedOut;
+
+ return osl_error;
+}
+
+/***************************************************************************
+ * osl_bootstrap_getExecutableFile_Impl().
+ *
+ * @internal
+ * @see rtl_bootstrap
+ * @see #i37371#
+ *
+ ***************************************************************************/
+
+extern "C" oslProcessError SAL_CALL osl_bootstrap_getExecutableFile_Impl (
+ rtl_uString ** ppFileURL
+) SAL_THROW_EXTERN_C()
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ DWORD buflen = 0;
+
+ if ((buflen = GetModuleFileNameW (0, ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), aBuffer.getBufSizeInSymbols())) > 0)
+ {
+ rtl_uString * pAbsPath = 0;
+ rtl_uString_newFromStr_WithLength (&(pAbsPath), aBuffer, buflen);
+ if (pAbsPath)
+ {
+ /* Convert from path to url. */
+ if (osl_getFileURLFromSystemPath (pAbsPath, ppFileURL) == osl_File_E_None)
+ {
+ /* Success. */
+ result = osl_Process_E_None;
+ }
+ rtl_uString_release (pAbsPath);
+ }
+ }
+
+ return (result);
+}
+
+/***************************************************************************
+ * Command Line Arguments.
+ ***************************************************************************/
+
+struct CommandArgs_Impl
+{
+ sal_uInt32 m_nCount;
+ rtl_uString ** m_ppArgs;
+};
+
+static struct CommandArgs_Impl g_command_args =
+{
+ 0,
+ 0
+};
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable: 4100 )
+#endif
+static rtl_uString ** osl_createCommandArgs_Impl (int argc, char ** argv)
+{
+ rtl_uString ** ppArgs =
+ (rtl_uString**)rtl_allocateZeroMemory (argc * sizeof(rtl_uString*));
+ if (ppArgs != 0)
+ {
+ int i;
+ int nArgs;
+ LPWSTR *wargv = CommandLineToArgvW( GetCommandLineW(), &nArgs );
+ OSL_ASSERT( nArgs == argc );
+ for (i = 0; i < nArgs; i++)
+ {
+ /* Convert to unicode */
+ rtl_uString_newFromStr( &(ppArgs[i]), reinterpret_cast<const sal_Unicode*>(wargv[i]) );
+ }
+ if (ppArgs[0] != 0)
+ {
+ /* Ensure absolute path */
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ DWORD dwResult = 0;
+
+ dwResult = SearchPath (
+ 0, reinterpret_cast<LPCWSTR>(ppArgs[0]->buffer), L".exe", aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer), 0);
+ if ((0 < dwResult) && (dwResult < aBuffer.getBufSizeInSymbols()))
+ {
+ /* Replace argv[0] with it's absolute path */
+ rtl_uString_newFromStr_WithLength(
+ &(ppArgs[0]), aBuffer, dwResult);
+ }
+ }
+ if (ppArgs[0] != 0)
+ {
+ /* Convert to FileURL, see @ osl_getExecutableFile() */
+ rtl_uString * pResult = 0;
+ osl_getFileURLFromSystemPath (ppArgs[0], &pResult);
+ if (pResult != 0)
+ {
+ rtl_uString_assign (&(ppArgs[0]), pResult);
+ rtl_uString_release (pResult);
+ }
+ }
+ }
+ return (ppArgs);
+
+}
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_getExecutableFile( rtl_uString **ppustrFile )
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ osl_acquireMutex (*osl_getGlobalMutex());
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > 0)
+ {
+ /* CommandArgs set. Obtain arv[0]. */
+ rtl_uString_assign (ppustrFile, g_command_args.m_ppArgs[0]);
+ result = osl_Process_E_None;
+ }
+ osl_releaseMutex (*osl_getGlobalMutex());
+
+ return (result);
+}
+
+/***************************************************************************/
+
+sal_uInt32 SAL_CALL osl_getCommandArgCount(void)
+{
+ sal_uInt32 result = 0;
+
+ osl_acquireMutex (*osl_getGlobalMutex());
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > 0)
+ {
+ /* We're not counting argv[0] here. */
+ result = g_command_args.m_nCount - 1;
+ }
+ osl_releaseMutex (*osl_getGlobalMutex());
+
+ return (result);
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_getCommandArg( sal_uInt32 nArg, rtl_uString **strCommandArg)
+{
+ oslProcessError result = osl_Process_E_NotFound;
+
+ osl_acquireMutex (*osl_getGlobalMutex());
+ OSL_ASSERT(g_command_args.m_nCount > 0);
+ if (g_command_args.m_nCount > (nArg + 1))
+ {
+ /* We're not counting argv[0] here. */
+ rtl_uString_assign (strCommandArg, g_command_args.m_ppArgs[nArg + 1]);
+ result = osl_Process_E_None;
+ }
+ osl_releaseMutex (*osl_getGlobalMutex());
+
+ return (result);
+}
+
+/***************************************************************************/
+
+void SAL_CALL osl_setCommandArgs (int argc, char ** argv)
+{
+ OSL_ASSERT(argc > 0);
+ osl_acquireMutex (*osl_getGlobalMutex());
+ if (g_command_args.m_nCount == 0)
+ {
+ rtl_uString** ppArgs = osl_createCommandArgs_Impl (argc, argv);
+ if (ppArgs != 0)
+ {
+ g_command_args.m_nCount = argc;
+ g_command_args.m_ppArgs = ppArgs;
+ }
+ }
+ osl_releaseMutex (*osl_getGlobalMutex());
+}
+
+/***************************************************************************
+ * Environment
+ ***************************************************************************/
+/*
+ #109941# because of a bug in the M$ unicows library we have to
+ allocate a buffer large enough to hold the requested environment
+ variable instead of testing for the required size. This wastes
+ some stack space, maybe we should revoke this work around if
+ unicows library is fixed.
+*/
+#define ENV_BUFFER_SIZE (32*1024-1)
+
+oslProcessError SAL_CALL osl_getEnvironment(rtl_uString *ustrVar, rtl_uString **ustrValue)
+{
+ WCHAR buff[ENV_BUFFER_SIZE];
+
+ if (GetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(ustrVar->buffer), buff, ENV_BUFFER_SIZE) > 0)
+ {
+ rtl_uString_newFromStr(ustrValue, reinterpret_cast<const sal_Unicode*>(buff));
+ return osl_Process_E_None;
+ }
+ return osl_Process_E_Unknown;
+}
+
+/***************************************************************************
+ * Current Working Directory.
+ ***************************************************************************/
+
+extern "C" oslMutex g_CurrentDirectoryMutex;
+
+oslProcessError SAL_CALL osl_getProcessWorkingDir( rtl_uString **pustrWorkingDir )
+{
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ DWORD dwLen = 0;
+
+
+ osl_acquireMutex( g_CurrentDirectoryMutex );
+ dwLen = GetCurrentDirectory( aBuffer.getBufSizeInSymbols(), ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer) );
+ osl_releaseMutex( g_CurrentDirectoryMutex );
+
+ if ( dwLen && dwLen < aBuffer.getBufSizeInSymbols() )
+ {
+ oslFileError eError;
+ rtl_uString *ustrTemp = NULL;;
+
+ rtl_uString_newFromStr_WithLength( &ustrTemp, aBuffer, dwLen );
+ eError = osl_getFileURLFromSystemPath( ustrTemp, pustrWorkingDir );
+
+ rtl_uString_release( ustrTemp );
+
+ if ( osl_File_E_None != eError )
+ return osl_Process_E_Unknown;
+ else
+ return osl_Process_E_None;
+ }
+ else
+ return osl_Process_E_Unknown;
+}
+
+/***************************************************************************
+ * Process Locale.
+ ***************************************************************************/
+
+extern "C" void _imp_getProcessLocale( rtl_Locale ** ppLocale );
+
+static rtl_Locale * g_theProcessLocale = NULL;
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_getProcessLocale( rtl_Locale ** ppLocale )
+{
+ osl_acquireMutex( *osl_getGlobalMutex() );
+
+ /* determine the users default locale */
+ if( NULL == g_theProcessLocale )
+ _imp_getProcessLocale( &g_theProcessLocale );
+
+ /* or return the cached value */
+ *ppLocale = g_theProcessLocale;
+
+ osl_releaseMutex( *osl_getGlobalMutex() );
+ return osl_Process_E_None;
+}
+
+/***************************************************************************/
+
+oslProcessError SAL_CALL osl_setProcessLocale( rtl_Locale * pLocale )
+{
+ osl_acquireMutex( *osl_getGlobalMutex() );
+
+ /* check if locale is supported */
+ if( RTL_TEXTENCODING_DONTKNOW == osl_getTextEncodingFromLocale( pLocale ) )
+ return osl_Process_E_Unknown;
+
+ /* just remember the locale here */
+ g_theProcessLocale = pLocale;
+
+ osl_releaseMutex( *osl_getGlobalMutex() );
+ return osl_Process_E_None;
+}
+
+/************************************************
+ * Portal send/receive interface implementation
+ ************************************************/
+
+static sal_Bool ReadPipe(oslPipe hPipe,
+ void* pBuffer,
+ sal_Int32 BytesToRead,
+ sal_Int32* nBytes)
+{
+ *nBytes = osl_receivePipe(hPipe, pBuffer, BytesToRead);
+ OSL_TRACE("tried to recieve %d, recieved %d.\n",
+ BytesToRead, *nBytes);
+ return (sal_Bool)((*nBytes >= 0) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
+}
+
+static sal_Bool WritePipe(oslPipe hPipe,
+ void* pBuffer,
+ sal_Int32 BytesToSend,
+ sal_Int32* nBytes)
+{
+ *nBytes = osl_sendPipe(hPipe, pBuffer, BytesToSend);
+ OSL_TRACE("tried to send %d, sent %d\n",
+ BytesToSend, *nBytes);
+ return (sal_Bool)((*nBytes == BytesToSend) && (osl_getLastPipeError(hPipe) == osl_Pipe_E_None));
+}
+
+sal_Bool SAL_CALL osl_sendResourcePipe(oslPipe hPipe, oslSocket pSocket)
+{
+ sal_Bool bRet = sal_False;
+ sal_Int32 bytes = 0;
+
+ /* duplicate handle on this other side ->
+ receive remote process
+ duplicate handle and send it */
+ DWORD remoteProcessID = 0;
+ HANDLE fd = (HANDLE)pSocket->m_Socket;
+ oslDescriptorType code = osl_Process_TypeSocket;
+
+ OSL_TRACE("osl_sendResourcePipe: enter...");
+
+ if (ReadPipe(hPipe, &remoteProcessID, sizeof(remoteProcessID), &bytes))
+ {
+ HANDLE hRemoteProc = OpenProcess(PROCESS_DUP_HANDLE,
+ FALSE,
+ remoteProcessID);
+
+ if (hRemoteProc != (HANDLE)NULL)
+ {
+ HANDLE newFd;
+
+ if (DuplicateHandle(GetCurrentProcess(),
+ fd,
+ hRemoteProc,
+ &newFd,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ if (
+ WritePipe(hPipe, &code, sizeof(code), &bytes) &&
+ WritePipe(hPipe, &newFd, sizeof(fd), &bytes)
+ )
+ bRet = sal_True;
+ }
+
+ CloseHandle(hRemoteProc);
+ }
+ }
+
+ if (bRet)
+ {
+ sal_Int32 commitCode;
+ OSL_TRACE("osl_sendResourcePipe: handle sent successfully, verify...\n");
+
+ if (
+ !ReadPipe(hPipe, &commitCode, sizeof(commitCode), &bytes) ||
+ (commitCode <= 0)
+ )
+ bRet = sal_False;
+ }
+
+ OSL_TRACE("osl_sendResourcePipe: exit... %d\n", bRet);
+ return(bRet);
+}
+
+
+oslSocket SAL_CALL osl_receiveResourcePipe(oslPipe hPipe)
+{
+ sal_Bool bRet = sal_False;
+ sal_Int32 bytes = 0;
+ sal_Int32 commitCode;
+ oslSocket pSocket = NULL;
+
+ /* duplicate handle on the other side ->
+ send my process id receive duplicated handle */
+ HANDLE fd = INVALID_HANDLE_VALUE;
+ DWORD myProcessID = GetCurrentProcessId();
+ oslDescriptorType code = osl_Process_TypeNone;
+
+ OSL_TRACE("osl_receiveResourcePipe: enter...\n");
+
+ if (
+ WritePipe(hPipe, &myProcessID, sizeof(myProcessID), &bytes) &&
+ ReadPipe(hPipe, &code, sizeof(code), &bytes) &&
+ ReadPipe(hPipe, &fd, sizeof(fd), &bytes)
+ )
+ {
+ if (code == osl_Process_TypeSocket)
+ {
+ pSocket = __osl_createSocketImpl((SOCKET)fd);
+ bRet = sal_True;
+ }
+ else
+ {
+ OSL_TRACE("osl_receiveResourcePipe: UKNOWN\n");
+ bRet = sal_False;
+ }
+ }
+
+ if (bRet)
+ commitCode = 1;
+ else
+ commitCode = 0;
+
+ WritePipe(hPipe, &commitCode, sizeof(commitCode), &bytes);
+
+ OSL_TRACE("osl_receiveResourcePipe: exit... %d, %p\n", bRet, pSocket);
+
+ return pSocket;
+}
diff --git a/sal/osl/w32/procimpl.cxx b/sal/osl/w32/procimpl.cxx
new file mode 100644
index 000000000000..fc04d5b84a8f
--- /dev/null
+++ b/sal/osl/w32/procimpl.cxx
@@ -0,0 +1,606 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#define UNICODE
+#define _UNICODE
+
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# ifdef _MSC_VER
+# pragma warning(push,1) /* disable warnings within system headers */
+# endif
+# include <windows.h>
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif
+# include <tchar.h>
+# undef WIN32_LEAN_AND_MEAN
+#endif
+#include "procimpl.h"
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include "secimpl.h"
+#include "rtl/allocator.hxx"
+#include <osl/file.hxx>
+
+#include <list>
+#include <vector>
+#include <algorithm>
+#include <string>
+
+//#################################################
+extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle( HANDLE hFile, sal_uInt32 uFlags );
+
+//#################################################
+const sal_Unicode NAME_VALUE_SEPARATOR = TEXT('=');
+const sal_Char* SPACE = " ";
+const rtl::OUString ENV_COMSPEC = rtl::OUString::createFromAscii("COMSPEC");
+const rtl::OUString QUOTE = rtl::OUString::createFromAscii("\"");
+
+namespace /* private */
+{
+ //#################################################
+ typedef std::list<rtl::OUString, rtl::Allocator<rtl::OUString> > string_container_t;
+ typedef string_container_t::iterator string_container_iterator_t;
+ typedef string_container_t::const_iterator string_container_const_iterator_t;
+ typedef std::pair<string_container_iterator_t, string_container_iterator_t> iterator_pair_t;
+ typedef std::vector<sal_Unicode, rtl::Allocator<sal_Unicode> > environment_container_t;
+
+ //#################################################
+ /* Function object that compares two strings that are
+ expected to be environment variables in the form
+ "name=value". Only the 'name' part will be compared.
+ The comparison is in upper case and returns true
+ if the first of both strings is less than the
+ second one. */
+ struct less_environment_variable :
+ public std::binary_function<rtl::OUString, rtl::OUString, bool>
+ {
+ bool operator() (const rtl::OUString& lhs, const rtl::OUString& rhs) const
+ {
+ OSL_ENSURE((lhs.indexOf(NAME_VALUE_SEPARATOR) > -1) && \
+ (rhs.indexOf(NAME_VALUE_SEPARATOR) > -1), \
+ "Malformed environment variable");
+
+ // Windows compares environment variables uppercase
+ // so we do it, too
+ return (rtl_ustr_compare_WithLength(
+ lhs.toAsciiUpperCase().pData->buffer,
+ lhs.indexOf(NAME_VALUE_SEPARATOR),
+ rhs.toAsciiUpperCase().pData->buffer,
+ rhs.indexOf(NAME_VALUE_SEPARATOR)) < 0);
+ }
+ };
+
+ //#################################################
+ /* Function object used by for_each algorithm to
+ calculate the sum of the length of all strings
+ in a string container. */
+ class sum_of_string_lengths
+ {
+ public:
+ //--------------------------------
+ sum_of_string_lengths() : sum_(0) {}
+
+ //--------------------------------
+ void operator() (const rtl::OUString& string)
+ {
+ OSL_ASSERT(string.getLength());
+
+ // always include the terminating '\0'
+ if (string.getLength())
+ sum_ += string.getLength() + 1;
+ }
+
+ //--------------------------------
+ operator size_t () const
+ {
+ return sum_;
+ }
+ private:
+ size_t sum_;
+ };
+
+ //#################################################
+ inline size_t calc_sum_of_string_lengths(const string_container_t& string_cont)
+ {
+ return std::for_each(
+ string_cont.begin(), string_cont.end(), sum_of_string_lengths());
+ }
+
+ //#################################################
+ void read_environment(/*out*/ string_container_t* environment)
+ {
+ // GetEnvironmentStrings returns a sorted list, Windows
+ // sorts environment variables upper case
+ LPTSTR env = reinterpret_cast<LPTSTR>(GetEnvironmentStrings());
+ LPTSTR p = env;
+
+ while (size_t l = _tcslen(p))
+ {
+ environment->push_back(reinterpret_cast<const sal_Unicode*>(p));
+ p += l + 1;
+ }
+ FreeEnvironmentStrings(env);
+ }
+
+ //#################################################
+ /* the environment list must be sorted, new values
+ should either replace existing ones or should be
+ added to the list, environment variables will
+ be handled case-insensitive */
+ bool create_merged_environment(
+ rtl_uString* env_vars[],
+ sal_uInt32 env_vars_count,
+ /*in|out*/ string_container_t* merged_env)
+ {
+ OSL_ASSERT(env_vars && env_vars_count > 0 && merged_env);
+
+ read_environment(merged_env);
+
+ for (sal_uInt32 i = 0; i < env_vars_count; i++)
+ {
+ rtl::OUString env_var = rtl::OUString(env_vars[i]);
+
+ if (env_var.getLength() == 0)
+ return false;
+
+ iterator_pair_t iter_pair = std::equal_range(
+ merged_env->begin(),
+ merged_env->end(),
+ env_var,
+ less_environment_variable());
+
+ if (env_var.indexOf(NAME_VALUE_SEPARATOR) == -1)
+ {
+ merged_env->erase(iter_pair.first, iter_pair.second);
+ }
+ else
+ {
+ if (iter_pair.first != iter_pair.second) // found
+ *iter_pair.first = env_var;
+ else // not found
+ merged_env->insert(iter_pair.first, env_var);
+ }
+ }
+ return true;
+ }
+
+ //#################################################
+ /* Create a merged environment */
+ bool setup_process_environment(
+ rtl_uString* environment_vars[],
+ sal_uInt32 n_environment_vars,
+ /*in|out*/ environment_container_t& environment)
+ {
+ string_container_t merged_env;
+ if (!create_merged_environment(environment_vars, n_environment_vars, &merged_env))
+ return false;
+
+ // allocate enough space for the '\0'-separated environment strings and
+ // a final '\0'
+ environment.resize(calc_sum_of_string_lengths(merged_env) + 1);
+
+ string_container_const_iterator_t iter = merged_env.begin();
+ string_container_const_iterator_t iter_end = merged_env.end();
+
+ sal_uInt32 pos = 0;
+ for (/**/; iter != iter_end; ++iter)
+ {
+ rtl::OUString envv = *iter;
+
+ OSL_ASSERT(envv.getLength());
+
+ sal_uInt32 n = envv.getLength() + 1; // copy the final '\0', too
+ rtl_copyMemory(
+ reinterpret_cast<void*>(&environment[pos]),
+ reinterpret_cast<const void*>(envv.getStr()),
+ n * sizeof(sal_Unicode));
+ pos += n;
+ }
+ environment[pos] = 0; // append a final '\0'
+
+ return true;
+ }
+
+ //##########################################################
+ /* In contrast to the Win32 API function CreatePipe with
+ this function the caller is able to determine separately
+ which handle of the pipe is inheritable. */
+ bool create_pipe(
+ PHANDLE p_read_pipe,
+ bool b_read_pipe_inheritable,
+ PHANDLE p_write_pipe,
+ bool b_write_pipe_inheritable,
+ LPVOID p_security_descriptor = NULL,
+ DWORD pipe_size = 0)
+ {
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = p_security_descriptor;
+ sa.bInheritHandle = b_read_pipe_inheritable || b_write_pipe_inheritable;
+
+ BOOL bRet = FALSE;
+ HANDLE hTemp = NULL;
+
+ if (!b_read_pipe_inheritable && b_write_pipe_inheritable)
+ {
+ bRet = CreatePipe(&hTemp, p_write_pipe, &sa, pipe_size);
+
+ if (bRet && !DuplicateHandle(GetCurrentProcess(), hTemp,
+ GetCurrentProcess(), p_read_pipe, 0, FALSE,
+ DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
+ {
+ CloseHandle(hTemp);
+ CloseHandle(*p_read_pipe);
+ return false;
+ }
+ }
+ else if (b_read_pipe_inheritable && !b_write_pipe_inheritable)
+ {
+ bRet = CreatePipe(p_read_pipe, &hTemp, &sa, pipe_size);
+
+ if (bRet && !DuplicateHandle(GetCurrentProcess(), hTemp,
+ GetCurrentProcess(), p_write_pipe, 0, FALSE,
+ DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
+ {
+ CloseHandle(hTemp);
+ CloseHandle(*p_write_pipe);
+ return false;
+ }
+ }
+ else
+ {
+ bRet = CreatePipe(p_read_pipe, p_write_pipe, &sa, pipe_size);
+ }
+ return bRet;
+ }
+
+ //#########################################################
+ // Add a quote sign to the start and the end of a string
+ // if not already present
+ rtl::OUString quote_string(const rtl::OUString& string)
+ {
+ rtl::OUStringBuffer quoted;
+ if (string.indexOf(QUOTE) != 0)
+ quoted.append(QUOTE);
+
+ quoted.append(string);
+
+ if (string.lastIndexOf(QUOTE) != (string.getLength() - 1))
+ quoted.append(QUOTE);
+
+ return quoted.makeStringAndClear();
+ }
+
+ //##########################################################
+ // Returns the system path of the executable which can either
+ // be provided via the strImageName parameter or as first
+ // element of the strArguments list.
+ // The returned path will be quoted if it contains spaces.
+ rtl::OUString get_executable_path(
+ rtl_uString* image_name,
+ rtl_uString* cmdline_args[],
+ sal_uInt32 n_cmdline_args,
+ bool search_path)
+ {
+ rtl::OUString exe_name;
+
+ if (image_name)
+ exe_name = image_name;
+ else if (n_cmdline_args)
+ exe_name = rtl::OUString(cmdline_args[0]);
+
+ rtl::OUString exe_url = exe_name;
+ if (search_path)
+ osl_searchFileURL(exe_name.pData, NULL, &exe_url.pData);
+
+ rtl::OUString exe_path;
+ if (osl_File_E_None != osl::FileBase::getSystemPathFromFileURL(exe_url, exe_path))
+ return rtl::OUString();
+
+ if (exe_path.indexOf(' ') != -1)
+ exe_path = quote_string(exe_path);
+
+ return exe_path;
+ }
+
+ //##########################################################
+ rtl::OUString get_file_extension(const rtl::OUString& file_name)
+ {
+ sal_Int32 index = file_name.lastIndexOf('.');
+ if ((index != -1) && ((index + 1) < file_name.getLength()))
+ return file_name.copy(index + 1);
+
+ return rtl::OUString();
+ }
+
+ //##########################################################
+ bool is_batch_file(const rtl::OUString& file_name)
+ {
+ rtl::OUString ext = get_file_extension(file_name);
+ return (ext.equalsIgnoreAsciiCaseAscii("bat") ||
+ ext.equalsIgnoreAsciiCaseAscii("cmd") ||
+ ext.equalsIgnoreAsciiCaseAscii("btm"));
+ }
+
+ //##########################################################
+ rtl::OUString get_batch_processor()
+ {
+ rtl::OUString comspec;
+ osl_getEnvironment(ENV_COMSPEC.pData, &comspec.pData);
+
+ OSL_ASSERT(comspec.getLength());
+
+ /* check if comspec path contains blanks and quote it if any */
+ if (comspec.indexOf(' ') != -1)
+ comspec = quote_string(comspec);
+
+ return comspec;
+ }
+
+} // namespace private
+
+
+//#################################################
+oslProcessError SAL_CALL osl_executeProcess(
+ rtl_uString *strImageName,
+ rtl_uString *strArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *strDirectory,
+ rtl_uString *strEnvironmentVars[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess
+)
+{
+ return osl_executeProcess_WithRedirectedIO(
+ strImageName,
+ strArguments,
+ nArguments,
+ Options,
+ Security,
+ strDirectory,
+ strEnvironmentVars,
+ nEnvironmentVars,
+ pProcess,
+ NULL, NULL, NULL );
+}
+
+//#################################################
+oslProcessError SAL_CALL osl_executeProcess_WithRedirectedIO(
+ rtl_uString *ustrImageName,
+ rtl_uString *ustrArguments[],
+ sal_uInt32 nArguments,
+ oslProcessOption Options,
+ oslSecurity Security,
+ rtl_uString *ustrDirectory,
+ rtl_uString *ustrEnvironmentVars[],
+ sal_uInt32 nEnvironmentVars,
+ oslProcess *pProcess,
+ oslFileHandle *pProcessInputWrite,
+ oslFileHandle *pProcessOutputRead,
+ oslFileHandle *pProcessErrorRead)
+{
+ rtl::OUString exe_path = get_executable_path(
+ ustrImageName, ustrArguments, nArguments, (Options & osl_Process_SEARCHPATH));
+
+ if (0 == exe_path.getLength())
+ return osl_Process_E_NotFound;
+
+ if (pProcess == NULL)
+ return osl_Process_E_InvalidError;
+
+ DWORD flags = NORMAL_PRIORITY_CLASS;
+ rtl::OUStringBuffer command_line;
+
+ if (is_batch_file(exe_path))
+ {
+ rtl::OUString batch_processor = get_batch_processor();
+
+ if (batch_processor.getLength())
+ {
+ /* cmd.exe does not work without a console window */
+ if (!(Options & osl_Process_WAIT) || (Options & osl_Process_DETACHED))
+ flags |= CREATE_NEW_CONSOLE;
+
+ command_line.append(batch_processor);
+ command_line.appendAscii(" /c ");
+ }
+ else
+ // should we return here in case of error?
+ return osl_Process_E_Unknown;
+ }
+
+ command_line.append(exe_path);
+
+ /* Add remaining arguments to command line. If ustrImageName is NULL
+ the first parameter is the name of the executable so we have to
+ start at 1 instead of 0 */
+ for (sal_uInt32 n = (NULL != ustrImageName) ? 0 : 1; n < nArguments; n++)
+ {
+ command_line.appendAscii(SPACE);
+
+ /* Quote arguments containing blanks */
+ if (rtl::OUString(ustrArguments[n]).indexOf(' ') != -1)
+ command_line.append(quote_string(ustrArguments[n]));
+ else
+ command_line.append(ustrArguments[n]);
+ }
+
+ environment_container_t environment;
+ LPVOID p_environment = NULL;
+
+ if (nEnvironmentVars && ustrEnvironmentVars)
+ {
+ if (!setup_process_environment(
+ ustrEnvironmentVars, nEnvironmentVars, environment))
+ return osl_Process_E_InvalidError;
+
+ flags |= CREATE_UNICODE_ENVIRONMENT;
+ p_environment = &environment[0];
+ }
+
+ rtl::OUString cwd;
+ if (ustrDirectory && ustrDirectory->length && (osl_File_E_None != osl::FileBase::getSystemPathFromFileURL(ustrDirectory, cwd)))
+ return osl_Process_E_InvalidError;
+
+ LPCWSTR p_cwd = (cwd.getLength()) ? reinterpret_cast<LPCWSTR>(cwd.getStr()) : NULL;
+
+ if ((Options & osl_Process_DETACHED) && !(flags & CREATE_NEW_CONSOLE))
+ flags |= DETACHED_PROCESS;
+
+ STARTUPINFO startup_info;
+ memset(&startup_info, 0, sizeof(STARTUPINFO));
+
+ startup_info.cb = sizeof(STARTUPINFO);
+ startup_info.dwFlags = STARTF_USESHOWWINDOW;
+ startup_info.lpDesktop = L"";
+
+ /* Create pipes for redirected IO */
+ HANDLE hInputRead = NULL;
+ HANDLE hInputWrite = NULL;
+ if (pProcessInputWrite && create_pipe(&hInputRead, true, &hInputWrite, false))
+ startup_info.hStdInput = hInputRead;
+
+ HANDLE hOutputRead = NULL;
+ HANDLE hOutputWrite = NULL;
+ if (pProcessOutputRead && create_pipe(&hOutputRead, false, &hOutputWrite, true))
+ startup_info.hStdOutput = hOutputWrite;
+
+ HANDLE hErrorRead = NULL;
+ HANDLE hErrorWrite = NULL;
+ if (pProcessErrorRead && create_pipe(&hErrorRead, false, &hErrorWrite, true))
+ startup_info.hStdError = hErrorWrite;
+
+ bool b_inherit_handles = false;
+ if (pProcessInputWrite || pProcessOutputRead || pProcessErrorRead)
+ {
+ startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ b_inherit_handles = true;
+ }
+
+ switch(Options & (osl_Process_NORMAL | osl_Process_HIDDEN | osl_Process_MINIMIZED | osl_Process_MAXIMIZED | osl_Process_FULLSCREEN))
+ {
+ case osl_Process_HIDDEN:
+ startup_info.wShowWindow = SW_HIDE;
+ flags |= CREATE_NO_WINDOW; // ignored for non-console
+ // applications; ignored on
+ // Win9x
+ break;
+
+ case osl_Process_MINIMIZED:
+ startup_info.wShowWindow = SW_MINIMIZE;
+ break;
+
+ case osl_Process_MAXIMIZED:
+ case osl_Process_FULLSCREEN:
+ startup_info.wShowWindow = SW_MAXIMIZE;
+ break;
+
+ default:
+ startup_info.wShowWindow = SW_NORMAL;
+ }
+
+ rtl::OUString cmdline = command_line.makeStringAndClear();
+ PROCESS_INFORMATION process_info;
+ BOOL bRet = FALSE;
+
+ if ((Security != NULL) && (((oslSecurityImpl*)Security)->m_hToken != NULL))
+ {
+ bRet = CreateProcessAsUser(
+ ((oslSecurityImpl*)Security)->m_hToken,
+ NULL, const_cast<LPTSTR>(reinterpret_cast<LPCTSTR>(cmdline.getStr())), NULL, NULL,
+ b_inherit_handles, flags, p_environment, p_cwd,
+ &startup_info, &process_info);
+ }
+ else
+ {
+ bRet = CreateProcess(
+ NULL, const_cast<LPTSTR>(reinterpret_cast<LPCTSTR>(cmdline.getStr())), NULL, NULL,
+ b_inherit_handles, flags, p_environment, p_cwd,
+ &startup_info, &process_info);
+ }
+
+ /* Now we can close the pipe ends that are used by the child process */
+
+ if (hInputRead)
+ CloseHandle(hInputRead);
+
+ if (hOutputWrite)
+ CloseHandle(hOutputWrite);
+
+ if (hErrorWrite)
+ CloseHandle(hErrorWrite);
+
+ if (bRet)
+ {
+ CloseHandle(process_info.hThread);
+
+ oslProcessImpl* pProcImpl = reinterpret_cast<oslProcessImpl*>(
+ rtl_allocateMemory(sizeof(oslProcessImpl)));
+
+ if (pProcImpl != NULL)
+ {
+ pProcImpl->m_hProcess = process_info.hProcess;
+ pProcImpl->m_IdProcess = process_info.dwProcessId;
+
+ *pProcess = (oslProcess)pProcImpl;
+
+ if (Options & osl_Process_WAIT)
+ WaitForSingleObject(pProcImpl->m_hProcess, INFINITE);
+
+ if (pProcessInputWrite)
+ *pProcessInputWrite = osl_createFileHandleFromOSHandle(hInputWrite, osl_File_OpenFlag_Write);
+
+ if (pProcessOutputRead)
+ *pProcessOutputRead = osl_createFileHandleFromOSHandle(hOutputRead, osl_File_OpenFlag_Read);
+
+ if (pProcessErrorRead)
+ *pProcessErrorRead = osl_createFileHandleFromOSHandle(hErrorRead, osl_File_OpenFlag_Read);
+
+ return osl_Process_E_None;
+ }
+ }
+
+ /* if an error occured we have to close the server side pipe ends too */
+
+ if (hInputWrite)
+ CloseHandle(hInputWrite);
+
+ if (hOutputRead)
+ CloseHandle(hOutputRead);
+
+ if (hErrorRead)
+ CloseHandle(hErrorRead);
+
+ return osl_Process_E_Unknown;
+}
diff --git a/sal/osl/w32/procimpl.h b/sal/osl/w32/procimpl.h
new file mode 100644
index 000000000000..b783f9b52ae2
--- /dev/null
+++ b/sal/osl/w32/procimpl.h
@@ -0,0 +1,47 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_PROCIMPL_H_
+#define _OSL_PROCIMPL_H_
+
+#include <osl/process.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _oslProcessImpl {
+ HANDLE m_hProcess;
+ DWORD m_IdProcess;
+} oslProcessImpl;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sal/osl/w32/profile.cxx b/sal/osl/w32/profile.cxx
new file mode 100644
index 000000000000..9f4ea5630e1f
--- /dev/null
+++ b/sal/osl/w32/profile.cxx
@@ -0,0 +1,2707 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+#include "system.h"
+
+#include "file_url.h"
+#include "path_helper.hxx"
+
+#include <osl/diagnose.h>
+#include <osl/profile.h>
+#include <osl/process.h>
+#include <osl/file.h>
+#include <osl/util.h>
+#include <rtl/alloc.h>
+#include <algorithm>
+using std::min;
+static inline void copy_ustr_n( void *dest, const void *source, size_t length ) { rtl_copyMemory(dest, source, length*sizeof(sal_Unicode)); }
+
+#define LINES_INI 32
+#define LINES_ADD 10
+#define SECTIONS_INI 5
+#define SECTIONS_ADD 3
+#define ENTRIES_INI 5
+#define ENTRIES_ADD 3
+
+
+#define STR_INI_EXTENSION L".ini"
+#define STR_INI_METAHOME "?~"
+#define STR_INI_METASYS "?$"
+#define STR_INI_METACFG "?^"
+#define STR_INI_METAINS "?#"
+
+#define STR_INI_BOOLYES "yes"
+#define STR_INI_BOOLON "on"
+#define STR_INI_BOOLONE "1"
+#define STR_INI_BOOLNO "no"
+#define STR_INI_BOOLOFF "off"
+#define STR_INI_BOOLZERO "0"
+
+#define FLG_USER 0x00FF
+#define FLG_AUTOOPEN 0x0100
+#define FLG_MODIFIED 0x0200
+
+#define SVERSION_LOCATION STR_INI_METACFG
+#define SVERSION_FALLBACK STR_INI_METASYS
+#define SVERSION_NAME "sversion"
+#define SVERSION_SECTION "Versions"
+#define SVERSION_SOFFICE "StarOffice"
+#define SVERSION_PROFILE "soffice.ini"
+#define SVERSION_OPTION "userid:"
+#define SVERSION_DIRS { "bin", "program" }
+#define SVERSION_USER "user"
+
+#define DEFAULT_PMODE (_S_IREAD | _S_IWRITE)
+
+#define _BUILD_STR_(n) # n
+#define BUILD_STR(n) _BUILD_STR_(n)
+
+
+/*#define DEBUG_OSL_PROFILE 1*/
+/*#define TRACE_OSL_PROFILE 1*/
+
+
+/*****************************************************************************/
+/* Data Type Definition */
+/*****************************************************************************/
+
+typedef FILETIME osl_TStamp;
+
+typedef enum _osl_TLockMode
+{
+ un_lock, read_lock, write_lock
+} osl_TLockMode;
+
+typedef struct _osl_TFile
+{
+ HANDLE m_Handle;
+ sal_Char* m_pReadPtr;
+ sal_Char m_ReadBuf[512];
+/* sal_Char* m_pWritePtr; */
+/* sal_Char m_WriteBuf[512]; */
+ sal_Char* m_pWriteBuf;
+ sal_uInt32 m_nWriteBufLen;
+ sal_uInt32 m_nWriteBufFree;
+} osl_TFile;
+
+typedef struct _osl_TProfileEntry
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+} osl_TProfileEntry;
+
+typedef struct _osl_TProfileSection
+{
+ sal_uInt32 m_Line;
+ sal_uInt32 m_Offset;
+ sal_uInt32 m_Len;
+ sal_uInt32 m_NoEntries;
+ sal_uInt32 m_MaxEntries;
+ osl_TProfileEntry* m_Entries;
+} osl_TProfileSection;
+
+
+/*
+ Profile-data structure hidden behind oslProfile:
+*/
+typedef struct _osl_TProfileImpl
+{
+ sal_uInt32 m_Flags;
+ osl_TFile* m_pFile;
+ osl_TStamp m_Stamp;
+ sal_uInt32 m_NoLines;
+ sal_uInt32 m_MaxLines;
+ sal_uInt32 m_NoSections;
+ sal_uInt32 m_MaxSections;
+ sal_Char** m_Lines;
+ rtl_uString *m_strFileName;
+ osl_TProfileSection* m_Sections;
+} osl_TProfileImpl;
+
+
+/*****************************************************************************/
+/* Static Module Function Declarations */
+/*****************************************************************************/
+
+static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags );
+static osl_TStamp closeFileImpl(osl_TFile* pFile);
+static sal_Bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode);
+static sal_Bool rewindFile(osl_TFile* pFile, sal_Bool bTruncate);
+static osl_TStamp getFileStamp(osl_TFile* pFile);
+
+static sal_Bool getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen);
+static sal_Bool putLine(osl_TFile* pFile, const sal_Char *pszLine);
+static const sal_Char* stripBlanks(const sal_Char* String, sal_uInt32* pLen);
+static const sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line);
+static const sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo);
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo);
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ const sal_Char* Entry, sal_uInt32 Len);
+static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, const sal_Char* Entry, sal_uInt32 Len);
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry);
+static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len);
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection);
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
+ const sal_Char* Entry, sal_uInt32 *pNoEntry);
+static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile);
+static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup);
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable);
+static sal_Bool releaseProfile(osl_TProfileImpl* pProfile);
+static sal_Bool lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile);
+
+static sal_Bool writeProfileImpl (osl_TFile* pFile);
+static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl*);
+static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl*);
+static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension);
+
+static sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName);
+
+/*****************************************************************************/
+/* Exported Module Functions */
+/*****************************************************************************/
+
+oslProfile SAL_CALL osl_openProfile(rtl_uString *strProfileName, sal_uInt32 Flags)
+{
+ osl_TFile* pFile = NULL;
+ osl_TProfileImpl* pProfile;
+ rtl_uString *FileName=NULL;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_openProfile\n");
+#endif
+ OSL_VERIFY(strProfileName);
+
+ if (rtl_uString_getLength(strProfileName) == 0 )
+ {
+ OSL_VERIFY(osl_getProfileName(NULL, NULL, &FileName));
+ }
+ else
+ {
+ rtl_uString_assign(&FileName, strProfileName);
+ }
+
+
+ osl_getSystemPathFromFileURL(FileName, &FileName);
+
+
+#ifdef DEBUG_OSL_PROFILE
+ Flags=osl_Profile_FLUSHWRITE;
+
+ // OSL_TRACE("opening '%s'\n",FileName);
+ if ( Flags == osl_Profile_DEFAULT )
+ {
+ OSL_TRACE("with osl_Profile_DEFAULT \n");
+ }
+ if ( Flags & osl_Profile_SYSTEM )
+ {
+ OSL_TRACE("with osl_Profile_SYSTEM \n");
+ }
+ if ( Flags & osl_Profile_READLOCK )
+ {
+ OSL_TRACE("with osl_Profile_READLOCK \n");
+ }
+ if ( Flags & osl_Profile_WRITELOCK )
+ {
+ OSL_TRACE("with osl_Profile_WRITELOCK \n");
+ }
+/* if ( Flags & osl_Profile_READWRITE ) */
+/* { */
+/* OSL_TRACE("with osl_Profile_READWRITE \n"); */
+/* } */
+ if ( Flags & osl_Profile_FLUSHWRITE )
+ {
+ OSL_TRACE("with osl_Profile_FLUSHWRITE \n");
+ }
+#endif
+
+ if ( (! (Flags & osl_Profile_SYSTEM)) && ( (pFile = openFileImpl(FileName, Flags) ) == NULL ) )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_openProfile [not opened]\n");
+#endif
+ if( FileName)
+ rtl_uString_release( FileName);
+
+ return (NULL);
+ }
+
+
+ pProfile = (osl_TProfileImpl*)calloc(1, sizeof(osl_TProfileImpl));
+
+
+ pProfile->m_Flags = Flags & FLG_USER;
+ osl_getSystemPathFromFileURL(strProfileName, &pProfile->m_strFileName);
+// rtl_uString_assign(&pProfile->m_strFileName, strProfileName);
+
+ if (Flags & (osl_Profile_READLOCK | osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ))
+ pProfile->m_pFile = pFile;
+
+ pProfile->m_Stamp = getFileStamp(pFile);
+
+ loadProfile(pFile, pProfile);
+
+ if (pProfile->m_pFile == NULL)
+ closeFileImpl(pFile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_openProfile [ok]\n");
+#endif
+ if( FileName)
+ rtl_uString_release( FileName);
+
+ return (pProfile);
+}
+
+sal_Bool SAL_CALL osl_closeProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_closeProfile\n");
+#endif
+
+ if ( Profile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [profile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ pProfile = acquireProfile(Profile,sal_True);
+
+ if ( pProfile != 0 )
+ {
+ if ( !( pProfile->m_Flags & osl_Profile_READLOCK ) && ( pProfile->m_Flags & FLG_MODIFIED ) )
+ {
+/* if (pProfile->m_pFile == NULL) */
+/* pProfile->m_pFile = openFileImpl(pProfile->m_Filename, sal_True); */
+
+ storeProfile(pProfile, sal_False);
+ }
+ }
+ else
+ {
+ pProfile = acquireProfile(Profile,sal_False);
+ }
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [pProfile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (pProfile->m_pFile != NULL)
+ closeFileImpl(pProfile->m_pFile);
+ }
+
+ pProfile->m_pFile = NULL;
+ rtl_uString_release(pProfile->m_strFileName);
+ pProfile->m_strFileName = NULL;
+
+ /* release whole profile data types memory */
+ if ( pProfile->m_NoLines > 0)
+ {
+ unsigned int index=0;
+ if ( pProfile->m_Lines != 0 )
+ {
+ for ( index = 0 ; index < pProfile->m_NoLines ; ++index)
+ {
+ if ( pProfile->m_Lines[index] != 0 )
+ {
+ free(pProfile->m_Lines[index]);
+ }
+ }
+ free(pProfile->m_Lines);
+ }
+ if ( pProfile->m_Sections != 0 )
+ {
+ /*osl_TProfileSection* pSections=pProfile->m_Sections;*/
+ for ( index = 0 ; index < pProfile->m_NoSections ; ++index )
+ {
+ if ( pProfile->m_Sections[index].m_Entries != 0 )
+ {
+ free(pProfile->m_Sections[index].m_Entries);
+ }
+ }
+ free(pProfile->m_Sections);
+ }
+
+ }
+ free(pProfile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_closeProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+
+sal_Bool SAL_CALL osl_flushProfile(oslProfile Profile)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*) Profile;
+ osl_TFile* pFile;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_flushProfile()\n");
+#endif
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [pProfile == 0]\n");
+#endif
+ return sal_False;
+ }
+
+ pFile = pProfile->m_pFile;
+ if ( !( pFile != 0 && pFile->m_Handle >= 0 ) )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [invalid file]\n");
+#endif
+ return sal_False;
+ }
+
+ if ( pProfile->m_Flags & FLG_MODIFIED )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("swapping to storeprofile\n");
+#endif
+ bRet = storeProfile(pProfile,sal_False);
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_flushProfile() [ok]\n");
+#endif
+ return bRet;
+}
+
+static sal_Bool writeProfileImpl(osl_TFile* pFile)
+{
+ DWORD BytesWritten=0;
+ BOOL bRet;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileImpl()\n");
+#endif
+
+ if ( !( pFile != 0 && pFile->m_Handle != INVALID_HANDLE_VALUE ) || ( pFile->m_pWriteBuf == 0 ) )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileImpl() [invalid args]\n");
+#endif
+ return sal_False;
+ }
+
+#ifdef DEBUG_OSL_PROFILE
+/* OSL_TRACE("File Buffer in writeProfileImpl '%s' size == '%i' '%i'(%i)\n",
+ pFile->m_pWriteBuf,pFile->m_nWriteBufLen,strlen(pFile->m_pWriteBuf),pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);*/
+#endif
+
+ bRet=WriteFile(pFile->m_Handle, pFile->m_pWriteBuf, pFile->m_nWriteBufLen - pFile->m_nWriteBufFree,&BytesWritten,NULL);
+
+ if ( bRet == 0 || BytesWritten <= 0 )
+ {
+ OSL_ENSURE(bRet,"WriteFile failed!!!");
+
+ OSL_TRACE("write failed '%s'\n",strerror(errno));
+
+/* OSL_TRACE("Out osl_writeProfileImpl() [write '%s']\n",strerror(errno));*/
+ return (sal_False);
+ }
+
+ free(pFile->m_pWriteBuf);
+ pFile->m_pWriteBuf=0;
+ pFile->m_nWriteBufLen=0;
+ pFile->m_nWriteBufFree=0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileImpl() [ok]\n");
+#endif
+ return sal_True;
+}
+
+
+sal_Bool SAL_CALL osl_readProfileString(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Char* pszString, sal_uInt32 MaxLen,
+ const sal_Char* pszDefault)
+{
+ sal_uInt32 NoEntry;
+ const sal_Char* pStr = 0;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileString\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [pProfile==0]\n");
+#endif
+
+
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
+ (NoEntry < pSec->m_NoEntries) &&
+ ((pStr = strchr(pProfile->m_Lines[pSec->m_Entries[NoEntry].m_Line],
+ '=')) != NULL))
+ pStr++;
+ else
+ pStr = pszDefault;
+
+ if ( pStr != 0 )
+ {
+ pStr = stripBlanks(pStr, NULL);
+ MaxLen = (MaxLen - 1 < strlen(pStr)) ? (MaxLen - 1) : strlen(pStr);
+ pStr = stripBlanks(pStr, &MaxLen);
+ strncpy(pszString, pStr, MaxLen);
+ pszString[MaxLen] = '\0';
+ }
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ GetPrivateProfileString(pszSection, pszEntry, pszDefault, pszString, MaxLen, aFileName);
+ }
+
+ releaseProfile(pProfile);
+
+ if ( pStr == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [pStr==0]\n");
+#endif
+
+
+ return (sal_False);
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileString [ok]\n");
+#endif
+
+
+
+
+ return (sal_True);
+}
+
+
+sal_Bool SAL_CALL osl_readProfileBool(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Bool Default)
+{
+ sal_Char Line[32];
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileBool\n");
+#endif
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ if ((stricmp(Line, STR_INI_BOOLYES) == 0) ||
+ (stricmp(Line, STR_INI_BOOLON) == 0) ||
+ (stricmp(Line, STR_INI_BOOLONE) == 0))
+ Default = sal_True;
+ else
+ if ((stricmp(Line, STR_INI_BOOLNO) == 0) ||
+ (stricmp(Line, STR_INI_BOOLOFF) == 0) ||
+ (stricmp(Line, STR_INI_BOOLZERO) == 0))
+ Default = sal_False;
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileBool [ok]\n");
+#endif
+
+ return (Default);
+}
+
+
+sal_uInt32 SAL_CALL osl_readProfileIdent(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_uInt32 FirstId, const sal_Char* Strings[],
+ sal_uInt32 Default)
+{
+ sal_uInt32 i;
+ sal_Char Line[256];
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_readProfileIdent\n");
+#endif
+
+ if (osl_readProfileString(Profile, pszSection, pszEntry, Line, sizeof(Line), ""))
+ {
+ i = 0;
+ while (Strings[i] != NULL)
+ {
+ if (stricmp(Line, Strings[i]) == 0)
+ {
+ Default = i + FirstId;
+ break;
+ }
+ i++;
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_readProfileIdent [ok]\n");
+#endif
+ return (Default);
+}
+
+sal_Bool SAL_CALL osl_writeProfileString(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ const sal_Char* pszString)
+{
+ sal_uInt32 i;
+ sal_Bool bRet = sal_False;
+ sal_uInt32 NoEntry;
+ const sal_Char* pStr;
+ sal_Char Line[4096];
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileString\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_True);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [pProfile==0]\n");
+#endif
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if ((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) == NULL)
+ {
+ Line[0] = '\0';
+ addLine(pProfile, Line);
+
+ Line[0] = '[';
+ strcpy(&Line[1], pszSection);
+ Line[1 + strlen(pszSection)] = ']';
+ Line[2 + strlen(pszSection)] = '\0';
+
+ if (((pStr = addLine(pProfile, Line)) == NULL) ||
+ (! addSection(pProfile, pProfile->m_NoLines - 1, &pStr[1], strlen(pszSection))))
+ {
+ releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [not added]\n");
+#endif
+ return (sal_False);
+ }
+
+ pSec = &pProfile->m_Sections[pProfile->m_NoSections - 1];
+ NoEntry = pSec->m_NoEntries;
+ }
+
+ Line[0] = '\0';
+ strcpy(&Line[0], pszEntry);
+ Line[0 + strlen(pszEntry)] = '=';
+ strcpy(&Line[1 + strlen(pszEntry)], pszString);
+
+ if (NoEntry >= pSec->m_NoEntries)
+ {
+ if (pSec->m_NoEntries > 0)
+ i = pSec->m_Entries[pSec->m_NoEntries - 1].m_Line + 1;
+ else
+ i = pSec->m_Line + 1;
+
+ if (((pStr = insertLine(pProfile, Line, i)) == NULL) ||
+ (! addEntry(pProfile, pSec, i, pStr, strlen(pszEntry))))
+ {
+ releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [not inserted]\n");
+#endif
+ return (sal_False);
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ else
+ {
+ i = pSec->m_Entries[NoEntry].m_Line;
+ free(pProfile->m_Lines[i]);
+ pProfile->m_Lines[i] = strdup(Line);
+ setEntry(pProfile, pSec, NoEntry, i, pProfile->m_Lines[i], strlen(pszEntry));
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ WritePrivateProfileString(pszSection, pszEntry, pszString, aFileName);
+ }
+
+ bRet = releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileString [ok]\n");
+#endif
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_writeProfileBool(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_Bool Value)
+{
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileBool\n");
+#endif
+
+ if (Value)
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLONE);
+ else
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, STR_INI_BOOLZERO);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileBool [ok]\n");
+#endif
+
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_writeProfileIdent(oslProfile Profile,
+ const sal_Char* pszSection, const sal_Char* pszEntry,
+ sal_uInt32 FirstId, const sal_Char* Strings[],
+ sal_uInt32 Value)
+{
+ int i, n;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_writeProfileIdent\n");
+#endif
+
+ for (n = 0; Strings[n] != NULL; n++);
+
+ if ((i = Value - FirstId) >= n)
+ bRet=sal_False;
+ else
+ bRet=osl_writeProfileString(Profile, pszSection, pszEntry, Strings[i]);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_writeProfileIdent\n");
+#endif
+ return bRet;
+}
+
+
+sal_Bool SAL_CALL osl_removeProfileEntry(oslProfile Profile,
+ const sal_Char *pszSection, const sal_Char *pszEntry)
+{
+ sal_uInt32 NoEntry;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+ sal_Bool bRet = sal_False;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_removeProfileEntry\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_True);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [pProfile==0]\n");
+#endif
+
+
+ return (sal_False);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (((pSec = findEntry(pProfile, pszSection, pszEntry, &NoEntry)) != NULL) &&
+ (NoEntry < pSec->m_NoEntries))
+ {
+ removeLine(pProfile, pSec->m_Entries[NoEntry].m_Line);
+ removeEntry(pSec, NoEntry);
+ if (pSec->m_NoEntries == 0)
+ {
+ removeLine(pProfile, pSec->m_Line);
+
+ /* remove any empty separation line */
+ if ((pSec->m_Line > 0) && (pProfile->m_Lines[pSec->m_Line - 1][0] == '\0'))
+ removeLine(pProfile, pSec->m_Line - 1);
+
+ removeSection(pProfile, pSec);
+ }
+
+ pProfile->m_Flags |= FLG_MODIFIED;
+ }
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ WritePrivateProfileString(pszSection, pszEntry, NULL, aFileName);
+ }
+
+ bRet = releaseProfile(pProfile);
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_removeProfileEntry [ok]\n");
+#endif
+ return bRet;
+}
+
+
+sal_uInt32 SAL_CALL osl_getProfileSectionEntries(oslProfile Profile, const sal_Char *pszSection,
+ sal_Char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ sal_uInt32 NoEntry;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = 0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In osl_getProfileSectionEntries\n");
+#endif
+
+ pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [pProfile=0]\n");
+#endif
+
+
+ return (0);
+ }
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if ((pSec = findEntry(pProfile, pszSection, "", &NoEntry)) != NULL)
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ if ((n + pSec->m_Entries[i].m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset], pSec->m_Entries[i].m_Len);
+ n += pSec->m_Entries[i].m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ break;
+
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ n += pSec->m_Entries[i].m_Len + 1;
+
+ n += 1;
+ }
+ }
+ else
+ n = 0;
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ n = GetPrivateProfileString(pszSection, NULL, NULL, pszBuffer, MaxLen, aFileName);
+ }
+
+ releaseProfile(pProfile);
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out osl_getProfileSectionEntries [ok]\n");
+#endif
+
+ return (n);
+}
+
+
+sal_Bool SAL_CALL osl_getProfileName(rtl_uString* strPath, rtl_uString* strName, rtl_uString** strProfileName)
+{
+ sal_Bool bFailed;
+ ::osl::LongPathBuffer< sal_Unicode > aFile( MAX_LONG_PATH );
+ ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
+ sal_uInt32 nFileLen = 0;
+ sal_uInt32 nPathLen = 0;
+
+ rtl_uString * strTmp = NULL;
+ oslFileError nError;
+
+ /* build file name */
+ if (strName && strName->length)
+ {
+ if( ::sal::static_int_cast< sal_uInt32 >( strName->length ) >= aFile.getBufSizeInSymbols() )
+ return sal_False;
+
+ copy_ustr_n( aFile, strName->buffer, strName->length+1);
+ nFileLen = strName->length;
+
+ if (rtl_ustr_indexOfChar( aFile, L'.' ) == -1)
+ {
+ if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
+ return sal_False;
+
+ /* add default extension */
+ copy_ustr_n( aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1 );
+ nFileLen += wcslen(STR_INI_EXTENSION);
+ }
+ }
+ else
+ {
+ rtl_uString *strProgName = NULL;
+ sal_Unicode *pProgName;
+ sal_Int32 nOffset = 0;
+ sal_Int32 nLen;
+ sal_Int32 nPos;
+
+ if (osl_getExecutableFile(&strProgName) != osl_Process_E_None)
+ return sal_False;
+
+ /* remove path and extension from filename */
+ pProgName = strProgName->buffer;
+ nLen = strProgName->length ;
+
+ if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'/' )) != -1)
+ nOffset = nPos + 1;
+ else if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L':' )) != -1)
+ nOffset = nPos + 1;
+
+ if ((nPos = rtl_ustr_lastIndexOfChar( pProgName, L'.' )) != -1 )
+ nLen -= 4;
+
+ if ((nFileLen = nLen - nOffset) >= aFile.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n(aFile, pProgName + nOffset, nFileLen);
+
+ if (nFileLen + wcslen(STR_INI_EXTENSION) >= aFile.getBufSizeInSymbols())
+ return sal_False;
+
+ /* add default extension */
+ copy_ustr_n(aFile + nFileLen, STR_INI_EXTENSION, wcslen(STR_INI_EXTENSION)+1);
+ nFileLen += wcslen(STR_INI_EXTENSION);
+
+ rtl_uString_release( strProgName );
+ }
+
+ if (aFile[0] == 0)
+ return sal_False;
+
+ /* build directory path */
+ if (strPath && strPath->length)
+ {
+ sal_Unicode *pPath = rtl_uString_getStr(strPath);
+ sal_Int32 nLen = rtl_uString_getLength(strPath);
+
+ if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAHOME) , STR_INI_METAHOME) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAHOME)] == '/')))
+ {
+ rtl_uString * strHome = NULL;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getHomeDir(security, &strHome);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return (sal_False);
+
+ if ( ::sal::static_int_cast< sal_uInt32 >( strHome->length ) >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n( aPath, strHome->buffer, strHome->length+1);
+ nPathLen = strHome->length;
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METAHOME))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METAHOME);
+
+ if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
+ nPathLen += nLen;
+ }
+
+ rtl_uString_release(strHome);
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METACFG), STR_INI_METACFG) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METACFG)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METACFG)] == '/')))
+ {
+ rtl_uString * strConfig = NULL;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getConfigDir(security, &strConfig);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return (sal_False);
+
+ if ( ::sal::static_int_cast< sal_uInt32 >( strConfig->length ) >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n( aPath, strConfig->buffer, strConfig->length+1 );
+ nPathLen = strConfig->length;
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METACFG))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METACFG);
+
+ if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
+ nPathLen += nLen;
+ }
+
+ rtl_uString_release(strConfig);
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METASYS), STR_INI_METASYS) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METASYS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METASYS)] == '/')))
+ {
+ if (((nPathLen = GetWindowsDirectoryW(::osl::mingw_reinterpret_cast<LPWSTR>(aPath), aPath.getBufSizeInSymbols())) == 0) || (nPathLen >= aPath.getBufSizeInSymbols()))
+ return (sal_False);
+
+ if (nLen > RTL_CONSTASCII_LENGTH(STR_INI_METASYS))
+ {
+ pPath += RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
+ nLen -= RTL_CONSTASCII_LENGTH(STR_INI_METASYS);
+
+ if (nLen + nPathLen >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ copy_ustr_n(aPath + nPathLen, pPath, nLen+1);
+ nPathLen += nLen;
+ }
+ }
+
+ else if ((rtl_ustr_ascii_compare_WithLength(pPath, RTL_CONSTASCII_LENGTH(STR_INI_METAINS), STR_INI_METAINS) == 0) &&
+ ((nLen == RTL_CONSTASCII_LENGTH(STR_INI_METAINS)) || (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '/') ||
+ (pPath[RTL_CONSTASCII_LENGTH(STR_INI_METAINS)] == '"') ) )
+ {
+ if (! lookupProfile(pPath + RTL_CONSTASCII_LENGTH(STR_INI_METAINS), aFile, aPath))
+ return (sal_False);
+
+ nPathLen = rtl_ustr_getLength(aPath);
+ }
+
+ else if( ::sal::static_int_cast< sal_uInt32 >( nLen ) < aPath.getBufSizeInSymbols())
+ {
+ copy_ustr_n(aPath, pPath, nLen+1);
+ nPathLen = rtl_ustr_getLength(aPath);
+ }
+ else
+ return sal_False;
+ }
+ else
+ {
+ rtl_uString * strConfigDir = NULL;
+ oslSecurity security = osl_getCurrentSecurity();
+
+ bFailed = ! osl_getConfigDir(security, &strConfigDir);
+ osl_freeSecurityHandle(security);
+
+ if (bFailed) return (sal_False);
+ if ( ::sal::static_int_cast< sal_uInt32 >( strConfigDir->length ) >= aPath.getBufSizeInSymbols() )
+ return sal_False;
+
+ copy_ustr_n(aPath, strConfigDir->buffer, strConfigDir->length+1);
+ nPathLen = strConfigDir->length;
+ }
+
+ if (nPathLen && (aPath[nPathLen - 1] != L'/') && (aPath[nPathLen - 1] != L'\\'))
+ {
+ aPath[nPathLen++] = L'\\';
+ aPath[nPathLen] = 0;
+ }
+
+ if (nPathLen + nFileLen >= aPath.getBufSizeInSymbols())
+ return sal_False;
+
+ /* append file name */
+ copy_ustr_n(aPath + nPathLen, aFile, nFileLen+1);
+ nPathLen += nFileLen;
+
+ /* copy filename */
+ rtl_uString_newFromStr_WithLength(&strTmp, aPath, nPathLen);
+ nError = osl_getFileURLFromSystemPath(strTmp, strProfileName);
+ rtl_uString_release(strTmp);
+
+ return (sal_Bool) (nError == osl_File_E_None);
+}
+
+
+sal_uInt32 SAL_CALL osl_getProfileSections(oslProfile Profile, sal_Char* pszBuffer, sal_uInt32 MaxLen)
+{
+ sal_uInt32 i, n = 0;
+ osl_TProfileSection* pSec;
+ osl_TProfileImpl* pProfile = acquireProfile(Profile, sal_False);
+
+ if (pProfile == NULL)
+ return (0);
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (MaxLen != 0)
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if ((n + pSec->m_Len + 1) < MaxLen)
+ {
+ strncpy(&pszBuffer[n], &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset],
+ pSec->m_Len);
+ n += pSec->m_Len;
+ pszBuffer[n++] = '\0';
+ }
+ else
+ break;
+ }
+
+ pszBuffer[n++] = '\0';
+ }
+ else
+ {
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ n += pProfile->m_Sections[i].m_Len + 1;
+
+ n += 1;
+ }
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aFileName( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(pProfile->m_strFileName->buffer), -1, aFileName, aFileName.getBufSizeInSymbols(), NULL, NULL);
+ n = GetPrivateProfileSectionNames(pszBuffer, MaxLen, aFileName);
+ }
+
+ releaseProfile(pProfile);
+
+ return (n);
+}
+
+
+
+
+/*****************************************************************************/
+/* Static Module Functions */
+/*****************************************************************************/
+
+static osl_TStamp getFileStamp(osl_TFile* pFile)
+{
+ FILETIME FileTime;
+
+ if ((pFile->m_Handle == INVALID_HANDLE_VALUE) ||
+ (! GetFileTime(pFile->m_Handle, NULL, NULL, &FileTime)))
+ memset(&FileTime, 0, sizeof(FileTime));
+
+ return (FileTime);
+}
+
+
+
+static sal_Bool lockFile(const osl_TFile* pFile, osl_TLockMode eMode)
+{
+ sal_Bool status = sal_False;
+ OVERLAPPED Overlapped;
+
+ if (pFile->m_Handle == INVALID_HANDLE_VALUE)
+ return (sal_False);
+
+ memset(&Overlapped, 0, sizeof(Overlapped));
+
+ switch (eMode)
+ {
+ case un_lock:
+ status = (sal_Bool) UnlockFileEx(
+ pFile->m_Handle, 0, 0xFFFFFFFF, 0, &Overlapped);
+ break;
+
+ case read_lock:
+ status = (sal_Bool) LockFileEx(
+ pFile->m_Handle, 0, 0, 0xFFFFFFFF, 0, &Overlapped);
+ break;
+
+ case write_lock:
+ status = (sal_Bool) LockFileEx(
+ pFile->m_Handle, LOCKFILE_EXCLUSIVE_LOCK, 0, 0xFFFFFFFF, 0,
+ &Overlapped);
+ break;
+ }
+
+ return (status);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static osl_TFile* openFileImpl(rtl_uString * strFileName, oslProfileOption ProfileFlags )
+{
+ osl_TFile* pFile = reinterpret_cast< osl_TFile*>( calloc( 1, sizeof(osl_TFile) ) );
+ sal_Bool bWriteable = sal_False;
+
+/* if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE | osl_Profile_READWRITE ) )*/
+ if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("setting bWriteable to TRUE\n");
+#endif
+ bWriteable=sal_True;
+ }
+
+ if (! bWriteable)
+ {
+#if 0
+//#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("opening '%s' read only\n",pszFilename);
+#endif
+
+ pFile->m_Handle = CreateFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strFileName )), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ /* mfe: argghh!!! do not check if the file could be openend */
+ /* default mode expects it that way!!! */
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("opening '%s' read/write\n",pszFilename);
+#endif
+
+ if ((pFile->m_Handle = CreateFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( strFileName )), GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
+ == INVALID_HANDLE_VALUE)
+ {
+ free(pFile);
+ return (NULL);
+ }
+ }
+
+ pFile->m_pWriteBuf=0;
+ pFile->m_nWriteBufFree=0;
+ pFile->m_nWriteBufLen=0;
+
+ if ( ProfileFlags & (osl_Profile_WRITELOCK | osl_Profile_READLOCK ) )
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("locking '%s' file\n",pszFilename);
+#endif
+
+ lockFile(pFile, bWriteable ? write_lock : read_lock);
+ }
+
+ /* mfe: new WriteBuf obsolete */
+/* pFile->m_pWritePtr = pFile->m_Buf;*/
+/* pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);*/
+
+ return (pFile);
+}
+
+
+
+
+
+
+
+
+
+static osl_TStamp closeFileImpl(osl_TFile* pFile)
+{
+ osl_TStamp stamp = {0, 0};
+
+ if ( pFile == 0 )
+ {
+ return stamp;
+ }
+
+ if (pFile->m_Handle != INVALID_HANDLE_VALUE)
+ {
+ /* mfe: new WriteBuf obsolete */
+ /* we just closing the file here, DO NOT write, it has to be handled in higher levels */
+/* if (pFile->m_pWritePtr > pFile->m_Buf)*/
+/* {*/
+/* DWORD Bytes;*/
+
+/* WriteFile(pFile->m_Handle, pFile->m_WriteBuf,*/
+/* pFile->m_pWritePtr - pFile->m_WriteBuf,*/
+/* &Bytes, NULL);*/
+/* }*/
+
+ stamp = getFileStamp(pFile);
+
+ lockFile(pFile, un_lock);
+
+ CloseHandle(pFile->m_Handle);
+ pFile->m_Handle = INVALID_HANDLE_VALUE;
+ }
+
+ if ( pFile->m_pWriteBuf != 0 )
+ {
+ free(pFile->m_pWriteBuf);
+ }
+
+ free(pFile);
+
+ return(stamp);
+}
+
+
+
+
+
+
+
+
+static sal_Bool rewindFile(osl_TFile* pFile, sal_Bool bTruncate)
+{
+ if (pFile->m_Handle != INVALID_HANDLE_VALUE)
+ {
+ /* mfe: new WriteBuf obsolete */
+ /* we just closing the file here, DO NOT write, it has to be handled in higher levels */
+/* if (pFile->m_pWritePtr > pFile->m_WriteBuf)*/
+/* {*/
+/* DWORD Bytes;*/
+
+/* WriteFile(pFile->m_Handle, pFile->m_WriteBuf,*/
+/* pFile->m_pWritePtr - pFile->m_WriteBuf,*/
+/* &Bytes, NULL);*/
+
+/* pFile->m_pWritePtr = pFile->m_WriteBuf;*/
+/* }*/
+
+ pFile->m_pReadPtr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+ SetFilePointer(pFile->m_Handle, 0, NULL, FILE_BEGIN);
+
+ if (bTruncate)
+ SetEndOfFile(pFile->m_Handle);
+ }
+
+ return (sal_True);
+}
+
+
+
+
+
+
+
+
+
+
+static sal_Bool getLine(osl_TFile* pFile, const sal_Char *pszLine, int MaxLen)
+{
+ DWORD Max;
+ size_t Free, Bytes;
+ sal_Char* pChr;
+ sal_Char* pLine = (sal_Char *)pszLine;
+
+ if (pFile->m_Handle == INVALID_HANDLE_VALUE)
+ return (sal_False);
+
+ MaxLen -= 1;
+
+ do
+ {
+ Bytes = sizeof(pFile->m_ReadBuf) - (pFile->m_pReadPtr - pFile->m_ReadBuf);
+
+ if (Bytes <= 1)
+ {
+ /* refill buffer */
+ memcpy(pFile->m_ReadBuf, pFile->m_pReadPtr, Bytes);
+ pFile->m_pReadPtr = pFile->m_ReadBuf;
+
+ Free = sizeof(pFile->m_ReadBuf) - Bytes;
+
+ if (! ReadFile(pFile->m_Handle, &pFile->m_ReadBuf[Bytes], Free, &Max, NULL))
+ {
+ *pLine = '\0';
+ return (sal_False);
+ }
+
+ if (Max < Free)
+ {
+ if ((Max == 0) && (pLine == pszLine))
+ {
+ *pLine = '\0';
+ return (sal_False);
+ }
+
+ pFile->m_ReadBuf[Bytes + Max] = '\0';
+ }
+ }
+
+ for (pChr = pFile->m_pReadPtr;
+ (*pChr != '\n') && (*pChr != '\r') && (*pChr != '\0') &&
+ (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1));
+ pChr++);
+
+ Max = min(pChr - pFile->m_pReadPtr, MaxLen);
+ memcpy(pLine, pFile->m_pReadPtr, Max);
+ MaxLen -= Max;
+ pLine += Max;
+
+ if (pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf) - 1))
+ {
+ if (*pChr != '\0')
+ {
+ if ((pChr[0] == '\r') && (pChr[1] == '\n'))
+ pChr += 2;
+ else
+ pChr += 1;
+ }
+
+ if ((pChr < (pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf))) &&
+ (*pChr == '\0'))
+ pChr = pFile->m_ReadBuf + sizeof(pFile->m_ReadBuf);
+
+ *pLine = '\0';
+
+ /* setting MaxLen to -1 indicates terminating read loop */
+ MaxLen = -1;
+ }
+
+ pFile->m_pReadPtr = pChr;
+ }
+ while (MaxLen > 0);
+
+ return (sal_True);
+}
+
+
+
+
+
+
+
+
+
+
+static sal_Bool putLine(osl_TFile* pFile, const sal_Char *pszLine)
+{
+ unsigned int Len = strlen(pszLine);
+
+#ifdef DEBUG_OSL_PROFILE
+ int strLen=0;
+#endif
+
+ if ( pFile == 0 || pFile->m_Handle < 0 )
+ {
+ return (sal_False);
+ }
+
+ if ( pFile->m_pWriteBuf == 0 )
+ {
+ pFile->m_pWriteBuf = (sal_Char*) malloc(Len+3);
+ pFile->m_nWriteBufLen = Len+3;
+ pFile->m_nWriteBufFree = Len+3;
+ }
+ else
+ {
+ if ( pFile->m_nWriteBufFree <= Len + 3 )
+ {
+ sal_Char* pTmp;
+
+ pTmp=(sal_Char*) realloc(pFile->m_pWriteBuf,( ( pFile->m_nWriteBufLen + Len ) * 2) );
+ if ( pTmp == 0 )
+ {
+ return sal_False;
+ }
+ pFile->m_pWriteBuf = pTmp;
+ pFile->m_nWriteBufFree = pFile->m_nWriteBufFree + pFile->m_nWriteBufLen + ( 2 * Len );
+ pFile->m_nWriteBufLen = ( pFile->m_nWriteBufLen + Len ) * 2;
+ memset( (pFile->m_pWriteBuf) + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ), 0, pFile->m_nWriteBufFree);
+ }
+ }
+
+
+
+ memcpy(pFile->m_pWriteBuf + ( pFile->m_nWriteBufLen - pFile->m_nWriteBufFree ),pszLine,Len+1);
+#ifdef DEBUG_OSL_PROFILE
+ strLen = strlen(pFile->m_pWriteBuf);
+#endif
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len]='\r';
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 1]='\n';
+ pFile->m_pWriteBuf[pFile->m_nWriteBufLen - pFile->m_nWriteBufFree + Len + 2]='\0';
+
+ pFile->m_nWriteBufFree-=Len+2;
+
+#ifdef DEBUG_OSL_PROFILE
+/* OSL_TRACE("File Buffer in _putLine '%s' '%i'(%i)\n",pFile->m_pWriteBuf,strlen(pFile->m_pWriteBuf),pFile->m_nWriteBufLen - pFile->m_nWriteBufFree);*/
+#endif
+
+ return (sal_True);
+}
+
+/* platform specific end */
+
+
+static const sal_Char* stripBlanks(const sal_Char* String, sal_uInt32* pLen)
+{
+ if ( (pLen != NULL) && ( *pLen != 0 ) )
+ {
+ while ((String[*pLen - 1] == ' ') || (String[*pLen - 1] == '\t'))
+ (*pLen)--;
+
+ while ((*String == ' ') || (*String == '\t'))
+ {
+ String++;
+ (*pLen)--;
+ }
+ }
+ else
+ while ((*String == ' ') || (*String == '\t'))
+ String++;
+
+ return (String);
+}
+
+static const sal_Char* addLine(osl_TProfileImpl* pProfile, const sal_Char* Line)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
+ memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+ else
+ {
+ unsigned int index=0;
+ unsigned int oldmax=pProfile->m_MaxLines;
+
+ pProfile->m_MaxLines += LINES_ADD;
+ pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines, pProfile->m_MaxLines * sizeof(sal_Char *));
+
+ for ( index = oldmax ; index < pProfile->m_MaxLines ; ++index )
+ {
+ pProfile->m_Lines[index]=0;
+ }
+ }
+
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return (NULL);
+ }
+
+ }
+
+ if ( pProfile->m_Lines != 0 && pProfile->m_Lines[pProfile->m_NoLines] != 0 )
+ {
+ free(pProfile->m_Lines[pProfile->m_NoLines]);
+ }
+ pProfile->m_Lines[pProfile->m_NoLines++] = strdup(Line);
+
+ return (pProfile->m_Lines[pProfile->m_NoLines - 1]);
+}
+
+static const sal_Char* insertLine(osl_TProfileImpl* pProfile, const sal_Char* Line, sal_uInt32 LineNo)
+{
+ if (pProfile->m_NoLines >= pProfile->m_MaxLines)
+ {
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_MaxLines = LINES_INI;
+ pProfile->m_Lines = (sal_Char **)malloc(pProfile->m_MaxLines * sizeof(sal_Char *));
+ memset(pProfile->m_Lines,0,pProfile->m_MaxLines * sizeof(sal_Char *));
+ }
+ else
+ {
+ pProfile->m_MaxLines += LINES_ADD;
+ pProfile->m_Lines = (sal_Char **)realloc(pProfile->m_Lines,
+ pProfile->m_MaxLines * sizeof(sal_Char *));
+
+ memset(&pProfile->m_Lines[pProfile->m_NoLines],
+ 0,
+ (pProfile->m_MaxLines - pProfile->m_NoLines - 1) * sizeof(sal_Char*));
+ }
+
+ if (pProfile->m_Lines == NULL)
+ {
+ pProfile->m_NoLines = 0;
+ pProfile->m_MaxLines = 0;
+ return (NULL);
+ }
+ }
+
+ LineNo = LineNo > pProfile->m_NoLines ? pProfile->m_NoLines : LineNo;
+
+ if (LineNo < pProfile->m_NoLines)
+ {
+ sal_uInt32 i, n;
+ osl_TProfileSection* pSec;
+
+ memmove(&pProfile->m_Lines[LineNo + 1], &pProfile->m_Lines[LineNo],
+ (pProfile->m_NoLines - LineNo) * sizeof(sal_Char *));
+
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line >= LineNo)
+ pSec->m_Line++;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line >= LineNo)
+ pSec->m_Entries[n].m_Line++;
+ }
+ }
+
+ pProfile->m_NoLines++;
+
+ pProfile->m_Lines[LineNo] = strdup(Line);
+
+ return (pProfile->m_Lines[LineNo]);
+}
+
+static void removeLine(osl_TProfileImpl* pProfile, sal_uInt32 LineNo)
+{
+ if (LineNo < pProfile->m_NoLines)
+ {
+ free(pProfile->m_Lines[LineNo]);
+ pProfile->m_Lines[LineNo]=0;
+ if (pProfile->m_NoLines - LineNo > 1)
+ {
+ sal_uInt32 i, n;
+ osl_TProfileSection* pSec;
+
+ memmove(&pProfile->m_Lines[LineNo], &pProfile->m_Lines[LineNo + 1],
+ (pProfile->m_NoLines - LineNo - 1) * sizeof(sal_Char *));
+
+ memset(&pProfile->m_Lines[pProfile->m_NoLines - 1],
+ 0,
+ (pProfile->m_MaxLines - pProfile->m_NoLines) * sizeof(sal_Char*));
+
+ /* adjust line references */
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ pSec = &pProfile->m_Sections[i];
+
+ if (pSec->m_Line > LineNo)
+ pSec->m_Line--;
+
+ for (n = 0; n < pSec->m_NoEntries; n++)
+ if (pSec->m_Entries[n].m_Line > LineNo)
+ pSec->m_Entries[n].m_Line--;
+ }
+ }
+ else
+ {
+ pProfile->m_Lines[LineNo] = 0;
+ }
+
+ pProfile->m_NoLines--;
+ }
+
+ return;
+}
+
+static void setEntry(osl_TProfileImpl* pProfile, osl_TProfileSection* pSection,
+ sal_uInt32 NoEntry, sal_uInt32 Line,
+ const sal_Char* Entry, sal_uInt32 Len)
+{
+ Entry = stripBlanks(Entry, &Len);
+ pSection->m_Entries[NoEntry].m_Line = Line;
+ pSection->m_Entries[NoEntry].m_Offset = Entry - pProfile->m_Lines[Line];
+ pSection->m_Entries[NoEntry].m_Len = Len;
+
+ return;
+}
+
+static sal_Bool addEntry(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection,
+ int Line, const sal_Char* Entry, sal_uInt32 Len)
+{
+ if (pSection != NULL)
+ {
+ if (pSection->m_NoEntries >= pSection->m_MaxEntries)
+ {
+ if (pSection->m_Entries == NULL)
+ {
+ pSection->m_MaxEntries = ENTRIES_INI;
+ pSection->m_Entries = (osl_TProfileEntry *)malloc(
+ pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
+ }
+ else
+ {
+ pSection->m_MaxEntries += ENTRIES_ADD;
+ pSection->m_Entries = (osl_TProfileEntry *)realloc(pSection->m_Entries,
+ pSection->m_MaxEntries * sizeof(osl_TProfileEntry));
+ }
+
+ if (pSection->m_Entries == NULL)
+ {
+ pSection->m_NoEntries = 0;
+ pSection->m_MaxEntries = 0;
+ return (sal_False);
+ }
+ }
+
+ pSection->m_NoEntries++;
+
+ Entry = stripBlanks(Entry, &Len);
+ setEntry(pProfile, pSection, pSection->m_NoEntries - 1, Line,
+ Entry, Len);
+
+ return (sal_True);
+ }
+
+ return (sal_False);
+}
+
+static void removeEntry(osl_TProfileSection *pSection, sal_uInt32 NoEntry)
+{
+ if (NoEntry < pSection->m_NoEntries)
+ {
+ if (pSection->m_NoEntries - NoEntry > 1)
+ {
+ memmove(&pSection->m_Entries[NoEntry],
+ &pSection->m_Entries[NoEntry + 1],
+ (pSection->m_NoEntries - NoEntry - 1) * sizeof(osl_TProfileEntry));
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Line=0;
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Offset=0;
+ pSection->m_Entries[pSection->m_NoEntries - 1].m_Len=0;
+ }
+
+ pSection->m_NoEntries--;
+ }
+
+ return;
+}
+
+static sal_Bool addSection(osl_TProfileImpl* pProfile, int Line, const sal_Char* Section, sal_uInt32 Len)
+{
+ if (pProfile->m_NoSections >= pProfile->m_MaxSections)
+ {
+ if (pProfile->m_Sections == NULL)
+ {
+ pProfile->m_MaxSections = SECTIONS_INI;
+ pProfile->m_Sections = (osl_TProfileSection *)malloc(pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ memset(pProfile->m_Sections,0,pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ }
+ else
+ {
+ unsigned int index=0;
+ unsigned int oldmax=pProfile->m_MaxSections;
+
+ pProfile->m_MaxSections += SECTIONS_ADD;
+ pProfile->m_Sections = (osl_TProfileSection *)realloc(pProfile->m_Sections,
+ pProfile->m_MaxSections * sizeof(osl_TProfileSection));
+ for ( index = oldmax ; index < pProfile->m_MaxSections ; ++index )
+ {
+ pProfile->m_Sections[index].m_Entries=0;
+ }
+ }
+
+ if (pProfile->m_Sections == NULL)
+ {
+ pProfile->m_NoSections = 0;
+ pProfile->m_MaxSections = 0;
+ return (sal_False);
+ }
+ }
+
+ pProfile->m_NoSections++;
+
+ if ( pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries != 0 )
+ {
+ free(pProfile->m_Sections[(pProfile->m_NoSections) - 1].m_Entries);
+ }
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = NULL;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_NoEntries = 0;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_MaxEntries = 0;
+
+ Section = (sal_Char *)stripBlanks(Section, &Len);
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Line = Line;
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Offset = Section - pProfile->m_Lines[Line];
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Len = Len;
+
+ return (sal_True);
+}
+
+static void removeSection(osl_TProfileImpl* pProfile, osl_TProfileSection *pSection)
+{
+ sal_uInt32 Section;
+
+ if ((Section = pSection - pProfile->m_Sections) < pProfile->m_NoSections)
+ {
+ free (pSection->m_Entries);
+ pSection->m_Entries=0;
+ if (pProfile->m_NoSections - Section > 1)
+ {
+ memmove(&pProfile->m_Sections[Section], &pProfile->m_Sections[Section + 1],
+ (pProfile->m_NoSections - Section - 1) * sizeof(osl_TProfileSection));
+
+ memset(&pProfile->m_Sections[pProfile->m_NoSections - 1],
+ 0,
+ (pProfile->m_MaxSections - pProfile->m_NoSections) * sizeof(osl_TProfileSection));
+ pProfile->m_Sections[pProfile->m_NoSections - 1].m_Entries = 0;
+ }
+ else
+ {
+ pSection->m_Entries = 0;
+ }
+
+ pProfile->m_NoSections--;
+ }
+
+ return;
+}
+
+static osl_TProfileSection* findEntry(osl_TProfileImpl* pProfile, const sal_Char* Section,
+ const sal_Char* Entry, sal_uInt32 *pNoEntry)
+{
+static sal_uInt32 Sect = 0;
+ sal_uInt32 i, n;
+ sal_uInt32 Len;
+ const sal_Char* pStr;
+ osl_TProfileSection* pSec = NULL;
+
+ Len = strlen(Section);
+ Section = (sal_Char *)stripBlanks(Section, &Len);
+
+ n = Sect;
+
+ for (i = 0; i < pProfile->m_NoSections; i++)
+ {
+ n %= pProfile->m_NoSections;
+ pSec = &pProfile->m_Sections[n];
+ if ((Len == pSec->m_Len) &&
+ (strnicmp(Section, &pProfile->m_Lines[pSec->m_Line][pSec->m_Offset], pSec->m_Len)
+ == 0))
+ break;
+ n++;
+ }
+
+ Sect = n;
+
+ if (i < pProfile->m_NoSections)
+ {
+ Len = strlen(Entry);
+ Entry = stripBlanks(Entry, &Len);
+
+ *pNoEntry = pSec->m_NoEntries;
+
+ for (i = 0; i < pSec->m_NoEntries; i++)
+ {
+ pStr = &pProfile->m_Lines[pSec->m_Entries[i].m_Line]
+ [pSec->m_Entries[i].m_Offset];
+ if ((Len == pSec->m_Entries[i].m_Len) &&
+ (strnicmp(Entry, pStr, pSec->m_Entries[i].m_Len)
+ == 0))
+ {
+ *pNoEntry = i;
+ break;
+ }
+ }
+ }
+ else
+ pSec = NULL;
+
+ return (pSec);
+}
+
+static sal_Bool loadProfile(osl_TFile* pFile, osl_TProfileImpl* pProfile)
+{
+ sal_uInt32 i;
+ sal_Char* pStr;
+ sal_Char* pChar;
+ sal_Char Line[4096];
+
+ pProfile->m_NoLines = 0;
+ pProfile->m_NoSections = 0;
+
+ OSL_VERIFY(rewindFile(pFile, sal_False));
+
+ while (getLine(pFile, Line, sizeof(Line)))
+ {
+ if (! addLine(pProfile, Line))
+ return (sal_False);
+ }
+
+ for (i = 0; i < pProfile->m_NoLines; i++)
+ {
+ pStr = (sal_Char *)stripBlanks(pProfile->m_Lines[i], NULL);
+
+ if ((*pStr == '\0') || (*pStr == ';'))
+ continue;
+
+ if ((*pStr != '[') || ((pChar = strrchr(pStr, ']')) == NULL) ||
+ ((pChar - pStr) <= 2))
+ {
+ /* insert entry */
+
+ if (pProfile->m_NoSections < 1)
+ continue;
+
+ if ((pChar = strchr(pStr, '=')) == NULL)
+ pChar = pStr + strlen(pStr);
+
+ if (! addEntry(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1],
+ i, pStr, pChar - pStr))
+ return (sal_False);
+ }
+ else
+ {
+ /* new section */
+
+ if (! addSection(pProfile, i, pStr + 1, pChar - pStr - 1))
+ return (sal_False);
+ }
+ }
+
+ return (sal_True);
+}
+
+
+
+
+
+static sal_Bool storeProfile(osl_TProfileImpl* pProfile, sal_Bool bCleanup)
+{
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In storeProfile\n");
+#endif
+
+ if (pProfile->m_Lines != NULL)
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ {
+ sal_uInt32 i;
+
+ osl_TFile* pTmpFile = osl_openTmpProfileImpl(pProfile);
+
+ if ( pTmpFile == 0 )
+ {
+ return sal_False;
+ }
+
+ OSL_VERIFY(rewindFile(pTmpFile, sal_True));
+
+ for (i = 0; i < pProfile->m_NoLines; i++)
+ {
+ OSL_VERIFY(putLine(pTmpFile, pProfile->m_Lines[i]));
+ }
+
+ if ( ! writeProfileImpl(pTmpFile) )
+ {
+ if ( pTmpFile->m_pWriteBuf != 0 )
+ {
+ free(pTmpFile->m_pWriteBuf);
+ }
+
+ pTmpFile->m_pWriteBuf=0;
+ pTmpFile->m_nWriteBufLen=0;
+ pTmpFile->m_nWriteBufFree=0;
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out storeProfile [not flushed]\n");
+#endif
+ closeFileImpl(pTmpFile);
+
+ return sal_False;
+ }
+
+ pProfile->m_Flags &= ~FLG_MODIFIED;
+
+ closeFileImpl(pProfile->m_pFile);
+ closeFileImpl(pTmpFile);
+
+ osl_ProfileSwapProfileNames(pProfile);
+
+/* free(pProfile->m_pFile);*/
+/* free(pTmpFile);*/
+
+ pProfile->m_pFile = openFileImpl(pProfile->m_strFileName,pProfile->m_Flags);
+
+ }
+
+ if (bCleanup)
+ {
+ while (pProfile->m_NoLines > 0)
+ removeLine(pProfile, pProfile->m_NoLines - 1);
+
+ free(pProfile->m_Lines);
+ pProfile->m_Lines = NULL;
+ pProfile->m_MaxLines = 0;
+
+ while (pProfile->m_NoSections > 0)
+ removeSection(pProfile, &pProfile->m_Sections[pProfile->m_NoSections - 1]);
+
+ free(pProfile->m_Sections);
+ pProfile->m_Sections = NULL;
+ pProfile->m_MaxSections = 0;
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out storeProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+
+static osl_TFile* osl_openTmpProfileImpl(osl_TProfileImpl* pProfile)
+{
+ osl_TFile* pFile=0;
+ rtl_uString* ustrExtension=0;
+ rtl_uString* ustrTmpName=0;
+ oslProfileOption PFlags=0;
+
+ rtl_uString_newFromAscii(&ustrExtension,"tmp");
+
+
+ /* generate tmp profilename */
+ ustrTmpName=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+
+ if ( ustrTmpName == 0 )
+ {
+ return 0;
+ }
+
+
+ if ( ! ( pProfile->m_Flags & osl_Profile_READLOCK ) )
+ {
+ PFlags |= osl_Profile_WRITELOCK;
+ }
+
+ /* open this file */
+ pFile = openFileImpl(ustrTmpName,pProfile->m_Flags | PFlags);
+
+
+ /* return new pFile */
+ return pFile;
+}
+
+
+static sal_Bool osl_ProfileSwapProfileNames(osl_TProfileImpl* pProfile)
+{
+ sal_Bool bRet = sal_False;
+
+ rtl_uString* ustrBakFile=0;
+ rtl_uString* ustrTmpFile=0;
+ rtl_uString* ustrIniFile=0;
+ rtl_uString* ustrExtension=0;
+
+
+ rtl_uString_newFromAscii(&ustrExtension,"bak");
+
+ ustrBakFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+ ustrExtension=0;
+
+
+ rtl_uString_newFromAscii(&ustrExtension,"ini");
+
+ ustrIniFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+ ustrExtension=0;
+
+
+ rtl_uString_newFromAscii(&ustrExtension,"tmp");
+
+ ustrTmpFile=osl_ProfileGenerateExtension(pProfile->m_strFileName,ustrExtension);
+ rtl_uString_release(ustrExtension);
+ ustrExtension=0;
+
+
+ /* unlink bak */
+ DeleteFileW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrBakFile )) );
+
+ /* rename ini bak */
+ MoveFileExW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrIniFile )), reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrBakFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
+
+ /* rename tmp ini */
+ MoveFileExW( reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrTmpFile )), reinterpret_cast<LPCWSTR>(rtl_uString_getStr( ustrIniFile )), MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH );
+
+ return bRet;
+}
+
+
+static rtl_uString* osl_ProfileGenerateExtension(rtl_uString* ustrFileName, rtl_uString* ustrExtension)
+{
+ rtl_uString* ustrNewFileName=0;
+ rtl_uString* ustrOldExtension = 0;
+ sal_Unicode* pExtensionBuf = 0;
+ sal_Unicode* pFileNameBuf = 0;
+ sal_Int32 nIndex = -1;
+
+ pFileNameBuf = rtl_uString_getStr(ustrFileName);
+
+ rtl_uString_newFromAscii(&ustrOldExtension,".");
+
+ pExtensionBuf = rtl_uString_getStr(ustrOldExtension);
+
+ nIndex = rtl_ustr_lastIndexOfChar(pFileNameBuf,*pExtensionBuf);
+
+ rtl_uString_newReplaceStrAt(&ustrNewFileName,
+ ustrFileName,
+ nIndex+1,
+ 3,
+ ustrExtension);
+
+ return ustrNewFileName;
+}
+
+
+static osl_TProfileImpl* acquireProfile(oslProfile Profile, sal_Bool bWriteable)
+{
+ osl_TProfileImpl* pProfile = (osl_TProfileImpl*)Profile;
+ oslProfileOption PFlags=0;
+
+
+ if ( bWriteable )
+ {
+/* PFlags = osl_Profile_DEFAULT | osl_Profile_READWRITE; */
+ PFlags = osl_Profile_DEFAULT | osl_Profile_WRITELOCK;
+ }
+ else
+ {
+ PFlags = osl_Profile_DEFAULT;
+ }
+
+
+ if (pProfile == NULL)
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("AUTOOPEN MODE\n");
+#endif
+
+
+
+ if ( ( pProfile = (osl_TProfileImpl*)osl_openProfile( NULL, PFlags ) ) != NULL )
+ {
+ pProfile->m_Flags |= FLG_AUTOOPEN;
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("try to acquire\n");
+#endif
+
+
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
+ osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
+ {
+ osl_TStamp Stamp;
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("DEFAULT MODE\n");
+#endif
+ pProfile->m_pFile = openFileImpl(
+ pProfile->m_strFileName, pProfile->m_Flags | PFlags);
+ if (!pProfile->m_pFile)
+ return NULL;
+
+ Stamp = getFileStamp(pProfile->m_pFile);
+
+ if (memcmp(&Stamp, &(pProfile->m_Stamp), sizeof(osl_TStamp)))
+ {
+ pProfile->m_Stamp = Stamp;
+
+ loadProfile(pProfile->m_pFile, pProfile);
+ }
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("READ/WRITELOCK MODE\n");
+#endif
+
+
+ /* A readlock file could not be written */
+ if ((pProfile->m_Flags & osl_Profile_READLOCK) && bWriteable)
+ {
+ return (NULL);
+ }
+ }
+ }
+ }
+
+ return (pProfile);
+}
+
+static sal_Bool releaseProfile(osl_TProfileImpl* pProfile)
+{
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("In releaseProfile\n");
+#endif
+
+ if ( pProfile == 0 )
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [profile==0]\n");
+#endif
+ return sal_False;
+ }
+
+ if (! (pProfile->m_Flags & osl_Profile_SYSTEM))
+ {
+ if (pProfile->m_Flags & FLG_AUTOOPEN)
+ {
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [AUTOOPEN]\n");
+#endif
+ return (osl_closeProfile((oslProfile)pProfile));
+ }
+ else
+ {
+#ifdef DEBUG_OSL_PROFILE
+ OSL_TRACE("DEFAULT MODE\n");
+#endif
+ if (! (pProfile->m_Flags & (osl_Profile_READLOCK |
+ osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE)))
+ {
+ if (pProfile->m_Flags & FLG_MODIFIED)
+ storeProfile(pProfile, sal_False);
+
+ closeFileImpl(pProfile->m_pFile);
+ pProfile->m_pFile = NULL;
+ }
+ }
+ }
+
+#ifdef TRACE_OSL_PROFILE
+ OSL_TRACE("Out releaseProfile [ok]\n");
+#endif
+ return (sal_True);
+}
+
+static sal_Bool lookupProfile(const sal_Unicode *strPath, const sal_Unicode *strFile, sal_Unicode *strProfile)
+{
+ sal_Char *pChr, *pStr;
+ sal_Char Buffer[4096] = "";
+ sal_Char Product[132] = "";
+
+ ::osl::LongPathBuffer< sal_Unicode > aPath( MAX_LONG_PATH );
+ aPath[0] = 0;
+ DWORD dwPathLen = 0;
+
+ if (*strPath == L'"')
+ {
+ int i = 0;
+
+ strPath++;
+
+ while ((strPath[i] != L'"') && (strPath[i] != L'\0'))
+ i++;
+
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(strPath), i, Product, sizeof(Product), NULL, NULL);
+ Product[i] = '\0';
+ strPath += i;
+
+ if (*strPath == L'"')
+ strPath++;
+
+ if ( (*strPath == L'/') || (*strPath == L'\\') )
+ {
+ strPath++;
+ }
+ }
+
+ else
+ {
+ /* if we have not product identfication, do a special handling for soffice.ini */
+ if (rtl_ustr_ascii_compare(strFile, SVERSION_PROFILE) == 0)
+ {
+ rtl_uString * strSVProfile = NULL;
+ rtl_uString * strSVFallback = NULL;
+ rtl_uString * strSVLocation = NULL;
+ rtl_uString * strSVName = NULL;
+ ::osl::LongPathBuffer< sal_Char > aDir( MAX_LONG_PATH );
+ oslProfile hProfile;
+
+ rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
+ rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
+ rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
+
+ /* open sversion.ini in the system directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if (osl_getProfileName( strSVFallback, strSVName, &strSVProfile))
+ {
+ hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_getProfileSectionEntries(
+ hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
+
+ for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
+ {
+ if ((strnicmp(
+ pChr, SVERSION_SOFFICE,
+ sizeof(SVERSION_SOFFICE) - 1)
+ == 0)
+ && (stricmp(Product, pChr) < 0))
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, pChr, aDir,
+ aDir.getBufSizeInSymbols(), "");
+
+ /* check for existence of path */
+ if (access(aDir, 0) >= 0)
+ strcpy(Product, pChr);
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+ rtl_uString_release(strSVProfile);
+ strSVProfile = NULL;
+ }
+
+ /* open sversion.ini in the users directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if ((strcmp(SVERSION_LOCATION, SVERSION_FALLBACK) != 0) &&
+ (osl_getProfileName(strSVLocation, strSVName, &strSVProfile)))
+ {
+ hProfile = osl_openProfile(strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_getProfileSectionEntries(
+ hProfile, SVERSION_SECTION, Buffer, sizeof(Buffer));
+
+ for (pChr = Buffer; *pChr != '\0'; pChr += strlen(pChr) + 1)
+ {
+ if ((strnicmp(
+ pChr, SVERSION_SOFFICE,
+ sizeof(SVERSION_SOFFICE) - 1)
+ == 0)
+ && (stricmp(Product, pChr) < 0))
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, pChr, aDir,
+ aDir.getBufSizeInSymbols(), "");
+
+ /* check for existence of path */
+ if (access(aDir, 0) >= 0)
+ strcpy(Product, pChr);
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+ rtl_uString_release(strSVProfile);
+ }
+
+ rtl_uString_release(strSVFallback);
+ rtl_uString_release(strSVLocation);
+ rtl_uString_release(strSVName);
+
+ /* remove any trailing build number */
+ if ((pChr = strrchr(Product, '/')) != NULL)
+ *pChr = '\0';
+ }
+ }
+
+ /* if we have an userid option eg. "-userid:rh[/usr/home/rh/staroffice]",
+ this will supercede all other locations */
+ {
+ sal_uInt32 n, nArgs = osl_getCommandArgCount();
+
+ for (n = 0; n < nArgs; n++)
+ {
+ rtl_uString * strCommandArg = NULL;
+
+ if ((osl_getCommandArg( n, &strCommandArg ) == osl_Process_E_None) &&
+ ((strCommandArg->buffer[0] == L'-') || (strCommandArg->buffer[0] == L'+')) &&
+ (rtl_ustr_ascii_compare_WithLength(strCommandArg->buffer, RTL_CONSTASCII_LENGTH(SVERSION_OPTION), SVERSION_OPTION)))
+ {
+ sal_Unicode *pCommandArg = strCommandArg->buffer + RTL_CONSTASCII_LENGTH(SVERSION_OPTION);
+ sal_Int32 nStart, nEnd;
+
+ if (((nStart = rtl_ustr_indexOfChar(pCommandArg, L'[')) != -1) &&
+ ((nEnd = rtl_ustr_indexOfChar(pCommandArg + nStart + 1, L']')) != -1))
+ {
+ dwPathLen = nEnd;
+ copy_ustr_n(aPath, pCommandArg + nStart + 1, dwPathLen);
+ aPath[dwPathLen] = 0;
+
+ /* build full path */
+ if ((aPath[dwPathLen - 1] != L'/') && (aPath[dwPathLen - 1] != L'\\'))
+ {
+ copy_ustr_n(aPath + dwPathLen++, L"/", 2);
+ }
+
+ if (*strPath)
+ {
+ copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen += rtl_ustr_getLength(strPath);
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
+ int n;
+
+ if ((n = WideCharToMultiByte(CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), NULL, NULL)) > 0)
+ {
+ strcpy(aTmpPath + n, SVERSION_USER);
+ if (access(aTmpPath, 0) >= 0)
+ {
+ dwPathLen += MultiByteToWideChar( CP_ACP, 0, SVERSION_USER, -1, reinterpret_cast<LPWSTR>(aPath + dwPathLen), aPath.getBufSizeInSymbols() - dwPathLen );
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+
+ if (dwPathLen == 0)
+ {
+ rtl_uString * strExecutable = NULL;
+ rtl_uString * strTmp = NULL;
+ sal_Int32 nPos;
+
+ /* try to find the file in the directory of the executbale */
+ if (osl_getExecutableFile(&strTmp) != osl_Process_E_None)
+ return (sal_False);
+
+ /* convert to native path */
+ if (osl_getSystemPathFromFileURL(strTmp, &strExecutable) != osl_File_E_None)
+ {
+ rtl_uString_release(strTmp);
+ return sal_False;
+ }
+
+ rtl_uString_release(strTmp);
+
+ /* seperate path from filename */
+ if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L'\\')) == -1)
+ {
+ if ((nPos = rtl_ustr_lastIndexOfChar(strExecutable->buffer, L':')) == -1)
+ {
+ return sal_False;
+ }
+ else
+ {
+ copy_ustr_n(aPath, strExecutable->buffer, nPos);
+ aPath[nPos] = 0;
+ dwPathLen = nPos;
+ }
+ }
+ else
+ {
+ copy_ustr_n(aPath, strExecutable->buffer, nPos);
+ dwPathLen = nPos;
+ aPath[dwPathLen] = 0;
+ }
+
+ /* if we have no product identification use the executable file name */
+ if (*Product == 0)
+ {
+ WideCharToMultiByte(CP_ACP,0, reinterpret_cast<LPCWSTR>(strExecutable->buffer + nPos + 1), -1, Product, sizeof(Product), NULL, NULL);
+
+ /* remove extension */
+ if ((pChr = strrchr(Product, '.')) != NULL)
+ *pChr = '\0';
+ }
+
+ rtl_uString_release(strExecutable);
+
+ /* remember last subdir */
+ nPos = rtl_ustr_lastIndexOfChar(aPath, L'\\');
+
+ copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
+
+ if (*strPath)
+ {
+ copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen += rtl_ustr_getLength(strPath);
+ }
+
+ {
+ ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), NULL, NULL);
+
+ /* if file not exists, remove any specified subdirectories
+ like "bin" or "program" */
+
+ if (((access(aTmpPath, 0) < 0) && (nPos != -1)) || (*strPath == 0))
+ {
+ static sal_Char *SubDirs[] = SVERSION_DIRS;
+
+ int i = 0;
+ pStr = aTmpPath + nPos;
+
+ for (i = 0; i < (sizeof(SubDirs) / sizeof(SubDirs[0])); i++)
+ if (strnicmp(pStr + 1, SubDirs[i], strlen(SubDirs[i])) == 0)
+ {
+ if ( *strPath == 0)
+ {
+ strcpy(pStr + 1,SVERSION_USER);
+ if ( access(aTmpPath, 0) < 0 )
+ {
+ *(pStr+1)='\0';
+ }
+ else
+ {
+ dwPathLen = nPos + MultiByteToWideChar( CP_ACP, 0, SVERSION_USER, -1, reinterpret_cast<LPWSTR>(aPath + nPos + 1), aPath.getBufSizeInSymbols() - (nPos + 1) );
+ }
+ }
+ else
+ {
+ copy_ustr_n(aPath + nPos + 1, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen = nPos + 1 + rtl_ustr_getLength(strPath);
+ }
+
+ break;
+ }
+ }
+ }
+
+ if ((aPath[dwPathLen - 1] != L'/') && (aPath[dwPathLen - 1] != L'\\'))
+ {
+ aPath[dwPathLen++] = L'\\';
+ aPath[dwPathLen] = 0;
+ }
+
+ copy_ustr_n(aPath + dwPathLen, strFile, rtl_ustr_getLength(strFile)+1);
+
+ {
+ ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
+
+ WideCharToMultiByte(CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath, aTmpPath.getBufSizeInSymbols(), NULL, NULL);
+
+ if ((access(aTmpPath, 0) < 0) && (strlen(Product) > 0))
+ {
+ rtl_uString * strSVFallback = NULL;
+ rtl_uString * strSVProfile = NULL;
+ rtl_uString * strSVLocation = NULL;
+ rtl_uString * strSVName = NULL;
+ oslProfile hProfile;
+
+ rtl_uString_newFromAscii(&strSVFallback, SVERSION_FALLBACK);
+ rtl_uString_newFromAscii(&strSVLocation, SVERSION_LOCATION);
+ rtl_uString_newFromAscii(&strSVName, SVERSION_NAME);
+
+ /* open sversion.ini in the system directory, and try to locate the entry
+ with the highest version for StarOffice */
+ if (osl_getProfileName(strSVLocation, strSVName, &strSVProfile))
+ {
+ hProfile = osl_openProfile(
+ strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, Product, Buffer,
+ sizeof(Buffer), "");
+ osl_closeProfile(hProfile);
+
+ /* if not found, try the fallback */
+ if ((strlen(Buffer) <= 0)
+ && (strcmp(SVERSION_LOCATION, SVERSION_FALLBACK)
+ != 0))
+ {
+ if (osl_getProfileName(
+ strSVFallback, strSVName, &strSVProfile))
+ {
+ hProfile = osl_openProfile(
+ strSVProfile, osl_Profile_READLOCK);
+ if (hProfile)
+ {
+ osl_readProfileString(
+ hProfile, SVERSION_SECTION, Product,
+ Buffer, sizeof(Buffer), "");
+ }
+ }
+
+ osl_closeProfile(hProfile);
+ }
+
+ if (strlen(Buffer) > 0)
+ {
+ dwPathLen = MultiByteToWideChar(
+ CP_ACP, 0, Buffer, -1, ::osl::mingw_reinterpret_cast<LPWSTR>(aPath), aPath.getBufSizeInSymbols() );
+ dwPathLen -=1;
+
+ /* build full path */
+ if ((aPath[dwPathLen - 1] != L'/')
+ && (aPath[dwPathLen - 1] != L'\\'))
+ {
+ copy_ustr_n(aPath + dwPathLen++, L"\\", 2);
+ }
+
+ if (*strPath)
+ {
+ copy_ustr_n(aPath + dwPathLen, strPath, rtl_ustr_getLength(strPath)+1);
+ dwPathLen += rtl_ustr_getLength(strPath);
+ }
+ else
+ {
+ ::osl::LongPathBuffer< sal_Char > aTmpPath( MAX_LONG_PATH );
+ int n;
+
+ if ((n = WideCharToMultiByte(
+ CP_ACP,0, ::osl::mingw_reinterpret_cast<LPCWSTR>(aPath), -1, aTmpPath,
+ aTmpPath.getBufSizeInSymbols(), NULL, NULL))
+ > 0)
+ {
+ strcpy(aTmpPath + n, SVERSION_USER);
+ if (access(aTmpPath, 0) >= 0)
+ {
+ dwPathLen += MultiByteToWideChar(
+ CP_ACP, 0, SVERSION_USER, -1,
+ reinterpret_cast<LPWSTR>(aPath + dwPathLen),
+ aPath.getBufSizeInSymbols() - dwPathLen );
+ }
+ }
+ }
+ }
+ }
+
+ rtl_uString_release(strSVProfile);
+ }
+
+ rtl_uString_release(strSVFallback);
+ rtl_uString_release(strSVLocation);
+ rtl_uString_release(strSVName);
+ }
+ }
+
+ aPath[dwPathLen] = 0;
+ }
+
+ /* copy filename */
+ copy_ustr_n(strProfile, aPath, dwPathLen+1);
+
+ return sal_True;
+}
+
+
diff --git a/sal/osl/w32/salinit.cxx b/sal/osl/w32/salinit.cxx
new file mode 100644
index 000000000000..aea584f67970
--- /dev/null
+++ b/sal/osl/w32/salinit.cxx
@@ -0,0 +1,82 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "system.h"
+#include <osl/process.h>
+#include <sal/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Prototypes for initialization and deinitialization of SAL library
+
+void SAL_CALL sal_detail_initialize(int argc, char ** argv)
+{
+ WSADATA wsaData;
+ int error;
+ WORD wVersionRequested;
+
+ wVersionRequested = MAKEWORD(1, 1);
+
+ error = WSAStartup(wVersionRequested, &wsaData);
+ if ( 0 == error )
+ {
+ WORD wMajorVersionRequired = 1;
+ WORD wMinorVersionRequired = 1;
+
+ if ((LOBYTE(wsaData.wVersion) < wMajorVersionRequired) ||
+ (LOBYTE(wsaData.wVersion) == wMajorVersionRequired) &&
+ ((HIBYTE(wsaData.wVersion) < wMinorVersionRequired)))
+ {
+ // How to handle a very unlikely error ???
+ }
+ }
+ else
+ {
+ // How to handle a very unlikely error ???
+ }
+
+ osl_setCommandArgs(argc, argv);
+}
+
+void SAL_CALL sal_detail_deinitialize()
+{
+ if ( SOCKET_ERROR == WSACleanup() )
+ {
+ // We should never reach this point or we did wrong elsewhere
+ }
+}
+
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/sal/osl/w32/secimpl.h b/sal/osl/w32/secimpl.h
new file mode 100644
index 000000000000..97a9d9c44f9e
--- /dev/null
+++ b/sal/osl/w32/secimpl.h
@@ -0,0 +1,54 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_SECURITYIMPL_H_
+#define _OSL_SECURITYIMPL_H_
+
+#include <winnetwk.h>
+
+#include <osl/security.h>
+
+#define USER_BUFFER_SIZE 256
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _oslSecurityImpl {
+ HANDLE m_hProfile;
+ HANDLE m_hToken;
+ sal_Unicode m_User[USER_BUFFER_SIZE];
+/* ts: Erweiterung um Fileserver-login */
+ NETRESOURCEW *m_pNetResource;
+} oslSecurityImpl;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/sal/osl/w32/security.c b/sal/osl/w32/security.c
new file mode 100644
index 000000000000..237ea67dc949
--- /dev/null
+++ b/sal/osl/w32/security.c
@@ -0,0 +1,991 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include "system.h"
+
+#include <osl/security.h>
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <osl/file.h>
+#include <systools/win32/uwinapi.h>
+#include "secimpl.h"
+
+/*****************************************************************************/
+/* Data Type Definition */
+/*****************************************************************************/
+
+
+/* Data for use in (un)LoadProfile Functions */
+/* Declarations based on USERENV.H for Windows 2000 Beta 2 */
+#define PI_NOUI 0x00000001 // Prevents displaying of messages
+#define PI_APPLYPOLICY 0x00000002 // Apply NT4 style policy
+
+typedef struct _PROFILEINFOW {
+ DWORD dwSize; // Must be set to sizeof(PROFILEINFO)
+ DWORD dwFlags; // See flags above
+ LPWSTR lpUserName; // User name (required)
+ LPWSTR lpProfilePath; // Roaming profile path
+ LPWSTR lpDefaultPath; // Default user profile path
+ LPWSTR lpServerName; // Validating DC name in netbios format
+ LPWSTR lpPolicyPath; // Path to the NT4 style policy file
+ HANDLE hProfile; // Registry key handle - filled by function
+} PROFILEINFOW, FAR * LPPROFILEINFOW;
+
+/* Typedefs for function pointers in USERENV.DLL */
+typedef BOOL (STDMETHODCALLTYPE FAR * LPFNLOADUSERPROFILE) (
+ HANDLE hToken,
+ LPPROFILEINFOW lpProfileInfo
+);
+
+typedef BOOL (STDMETHODCALLTYPE FAR * LPFNUNLOADUSERPROFILE) (
+ HANDLE hToken,
+ HANDLE hProfile
+);
+
+typedef BOOL (STDMETHODCALLTYPE FAR * LPFNGETUSERPROFILEDIR) (
+ HANDLE hToken,
+ LPTSTR lpProfileDir,
+ LPDWORD lpcchSize
+);
+
+/* To get an impersonation token we need to create an impersonation
+ duplicate so every access token has to be created with duplicate
+ access rights */
+
+#define TOKEN_DUP_QUERY (TOKEN_QUERY|TOKEN_DUPLICATE)
+
+/*****************************************************************************/
+/* Static Module Function Declarations */
+/*****************************************************************************/
+
+static sal_Bool isWNT(void);
+static sal_Bool GetSpecialFolder(rtl_uString **strPath,int nFolder);
+static BOOL Privilege(LPTSTR pszPrivilege, BOOL bEnable);
+static sal_Bool SAL_CALL getUserNameImpl(oslSecurity Security, rtl_uString **strName, sal_Bool bIncludeDomain);
+
+/*****************************************************************************/
+/* Exported Module Functions */
+/*****************************************************************************/
+
+oslSecurity SAL_CALL osl_getCurrentSecurity(void)
+{
+ oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl));
+
+ pSecImpl->m_pNetResource = NULL;
+ pSecImpl->m_User[0] = '\0';
+ pSecImpl->m_hToken = NULL;
+ pSecImpl->m_hProfile = NULL;
+
+ return ((oslSecurity)pSecImpl);
+}
+
+oslSecurityError SAL_CALL osl_loginUser( rtl_uString *strUserName, rtl_uString *strPasswd, oslSecurity *pSecurity )
+{
+ oslSecurityError ret;
+
+ if (!isWNT())
+ {
+ *pSecurity = osl_getCurrentSecurity();
+ ret = osl_Security_E_None;
+ }
+ else
+ {
+ sal_Unicode* strUser;
+ sal_Unicode* strDomain = _wcsdup(rtl_uString_getStr(strUserName));
+ HANDLE hUserToken;
+
+ #if OSL_DEBUG_LEVEL > 0
+ LUID luid;
+ #endif
+
+ if (NULL != (strUser = wcschr(strDomain, L'/')))
+ *strUser++ = L'\0';
+ else
+ {
+ strUser = strDomain;
+ strDomain = NULL;
+ }
+
+ // this process must have the right: 'act as a part of operatingsystem'
+ OSL_ASSERT(LookupPrivilegeValue(NULL, SE_TCB_NAME, &luid));
+
+ if (LogonUserW(strUser, strDomain ? strDomain : L"", rtl_uString_getStr(strPasswd),
+ LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
+ &hUserToken))
+ {
+ oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl));
+
+ pSecImpl->m_pNetResource = NULL;
+ pSecImpl->m_hToken = hUserToken;
+ pSecImpl->m_hProfile = NULL;
+ wcscpy(pSecImpl->m_User, strUser);
+
+ *pSecurity = (oslSecurity)pSecImpl;
+ ret = osl_Security_E_None;
+ }
+ else
+ ret = osl_Security_E_UserUnknown;
+
+ if (strDomain)
+ free(strDomain);
+ else
+ free(strUser);
+ }
+
+ return ret;
+}
+
+oslSecurityError SAL_CALL osl_loginUserOnFileServer(rtl_uString *strUserName,
+ rtl_uString *strPasswd,
+ rtl_uString *strFileServer,
+ oslSecurity *pSecurity)
+{
+ oslSecurityError ret;
+ DWORD err;
+ NETRESOURCEW netResource;
+ sal_Unicode* remoteName;
+ sal_Unicode* userName;
+
+ remoteName = malloc(rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 4);
+ userName = malloc(rtl_uString_getLength(strFileServer) + rtl_uString_getLength(strUserName) + 2);
+
+ wcscpy(remoteName, L"\\\\");
+ wcscat(remoteName, rtl_uString_getStr(strFileServer));
+ wcscat(remoteName, L"\\");
+ wcscat(remoteName, rtl_uString_getStr(strUserName));
+
+ wcscpy(userName, rtl_uString_getStr(strFileServer));
+ wcscat(userName, L"\\");
+ wcscat(userName, rtl_uString_getStr(strUserName));
+
+ netResource.dwScope = RESOURCE_GLOBALNET;
+ netResource.dwType = RESOURCETYPE_DISK;
+ netResource.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
+ netResource.dwUsage = RESOURCEUSAGE_CONNECTABLE;
+ netResource.lpLocalName = NULL;
+ netResource.lpRemoteName = remoteName;
+ netResource.lpComment = NULL;
+ netResource.lpProvider = NULL;
+
+ err = WNetAddConnection2W(&netResource, rtl_uString_getStr(strPasswd), userName, 0);
+
+ if ((err == NO_ERROR) || (err == ERROR_ALREADY_ASSIGNED))
+ {
+ oslSecurityImpl* pSecImpl = malloc(sizeof(oslSecurityImpl));
+
+ pSecImpl->m_pNetResource = malloc(sizeof(NETRESOURCE));
+ *pSecImpl->m_pNetResource = netResource;
+
+ pSecImpl->m_hToken = NULL;
+ pSecImpl->m_hProfile = NULL;
+ wcscpy(pSecImpl->m_User, rtl_uString_getStr(strUserName));
+
+ *pSecurity = (oslSecurity)pSecImpl;
+
+ ret = osl_Security_E_None;
+ }
+ else
+ ret = osl_Security_E_UserUnknown;
+
+ free(remoteName);
+ free(userName);
+
+ return ret;
+}
+
+
+static BOOL WINAPI CheckTokenMembership_Stub( HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember )
+{
+ typedef BOOL (WINAPI *CheckTokenMembership_PROC)( HANDLE, PSID, PBOOL );
+
+ static HMODULE hModule = NULL;
+ static CheckTokenMembership_PROC pCheckTokenMembership = NULL;
+
+ if ( !hModule )
+ {
+ /* SAL is always linked against ADVAPI32 so we can rely on that it is already mapped */
+
+ hModule = GetModuleHandleA( "ADVAPI32.DLL" );
+
+ pCheckTokenMembership = (CheckTokenMembership_PROC)GetProcAddress( hModule, "CheckTokenMembership" );
+ }
+
+ if ( pCheckTokenMembership )
+ return pCheckTokenMembership( TokenHandle, SidToCheck, IsMember );
+ else
+ {
+ SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+ return FALSE;
+ }
+
+}
+
+
+sal_Bool SAL_CALL osl_isAdministrator(oslSecurity Security)
+{
+ if (Security != NULL)
+ {
+ /* ts: on Window 95 systems any user seems to be an adminstrator */
+ if (!isWNT())
+ {
+ return(sal_True);
+ }
+ else
+ {
+ HANDLE hImpersonationToken = NULL;
+ PSID psidAdministrators;
+ SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
+ sal_Bool bSuccess = sal_False;
+
+
+ /* If Security contains an access token we need to duplicate it to an impersonation
+ access token. NULL works with CheckTokenMembership() as the current effective
+ impersonation token
+ */
+
+ if ( ((oslSecurityImpl*)Security)->m_hToken )
+ {
+ if ( !DuplicateToken (((oslSecurityImpl*)Security)->m_hToken, SecurityImpersonation, &hImpersonationToken) )
+ return sal_False;
+ }
+
+ /* CheckTokenMembership() can be used on W2K and higher (NT4 no longer supported by OOo)
+ and also works on Vista to retrieve the effective user rights. Just checking for
+ membership of Administrators group is not enough on Vista this would require additional
+ complicated checks as described in KB arcticle Q118626: http://support.microsoft.com/kb/118626/en-us
+ */
+
+ if (AllocateAndInitializeSid(&siaNtAuthority,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &psidAdministrators))
+ {
+ BOOL fSuccess = FALSE;
+
+ if ( CheckTokenMembership_Stub( hImpersonationToken, psidAdministrators, &fSuccess ) && fSuccess )
+ bSuccess = sal_True;
+
+ FreeSid(psidAdministrators);
+ }
+
+ if ( hImpersonationToken )
+ CloseHandle( hImpersonationToken );
+
+ return (bSuccess);
+ }
+ }
+ else
+ return (sal_False);
+}
+
+
+void SAL_CALL osl_freeSecurityHandle(oslSecurity Security)
+{
+ if (Security)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ if (pSecImpl->m_pNetResource != NULL)
+ {
+ WNetCancelConnection2W(pSecImpl->m_pNetResource->lpRemoteName, 0, sal_True);
+
+ free(pSecImpl->m_pNetResource->lpRemoteName);
+ free(pSecImpl->m_pNetResource);
+ }
+
+ if (pSecImpl->m_hToken)
+ CloseHandle(pSecImpl->m_hToken);
+
+ if ( pSecImpl->m_hProfile )
+ CloseHandle(pSecImpl->m_hProfile);
+
+ free (pSecImpl);
+ }
+}
+
+
+sal_Bool SAL_CALL osl_getUserIdent(oslSecurity Security, rtl_uString **strIdent)
+{
+ if (Security != NULL)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ HANDLE hAccessToken = pSecImpl->m_hToken;
+
+ if (hAccessToken == NULL)
+ OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
+
+ if (hAccessToken)
+ {
+ sal_Char *Ident;
+ DWORD nInfoBuffer = 512;
+ UCHAR* pInfoBuffer = malloc(nInfoBuffer);
+
+
+ while (!GetTokenInformation(hAccessToken, TokenUser,
+ pInfoBuffer, nInfoBuffer, &nInfoBuffer))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer);
+ else
+ {
+ free(pInfoBuffer);
+ pInfoBuffer = NULL;
+ break;
+ }
+ }
+
+ if (pSecImpl->m_hToken == NULL)
+ CloseHandle(hAccessToken);
+
+ if (pInfoBuffer)
+ {
+ PSID pSid = ((PTOKEN_USER)pInfoBuffer)->User.Sid;
+ PSID_IDENTIFIER_AUTHORITY psia;
+ DWORD dwSubAuthorities;
+ DWORD dwSidRev=SID_REVISION;
+ DWORD dwCounter;
+ DWORD dwSidSize;
+
+ /* obtain SidIdentifierAuthority */
+ psia=GetSidIdentifierAuthority(pSid);
+
+ /* obtain sidsubauthority count */
+ dwSubAuthorities=min(*GetSidSubAuthorityCount(pSid), 5);
+
+ /* buffer length: S-SID_REVISION- + identifierauthority- + subauthorities- + NULL */
+ Ident=malloc(88*sizeof(sal_Char));
+
+ /* prepare S-SID_REVISION- */
+ dwSidSize=wsprintf(Ident, TEXT("S-%lu-"), dwSidRev);
+
+ /* prepare SidIdentifierAuthority */
+ if ((psia->Value[0] != 0) || (psia->Value[1] != 0))
+ {
+ dwSidSize+=wsprintf(Ident + strlen(Ident),
+ TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
+ (USHORT)psia->Value[0],
+ (USHORT)psia->Value[1],
+ (USHORT)psia->Value[2],
+ (USHORT)psia->Value[3],
+ (USHORT)psia->Value[4],
+ (USHORT)psia->Value[5]);
+ }
+ else
+ {
+ dwSidSize+=wsprintf(Ident + strlen(Ident),
+ TEXT("%lu"),
+ (ULONG)(psia->Value[5] ) +
+ (ULONG)(psia->Value[4] << 8) +
+ (ULONG)(psia->Value[3] << 16) +
+ (ULONG)(psia->Value[2] << 24) );
+ }
+
+ /* loop through SidSubAuthorities */
+ for (dwCounter=0; dwCounter < dwSubAuthorities; dwCounter++)
+ {
+ dwSidSize+=wsprintf(Ident + dwSidSize, TEXT("-%lu"),
+ *GetSidSubAuthority(pSid, dwCounter) );
+ }
+
+ rtl_uString_newFromAscii( strIdent, Ident );
+
+ free(pInfoBuffer);
+ free(Ident);
+
+ return (sal_True);
+ }
+ }
+ else
+ {
+ DWORD needed=0;
+ sal_Unicode *Ident;
+
+ WNetGetUserA(NULL, NULL, &needed);
+ needed = max( 16 , needed );
+ Ident=malloc(needed*sizeof(sal_Unicode));
+
+ if (WNetGetUserW(NULL, Ident, &needed) != NO_ERROR)
+ {
+ wcscpy(Ident, L"unknown");
+ Ident[7] = L'\0';
+ }
+
+ rtl_uString_newFromStr( strIdent, Ident);
+
+ free(Ident);
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+
+
+sal_Bool SAL_CALL osl_getUserName(oslSecurity Security, rtl_uString **strName)
+{
+ return getUserNameImpl(Security, strName, sal_True);
+}
+
+
+sal_Bool SAL_CALL osl_getHomeDir(oslSecurity Security, rtl_uString **pustrDirectory)
+{
+ rtl_uString *ustrSysDir = NULL;
+ sal_Bool bSuccess = sal_False;
+
+ if (Security != NULL)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ if (pSecImpl->m_pNetResource != NULL)
+ {
+ rtl_uString_newFromStr( &ustrSysDir, pSecImpl->m_pNetResource->lpRemoteName);
+
+ bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory ));
+ }
+ else
+ {
+#if 0
+ if (pSecImpl->m_hToken)
+ {
+ DWORD nInfoBuffer = 512;
+ UCHAR* pInfoBuffer = malloc(nInfoBuffer);
+
+ while (!GetTokenInformation(pSecImpl->m_hToken, TokenUser,
+ pInfoBuffer, nInfoBuffer, &nInfoBuffer))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer);
+ else
+ {
+ free(pInfoBuffer);
+ pInfoBuffer = NULL;
+ break;
+ }
+ }
+
+ /* not implemented */
+ OSL_ASSERT(sal_False);
+
+ if (pInfoBuffer)
+ {
+ /* if (EqualSid() ... */
+
+ }
+ }
+ else
+#endif
+
+ bSuccess = (sal_Bool)(GetSpecialFolder(&ustrSysDir, CSIDL_PERSONAL) &&
+ (osl_File_E_None == osl_getFileURLFromSystemPath(ustrSysDir, pustrDirectory)));
+ }
+ }
+
+ if ( ustrSysDir )
+ rtl_uString_release( ustrSysDir );
+
+ return bSuccess;
+}
+
+sal_Bool SAL_CALL osl_getConfigDir(oslSecurity Security, rtl_uString **pustrDirectory)
+{
+ sal_Bool bSuccess = sal_False;
+
+ if (Security != NULL)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ if (pSecImpl->m_pNetResource != NULL)
+ {
+ rtl_uString *ustrSysDir = NULL;
+
+ rtl_uString_newFromStr( &ustrSysDir, pSecImpl->m_pNetResource->lpRemoteName);
+ bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath( ustrSysDir, pustrDirectory));
+
+ if ( ustrSysDir )
+ rtl_uString_release( ustrSysDir );
+ }
+ else
+ {
+ if (pSecImpl->m_hToken)
+ {
+ /* not implemented */
+ OSL_ASSERT(sal_False);
+ }
+ else
+ {
+ rtl_uString *ustrFile = NULL;
+ sal_Unicode sFile[_MAX_PATH];
+
+ if ( !GetSpecialFolder( &ustrFile, CSIDL_APPDATA) )
+ {
+ OSL_VERIFY(GetWindowsDirectoryW(sFile, _MAX_DIR) > 0);
+
+ rtl_uString_newFromStr( &ustrFile, sFile);
+ }
+
+ bSuccess = (sal_Bool)(osl_File_E_None == osl_getFileURLFromSystemPath(ustrFile, pustrDirectory));
+
+ if ( ustrFile )
+ rtl_uString_release( ustrFile );
+ }
+ }
+ }
+
+ return bSuccess;
+}
+
+
+sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security)
+{
+ /* CreateProcessAsUser does not load the specified user's profile
+ into the HKEY_USERS registry key. This means that access to information
+ in the HKEY_CURRENT_USER registry key may not produce results consistent
+ with a normal interactive logon.
+ It is your responsibility to load the user's registry hive into HKEY_USERS
+ with the LoadUserProfile function before calling CreateProcessAsUser.
+ */
+ BOOL bOk = FALSE;
+
+ RegCloseKey(HKEY_CURRENT_USER);
+
+ if (Privilege(SE_RESTORE_NAME, TRUE))
+ {
+ HMODULE hUserEnvLib = NULL;
+ LPFNLOADUSERPROFILE fLoadUserProfile = NULL;
+ LPFNUNLOADUSERPROFILE fUnloadUserProfile = NULL;
+ HANDLE hAccessToken = ((oslSecurityImpl*)Security)->m_hToken;
+ DWORD nError = 0;
+
+ /* try to create user profile */
+ if ( !hAccessToken )
+ {
+ /* retrieve security handle if not done before e.g. osl_getCurrentSecurity()
+ */
+ HANDLE hProcess = GetCurrentProcess();
+
+ if (hProcess != NULL)
+ {
+ OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
+ CloseHandle(hProcess);
+ }
+ }
+
+ hUserEnvLib = LoadLibraryA("userenv.dll");
+
+ if (hUserEnvLib)
+ {
+ fLoadUserProfile = (LPFNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "LoadUserProfileW");
+ fUnloadUserProfile = (LPFNUNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "UnloadUserProfile");
+
+ if (fLoadUserProfile && fUnloadUserProfile)
+ {
+ rtl_uString *buffer = 0;
+ PROFILEINFOW pi;
+
+ getUserNameImpl(Security, &buffer, sal_False);
+
+ ZeroMemory( &pi, sizeof(pi) );
+ pi.dwSize = sizeof(pi);
+ pi.lpUserName = rtl_uString_getStr(buffer);
+ pi.dwFlags = PI_NOUI;
+
+ if (fLoadUserProfile(hAccessToken, &pi))
+ {
+ fUnloadUserProfile(hAccessToken, pi.hProfile);
+
+ bOk = TRUE;
+ }
+ else
+ nError = GetLastError();
+
+ rtl_uString_release(buffer);
+ }
+
+ FreeLibrary(hUserEnvLib);
+ }
+
+ if (hAccessToken && (hAccessToken != ((oslSecurityImpl*)Security)->m_hToken))
+ CloseHandle(hAccessToken);
+ }
+
+ return (sal_Bool)bOk;
+}
+
+
+void SAL_CALL osl_unloadUserProfile(oslSecurity Security)
+{
+ if ( ((oslSecurityImpl*)Security)->m_hProfile != NULL )
+ {
+ HMODULE hUserEnvLib = NULL;
+ LPFNLOADUSERPROFILE fLoadUserProfile = NULL;
+ LPFNUNLOADUSERPROFILE fUnloadUserProfile = NULL;
+ BOOL bOk = FALSE;
+ HANDLE hAccessToken = ((oslSecurityImpl*)Security)->m_hToken;
+
+ if ( !hAccessToken )
+ {
+ /* retrieve security handle if not done before e.g. osl_getCurrentSecurity()
+ */
+ HANDLE hProcess = GetCurrentProcess();
+
+ if (hProcess != NULL)
+ {
+ OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken);
+ CloseHandle(hProcess);
+ }
+ }
+
+ hUserEnvLib = LoadLibrary("userenv.dll");
+
+ if (hUserEnvLib)
+ {
+ fLoadUserProfile = (LPFNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "LoadUserProfileA");
+ fUnloadUserProfile = (LPFNUNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "UnloadUserProfile");
+
+ if (fLoadUserProfile && fUnloadUserProfile)
+ {
+ /* unloading the user profile */
+ if (fLoadUserProfile && fUnloadUserProfile)
+ bOk = fUnloadUserProfile(hAccessToken, ((oslSecurityImpl*)Security)->m_hProfile);
+
+ if (hUserEnvLib)
+ FreeLibrary(hUserEnvLib);
+ }
+ }
+
+ ((oslSecurityImpl*)Security)->m_hProfile;
+
+ if (hAccessToken && (hAccessToken != ((oslSecurityImpl*)Security)->m_hToken))
+ {
+ CloseHandle(hAccessToken);
+ }
+ }
+}
+
+/*****************************************************************************/
+/* Static Module Functions */
+/*****************************************************************************/
+
+
+static sal_Bool GetSpecialFolder(rtl_uString **strPath, int nFolder)
+{
+ sal_Bool bRet = sal_False;
+ HINSTANCE hLibrary;
+ sal_Char PathA[_MAX_PATH];
+ sal_Unicode PathW[_MAX_PATH];
+
+ if ((hLibrary = LoadLibrary("shell32.dll")) != NULL)
+ {
+ BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL);
+ BOOL (WINAPI *pSHGetSpecialFolderPathW)(HWND, LPWSTR, int, BOOL);
+
+ pSHGetSpecialFolderPathA = (BOOL (WINAPI *)(HWND, LPSTR, int, BOOL))GetProcAddress(hLibrary, "SHGetSpecialFolderPathA");
+ pSHGetSpecialFolderPathW = (BOOL (WINAPI *)(HWND, LPWSTR, int, BOOL))GetProcAddress(hLibrary, "SHGetSpecialFolderPathW");
+
+ if (pSHGetSpecialFolderPathA)
+ {
+ if (pSHGetSpecialFolderPathA(GetActiveWindow(), PathA, nFolder, TRUE))
+ {
+ rtl_string2UString( strPath, PathA, strlen(PathA), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(*strPath != NULL);
+ bRet = sal_True;
+ }
+ }
+ else if (pSHGetSpecialFolderPathW)
+ {
+ if (pSHGetSpecialFolderPathW(GetActiveWindow(), PathW, nFolder, TRUE))
+ {
+ rtl_uString_newFromStr( strPath, PathW);
+ bRet = sal_True;
+ }
+ }
+ else
+ {
+ HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *) = (HRESULT (WINAPI *)(HWND, int, LPITEMIDLIST *))GetProcAddress(hLibrary, "SHGetSpecialFolderLocation");
+ BOOL (WINAPI *pSHGetPathFromIDListA)(LPCITEMIDLIST, LPSTR) = (BOOL (WINAPI *)(LPCITEMIDLIST, LPSTR))GetProcAddress(hLibrary, "SHGetPathFromIDListA");
+ BOOL (WINAPI *pSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR) = (BOOL (WINAPI *)(LPCITEMIDLIST, LPWSTR))GetProcAddress(hLibrary, "SHGetPathFromIDListW");
+ HRESULT (WINAPI *pSHGetMalloc)(LPMALLOC *) = (HRESULT (WINAPI *)(LPMALLOC *))GetProcAddress(hLibrary, "SHGetMalloc");
+
+
+ if (pSHGetSpecialFolderLocation && (pSHGetPathFromIDListA || pSHGetPathFromIDListW ) && pSHGetMalloc )
+ {
+ LPITEMIDLIST pidl;
+ LPMALLOC pMalloc;
+ HRESULT hr;
+
+ hr = pSHGetSpecialFolderLocation(GetActiveWindow(), nFolder, &pidl);
+
+ /* Get SHGetSpecialFolderLocation fails if directory does not exists. */
+ /* If it fails we try to create the directory and redo the call */
+ if (! SUCCEEDED(hr))
+ {
+ HKEY hRegKey;
+
+ if (RegOpenKey(HKEY_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
+ &hRegKey) == ERROR_SUCCESS)
+ {
+ LONG lRet;
+ DWORD lSize = elementsof(PathA);
+ DWORD Type = REG_SZ;
+
+ switch (nFolder)
+ {
+ case CSIDL_APPDATA:
+ lRet = RegQueryValueEx(hRegKey, "AppData", NULL, &Type, (LPBYTE)PathA, &lSize);
+ break;
+
+ case CSIDL_PERSONAL:
+ lRet = RegQueryValueEx(hRegKey, "Personal", NULL, &Type, (LPBYTE)PathA, &lSize);
+ break;
+
+ default:
+ lRet = -1l;
+ }
+
+ if ((lRet == ERROR_SUCCESS) && (Type == REG_SZ))
+ {
+ if (_access(PathA, 0) < 0)
+ CreateDirectory(PathA, NULL);
+
+ hr = pSHGetSpecialFolderLocation(GetActiveWindow(), nFolder, &pidl);
+ }
+
+ RegCloseKey(hRegKey);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (pSHGetPathFromIDListW && pSHGetPathFromIDListW(pidl, PathW))
+ {
+ /* if directory does not exist, create it */
+ if (_waccess(PathW, 0) < 0)
+ CreateDirectoryW(PathW, NULL);
+
+ rtl_uString_newFromStr( strPath, PathW);
+ bRet = sal_True;
+ }
+ else if (pSHGetPathFromIDListA && pSHGetPathFromIDListA(pidl, PathA))
+ {
+ /* if directory does not exist, create it */
+ if (_access(PathA, 0) < 0)
+ CreateDirectoryA(PathA, NULL);
+
+ rtl_string2UString( strPath, PathA, strlen(PathA), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(*strPath != NULL);
+ bRet = sal_True;
+ }
+ }
+
+ if (SUCCEEDED(pSHGetMalloc(&pMalloc)))
+ {
+ pMalloc->lpVtbl->Free(pMalloc, pidl);
+ pMalloc->lpVtbl->Release(pMalloc);
+ }
+ }
+ }
+ }
+
+ FreeLibrary(hLibrary);
+
+ return (bRet);
+}
+
+
+static sal_Bool isWNT(void)
+{
+ static sal_Bool isInit = sal_False;
+ static sal_Bool isWNT = sal_False;
+
+ if (!isInit)
+ {
+ OSVERSIONINFO VersionInformation =
+
+ {
+ sizeof(OSVERSIONINFO),
+ 0,
+ 0,
+ 0,
+ 0,
+ "",
+ };
+
+ if (
+ GetVersionEx(&VersionInformation) &&
+ (VersionInformation.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ )
+ {
+ isWNT = sal_True;
+ }
+
+ isInit = sal_True;
+ }
+
+ return(isWNT);
+}
+
+static BOOL Privilege(LPTSTR strPrivilege, BOOL bEnable)
+{
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tp;
+
+ /*
+ obtain the processes token
+ */
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_DUP_QUERY, &hToken))
+ return FALSE;
+
+ /*
+ get the luid
+ */
+ if (!LookupPrivilegeValue(NULL, strPrivilege, &tp.Privileges[0].Luid))
+ return FALSE;
+
+ tp.PrivilegeCount = 1;
+
+ if (bEnable)
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ else
+ tp.Privileges[0].Attributes = 0;
+
+ /*
+ enable or disable the privilege
+ */
+ if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
+ return FALSE;
+
+ if (!CloseHandle(hToken))
+ return FALSE;
+
+ return TRUE;
+}
+
+static sal_Bool SAL_CALL getUserNameImpl(oslSecurity Security, rtl_uString **strName, sal_Bool bIncludeDomain)
+{
+ if (Security != NULL)
+ {
+ oslSecurityImpl *pSecImpl = (oslSecurityImpl*)Security;
+
+ HANDLE hAccessToken = pSecImpl->m_hToken;
+
+ if (hAccessToken == NULL)
+ OpenProcessToken(GetCurrentProcess(), TOKEN_DUP_QUERY, &hAccessToken);
+
+ if (hAccessToken)
+ {
+ DWORD nInfoBuffer = 512;
+ UCHAR* pInfoBuffer = malloc(nInfoBuffer);
+
+ while (!GetTokenInformation(hAccessToken, TokenUser,
+ pInfoBuffer, nInfoBuffer, &nInfoBuffer))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ pInfoBuffer = realloc(pInfoBuffer, nInfoBuffer);
+ else
+ {
+ free(pInfoBuffer);
+ pInfoBuffer = NULL;
+ break;
+ }
+ }
+
+ if (pSecImpl->m_hToken == NULL)
+ CloseHandle(hAccessToken);
+
+ if (pInfoBuffer)
+ {
+ sal_Unicode UserName[128];
+ sal_Unicode DomainName[128];
+ sal_Unicode Name[257];
+ DWORD nUserName = sizeof(UserName);
+ DWORD nDomainName = sizeof(DomainName);
+ SID_NAME_USE sUse;
+
+ if (LookupAccountSidW(NULL, ((PTOKEN_USER)pInfoBuffer)->User.Sid,
+ UserName, &nUserName,
+ DomainName, &nDomainName, &sUse))
+ {
+ if (bIncludeDomain)
+ {
+ wcscpy(Name, DomainName);
+ wcscat(Name, L"/");
+ wcscat(Name, UserName);
+ }
+ else
+ {
+ wcscpy(Name, UserName);
+ }
+ }
+ rtl_uString_newFromStr( strName, Name);
+
+ free(pInfoBuffer);
+
+ return (sal_True);
+ }
+ }
+ else
+ {
+ DWORD needed=0;
+ sal_Unicode *pNameW=NULL;
+
+ WNetGetUserW(NULL, NULL, &needed);
+ pNameW = malloc (needed*sizeof(sal_Unicode));
+
+ if (WNetGetUserW(NULL, pNameW, &needed) == NO_ERROR)
+ {
+ rtl_uString_newFromStr( strName, pNameW);
+
+ if (pNameW)
+ free(pNameW);
+ return (sal_True);
+ }
+ else
+ if (wcslen(pSecImpl->m_User) > 0)
+ {
+ rtl_uString_newFromStr( strName, pSecImpl->m_pNetResource->lpRemoteName);
+
+ if (pNameW)
+ free(pNameW);
+
+ return (sal_True);
+ }
+
+ if (pNameW)
+ free(pNameW);
+ }
+ }
+
+ return sal_False;
+}
+
diff --git a/sal/osl/w32/semaphor.c b/sal/osl/w32/semaphor.c
new file mode 100644
index 000000000000..e16a73d998fa
--- /dev/null
+++ b/sal/osl/w32/semaphor.c
@@ -0,0 +1,111 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/semaphor.h>
+
+/*
+ Implemetation notes:
+ The void* represented by oslSemaphore is used
+ to store a WIN32 HANDLE.
+*/
+
+
+/*****************************************************************************/
+/* osl_createSemaphore */
+/*****************************************************************************/
+oslSemaphore SAL_CALL osl_createSemaphore(sal_uInt32 initialCount)
+{
+ oslSemaphore Semaphore;
+
+ Semaphore= CreateSemaphore(0, initialCount, INT_MAX, 0);
+
+ /* create failed? */
+ if((HANDLE)Semaphore == INVALID_HANDLE_VALUE)
+ {
+ Semaphore= 0;
+ }
+
+ return Semaphore;
+}
+
+/*****************************************************************************/
+/* osl_destroySemaphore */
+/*****************************************************************************/
+void SAL_CALL osl_destroySemaphore(oslSemaphore Semaphore)
+{
+
+
+ if(Semaphore != 0)
+ {
+ CloseHandle((HANDLE)Semaphore);
+ }
+
+}
+
+/*****************************************************************************/
+/* osl_acquireSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_acquireSemaphore(oslSemaphore Semaphore)
+{
+ OSL_ASSERT(Semaphore != 0);
+
+ switch ( WaitForSingleObject( (HANDLE)Semaphore, INFINITE ) )
+ {
+ case WAIT_OBJECT_0:
+ return sal_True;
+
+ default:
+ return (sal_False);
+ }
+}
+
+/*****************************************************************************/
+/* osl_tryToAcquireSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_tryToAcquireSemaphore(oslSemaphore Semaphore)
+{
+ OSL_ASSERT(Semaphore != 0);
+ return (sal_Bool)(WaitForSingleObject((HANDLE)Semaphore, 0) == WAIT_OBJECT_0);
+}
+
+
+/*****************************************************************************/
+/* osl_releaseSemaphore */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_releaseSemaphore(oslSemaphore Semaphore)
+{
+ OSL_ASSERT(Semaphore != 0);
+
+ /* increase count by one, not interested in previous count */
+ return (sal_Bool)(ReleaseSemaphore((HANDLE)Semaphore, 1, NULL) != FALSE);
+}
+
+
+
diff --git a/sal/osl/w32/signal.cxx b/sal/osl/w32/signal.cxx
new file mode 100644
index 000000000000..f893f7520d40
--- /dev/null
+++ b/sal/osl/w32/signal.cxx
@@ -0,0 +1,436 @@
+/*************************************************************************
+*
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+*
+************************************************************************/
+
+/* system headers */
+#include "system.h"
+#include <tchar.h>
+
+#include "file_url.h"
+#include "path_helper.hxx"
+
+#include <osl/diagnose.h>
+#include <osl/mutex.h>
+#include <osl/signal.h>
+#ifndef __MINGW32__
+#include <DbgHelp.h>
+#endif
+#include <ErrorRep.h>
+#include <systools/win32/uwinapi.h>
+
+typedef struct _oslSignalHandlerImpl
+{
+ oslSignalHandlerFunction Handler;
+ void* pData;
+ struct _oslSignalHandlerImpl* pNext;
+} oslSignalHandlerImpl;
+
+static sal_Bool bErrorReportingEnabled = sal_True;
+static sal_Bool bInitSignal = sal_False;
+static oslMutex SignalListMutex;
+static oslSignalHandlerImpl* SignalList;
+
+static long WINAPI SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP);
+
+static sal_Bool InitSignal(void)
+{
+ HMODULE hFaultRep;
+
+ SignalListMutex = osl_createMutex();
+
+ SetUnhandledExceptionFilter(SignalHandlerFunction);
+
+ hFaultRep = LoadLibrary( "faultrep.dll" );
+ if ( hFaultRep )
+ {
+#ifdef __MINGW32__
+typedef BOOL (WINAPI *pfn_ADDEREXCLUDEDAPPLICATIONW)(LPCWSTR);
+#endif
+ pfn_ADDEREXCLUDEDAPPLICATIONW pfn = (pfn_ADDEREXCLUDEDAPPLICATIONW)GetProcAddress( hFaultRep, "AddERExcludedApplicationW" );
+ if ( pfn )
+ pfn( L"SOFFICE.EXE" );
+ FreeLibrary( hFaultRep );
+ }
+
+ return sal_True;
+}
+
+static sal_Bool DeInitSignal(void)
+{
+ SetUnhandledExceptionFilter(NULL);
+
+ osl_destroyMutex(SignalListMutex);
+
+ return sal_False;
+}
+
+static oslSignalAction CallSignalHandler(oslSignalInfo *pInfo)
+{
+ oslSignalHandlerImpl* pHandler = SignalList;
+ oslSignalAction Action = osl_Signal_ActCallNextHdl;
+
+ while (pHandler != NULL)
+ {
+ if ((Action = pHandler->Handler(pHandler->pData, pInfo)) != osl_Signal_ActCallNextHdl)
+ break;
+
+ pHandler = pHandler->pNext;
+ }
+
+ return Action;
+}
+
+/*****************************************************************************/
+/* SignalHandlerFunction */
+/*****************************************************************************/
+
+#define REPORTENV_PARAM "-crashreportenv:"
+#define REPORTENV_PARAM2 "/crashreportenv:"
+
+static BOOL ReportCrash( LPEXCEPTION_POINTERS lpEP )
+{
+ BOOL fSuccess = FALSE;
+ BOOL fAutoReport = FALSE;
+ TCHAR szBuffer[1024];
+ ::osl::LongPathBuffer< sal_Char > aPath( MAX_LONG_PATH );
+ LPTSTR lpFilePart;
+ PROCESS_INFORMATION ProcessInfo;
+ STARTUPINFO StartupInfo;
+ int argi;
+
+ if ( !bErrorReportingEnabled )
+ return FALSE;
+
+ /* Check if crash reporter was disabled by command line */
+
+ for ( argi = 1; argi < __argc; argi++ )
+ {
+ if (
+ 0 == stricmp( __argv[argi], "-nocrashreport" ) ||
+ 0 == stricmp( __argv[argi], "/nocrashreport" )
+ )
+ return FALSE;
+ else if (
+ 0 == stricmp( __argv[argi], "-autocrashreport" ) ||
+ 0 == stricmp( __argv[argi], "/autocrashreport" )
+ )
+ fAutoReport = TRUE;
+ else if (
+ 0 == strnicmp( __argv[argi], REPORTENV_PARAM, strlen(REPORTENV_PARAM) ) ||
+ 0 == strnicmp( __argv[argi], REPORTENV_PARAM2, strlen(REPORTENV_PARAM2) )
+ )
+ {
+ const char *envparam = __argv[argi] + strlen(REPORTENV_PARAM);
+ const char *delim = strchr(envparam, '=' );
+
+ if ( delim )
+ {
+ CHAR *lpVariable;
+ CHAR *lpValue;
+ const char *variable = envparam;
+ size_t variable_len = delim - envparam;
+ const char *value = delim + 1;
+ size_t value_len = strlen(envparam) - variable_len - 1;
+
+ if ( '\"' == *value )
+ {
+ const char *quote;
+
+ value++;
+ value_len--;
+
+ quote = strchr( value, '\"' );
+ if ( quote )
+ value_len = quote - value;
+ }
+
+ lpVariable = reinterpret_cast< CHAR* >( _alloca( variable_len + 1 ) );
+ memcpy( lpVariable, variable, variable_len );
+ lpVariable[variable_len] = 0;
+
+ lpValue = reinterpret_cast< CHAR* >( _alloca( value_len + 1) );
+ memcpy( lpValue, value, value_len );
+ lpValue[value_len] = 0;
+
+ SetEnvironmentVariable( lpVariable, lpValue );
+ }
+ }
+ }
+
+ if ( SearchPath( NULL, TEXT( "crashrep.exe" ), NULL, aPath.getBufSizeInSymbols(), aPath, &lpFilePart ) )
+ {
+ ZeroMemory( &StartupInfo, sizeof(StartupInfo) );
+ StartupInfo.cb = sizeof(StartupInfo.cb);
+
+
+ sntprintf( szBuffer, elementsof(szBuffer),
+ _T("%s -p %u -excp 0x%p -t %u%s"),
+ aPath,
+ GetCurrentProcessId(),
+ lpEP,
+ GetCurrentThreadId(),
+ fAutoReport ? _T(" -noui -send") : _T(" -noui") );
+
+ if (
+ CreateProcess(
+ NULL,
+ szBuffer,
+ NULL,
+ NULL,
+ FALSE,
+#ifdef UNICODE
+ CREATE_UNICODE_ENVIRONMENT,
+#else
+ 0,
+#endif
+ NULL, NULL, &StartupInfo, &ProcessInfo )
+ )
+ {
+ DWORD dwExitCode;
+
+ WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
+ if ( GetExitCodeProcess( ProcessInfo.hProcess, &dwExitCode ) && 0 == dwExitCode )
+
+ fSuccess = TRUE;
+
+ }
+ }
+
+ return fSuccess;
+}
+
+/*****************************************************************************/
+/* SignalHandlerFunction */
+/*****************************************************************************/
+
+static BOOL WINAPI IsWin95A(void)
+{
+ OSVERSIONINFO ovi;
+
+ ZeroMemory( &ovi, sizeof(ovi) );
+ ovi.dwOSVersionInfoSize = sizeof(ovi);
+
+ if ( GetVersionEx( &ovi ) )
+ /* See MSDN January 2000 documentation of GetVersionEx */
+ return (ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
+ (ovi.dwMajorVersion <= 4) &&
+ (ovi.dwMinorVersion == 0) &&
+ (ovi.dwBuildNumber == 0x040003B6);
+
+ /* Something wrent wrong. So assume we have an older operating prior Win95 */
+
+ return TRUE;
+}
+
+/* magic Microsoft C++ compiler exception constant */
+#define EXCEPTION_MSC_CPP_EXCEPTION 0xe06d7363
+
+static long WINAPI SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP)
+{
+ static sal_Bool bNested = sal_False;
+ sal_Bool bRaiseCrashReporter = sal_False;
+ oslSignalInfo Info;
+ oslSignalAction Action;
+
+ Info.UserSignal = lpEP->ExceptionRecord->ExceptionCode;
+ Info.UserData = NULL;
+
+ switch (lpEP->ExceptionRecord->ExceptionCode)
+ {
+ /* Transform unhandled exceptions into access violations.
+ Microsoft C++ compiler (add more for other compilers if necessary).
+ */
+ case EXCEPTION_MSC_CPP_EXCEPTION:
+ case EXCEPTION_ACCESS_VIOLATION:
+ Info.Signal = osl_Signal_AccessViolation;
+ bRaiseCrashReporter = sal_True;
+ break;
+
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ Info.Signal = osl_Signal_IntegerDivideByZero;
+ bRaiseCrashReporter = sal_True;
+ break;
+
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ Info.Signal = osl_Signal_FloatDivideByZero;
+ bRaiseCrashReporter = sal_True;
+ break;
+
+ case EXCEPTION_BREAKPOINT:
+ Info.Signal = osl_Signal_DebugBreak;
+ break;
+
+ default:
+ Info.Signal = osl_Signal_System;
+ bRaiseCrashReporter = sal_True;
+ break;
+ }
+
+ if ( !bNested )
+ {
+ bNested = sal_True;
+
+ if ( bRaiseCrashReporter && ReportCrash( lpEP ) || IsWin95A() )
+ {
+ CallSignalHandler(&Info);
+ Action = osl_Signal_ActKillApp;
+ }
+ else
+ Action = CallSignalHandler(&Info);
+ }
+ else
+ Action = osl_Signal_ActKillApp;
+
+
+ switch ( Action )
+ {
+ case osl_Signal_ActCallNextHdl:
+ return (EXCEPTION_CONTINUE_SEARCH);
+
+ case osl_Signal_ActAbortApp:
+ return (EXCEPTION_EXECUTE_HANDLER);
+
+ case osl_Signal_ActKillApp:
+ SetErrorMode(SEM_NOGPFAULTERRORBOX);
+ exit(255);
+ break;
+ default:
+ break;
+ }
+
+ return (EXCEPTION_CONTINUE_EXECUTION);
+}
+
+/*****************************************************************************/
+/* osl_addSignalHandler */
+/*****************************************************************************/
+oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData)
+{
+ oslSignalHandlerImpl* pHandler;
+
+ OSL_ASSERT(Handler != NULL);
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ pHandler = reinterpret_cast< oslSignalHandlerImpl* >( calloc( 1, sizeof(oslSignalHandlerImpl) ) );
+
+ if (pHandler != NULL)
+ {
+ pHandler->Handler = Handler;
+ pHandler->pData = pData;
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler->pNext = SignalList;
+ SignalList = pHandler;
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (pHandler);
+ }
+
+ return (NULL);
+}
+
+/*****************************************************************************/
+/* osl_removeSignalHandler */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler)
+{
+ oslSignalHandlerImpl *pHandler, *pPrevious = NULL;
+
+ OSL_ASSERT(Handler != NULL);
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ pHandler = SignalList;
+
+ while (pHandler != NULL)
+ {
+ if (pHandler == Handler)
+ {
+ if (pPrevious)
+ pPrevious->pNext = pHandler->pNext;
+ else
+ SignalList = pHandler->pNext;
+
+ osl_releaseMutex(SignalListMutex);
+
+ if (SignalList == NULL)
+ bInitSignal = DeInitSignal();
+
+ free(pHandler);
+
+ return (sal_True);
+ }
+
+ pPrevious = pHandler;
+ pHandler = pHandler->pNext;
+ }
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (sal_False);
+}
+
+/*****************************************************************************/
+/* osl_raiseSignal */
+/*****************************************************************************/
+oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData)
+{
+ oslSignalInfo Info;
+ oslSignalAction Action;
+
+ if (! bInitSignal)
+ bInitSignal = InitSignal();
+
+ osl_acquireMutex(SignalListMutex);
+
+ Info.Signal = osl_Signal_User;
+ Info.UserSignal = UserSignal;
+ Info.UserData = UserData;
+
+ Action = CallSignalHandler(&Info);
+
+ osl_releaseMutex(SignalListMutex);
+
+ return (Action);
+}
+
+/*****************************************************************************/
+/* osl_setErrorReporting */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable )
+{
+ sal_Bool bOld = bErrorReportingEnabled;
+ bErrorReportingEnabled = bEnable;
+
+ return bOld;
+}
diff --git a/sal/osl/w32/socket.cxx b/sal/osl/w32/socket.cxx
new file mode 100644
index 000000000000..191c31fb986a
--- /dev/null
+++ b/sal/osl/w32/socket.cxx
@@ -0,0 +1,2190 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sal.hxx"
+
+#include "system.h"
+
+#include <osl/socket.h>
+#include <osl/diagnose.h>
+#include <rtl/alloc.h>
+
+#include "sockimpl.h"
+
+extern "C" {
+
+/* defines for shutdown */
+#ifdef GCC
+# define SD_RECEIVE 0
+# define SD_SEND 1
+# define SD_BOTH 2
+#endif
+
+/*
+ oslSocketAddr is a pointer to a Berkeley struct sockaddr.
+ I refrained from using sockaddr_in because of possible further
+ extensions of this socket-interface (IP-NG?).
+ The intention was to hide all Berkeley data-structures from
+ direct access past the osl-interface.
+
+ The current implementation is internet (IP) centered. All
+ the constructor-functions (osl_create...) take parameters
+ that will probably make sense only in the IP-environment
+ (e.g. because of using the dotted-Addr-format).
+
+ If the interface will be extended to host other protocol-
+ families, I expect no externally visible changes in the
+ existing functions. You'll probably need only new
+ constructor-functions who take the different Addr
+ formats into consideration (maybe a long dotted Addr
+ or whatever).
+*/
+
+/*
+ _Note_ that I rely on the fact that oslSocketAddr and struct sockaddr
+ are the same! I don't like it very much but see no other easy way to
+ conceal the struct sockaddr from the eyes of the user.
+*/
+
+#define OSL_INVALID_SOCKET INVALID_SOCKET /* WIN32 */
+#define OSL_SOCKET_ERROR SOCKET_ERROR /* WIN32 */
+
+/*****************************************************************************/
+/* enum oslAddrFamily */
+/*****************************************************************************/
+
+/* map */
+static DWORD FamilyMap[]= {
+ AF_INET, /* osl_Socket_FamilyInet */
+ AF_IPX, /* osl_Socket_FamilyIpx */
+ 0 /* osl_Socket_FamilyInvalid */
+};
+
+/* reverse map */
+static oslAddrFamily osl_AddrFamilyFromNative(DWORD nativeType)
+{
+ oslAddrFamily i= (oslAddrFamily) 0;
+ while(i != osl_Socket_FamilyInvalid)
+ {
+ if(FamilyMap[i] == nativeType)
+ return i;
+ i = (oslAddrFamily) ( (int)i + 1);
+ }
+ return i;
+}
+
+/* macros */
+#define FAMILY_FROM_NATIVE(y) osl_AddrFamilyFromNative(y)
+#define FAMILY_TO_NATIVE(x) (short)FamilyMap[x]
+
+/*****************************************************************************/
+/* enum oslProtocol */
+/*****************************************************************************/
+
+/* map */
+static DWORD ProtocolMap[]= {
+ 0, /* osl_Socket_FamilyInet */
+ NSPROTO_IPX, /* osl_Socket_FamilyIpx */
+ NSPROTO_SPX, /* osl_Socket_ProtocolSpx */
+ NSPROTO_SPXII, /* osl_Socket_ProtocolSpx_ii */
+ 0 /* osl_Socket_ProtocolInvalid */
+};
+
+/* macros */
+#define PROTOCOL_FROM_NATIVE(y) osl_ProtocolFromNative(y)
+#define PROTOCOL_TO_NATIVE(x) ProtocolMap[x]
+
+/*****************************************************************************/
+/* enum oslSocketType */
+/*****************************************************************************/
+
+/* map */
+static DWORD TypeMap[]= {
+ SOCK_STREAM, /* osl_Socket_TypeStream */
+ SOCK_DGRAM, /* osl_Socket_TypeDgram */
+ SOCK_RAW, /* osl_Socket_TypeRaw */
+ SOCK_RDM, /* osl_Socket_TypeRdm */
+ SOCK_SEQPACKET, /* osl_Socket_TypeSeqPacket */
+ 0 /* osl_Socket_TypeInvalid */
+};
+
+/* reverse map */
+static oslSocketType osl_SocketTypeFromNative(DWORD nativeType)
+{
+ oslSocketType i= (oslSocketType)0;
+ while(i != osl_Socket_TypeInvalid)
+ {
+ if(TypeMap[i] == nativeType)
+ return i;
+ i = (oslSocketType)((int)i+1);
+ }
+ return i;
+}
+
+/* macros */
+#define TYPE_TO_NATIVE(x) TypeMap[x]
+#define TYPE_FROM_NATIVE(y) osl_SocketTypeFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketOption */
+/*****************************************************************************/
+
+/* map */
+static DWORD OptionMap[]= {
+ SO_DEBUG, /* osl_Socket_OptionDebug */
+ SO_ACCEPTCONN, /* osl_Socket_OptionAcceptConn */
+ SO_REUSEADDR, /* osl_Socket_OptionReuseAddr */
+ SO_KEEPALIVE, /* osl_Socket_OptionKeepAlive */
+ SO_DONTROUTE, /* osl_Socket_OptionDontRoute */
+ SO_BROADCAST, /* osl_Socket_OptionBroadcast */
+ SO_USELOOPBACK, /* osl_Socket_OptionUseLoopback */
+ SO_LINGER, /* osl_Socket_OptionLinger */
+ SO_OOBINLINE, /* osl_Socket_OptionOOBinLine */
+ SO_SNDBUF, /* osl_Socket_OptionSndBuf */
+ SO_RCVBUF, /* osl_Socket_OptionRcvBuf */
+ SO_SNDLOWAT, /* osl_Socket_OptionSndLowat */
+ SO_RCVLOWAT, /* osl_Socket_OptionRcvLowat */
+ SO_SNDTIMEO, /* osl_Socket_OptionSndTimeo */
+ SO_RCVTIMEO, /* osl_Socket_OptionRcvTimeo */
+ SO_ERROR, /* osl_Socket_OptionError */
+ SO_TYPE, /* osl_Socket_OptionType */
+ TCP_NODELAY, /* osl_Socket_OptionTcpNoDelay */
+ 0 /* osl_Socket_OptionInvalid */
+};
+
+/* macros */
+#define OPTION_TO_NATIVE(x) OptionMap[x]
+#define OPTION_FROM_NATIVE(y) osl_SocketOptionFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketOptionLevel */
+/*****************************************************************************/
+
+static DWORD OptionLevelMap[]= {
+ SOL_SOCKET, /* osl_Socket_LevelSocket */
+ IPPROTO_TCP, /* osl_Socket_LevelTcp */
+ 0 /* osl_invalid_SocketLevel */
+};
+
+/* macros */
+#define OPTION_LEVEL_TO_NATIVE(x) OptionLevelMap[x]
+#define OPTION_LEVEL_FROM_NATIVE(y) osl_SocketOptionLevelFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketMsgFlag */
+/*****************************************************************************/
+
+static DWORD SocketMsgFlagMap[]= {
+ 0, /* osl_Socket_MsgNormal */
+ MSG_OOB, /* osl_Socket_MsgOOB */
+ MSG_PEEK, /* osl_Socket_MsgPeek */
+ MSG_DONTROUTE, /* osl_Socket_MsgDontRoute */
+ MSG_MAXIOVLEN /* osl_Socket_MsgMaxIOVLen */
+};
+
+/* macros */
+#define MSG_FLAG_TO_NATIVE(x) SocketMsgFlagMap[x]
+#define MSG_FLAG_FROM_NATIVE(y) osl_SocketMsgFlagFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketDirection */
+/*****************************************************************************/
+
+static DWORD SocketDirection[]= {
+ SD_RECEIVE, /* osl_Socket_DirRead */
+ SD_SEND, /* osl_Socket_DirWrite */
+ SD_BOTH /* osl_Socket_DirReadwrite */
+};
+
+/* macros */
+#define DIRECTION_TO_NATIVE(x) SocketDirection[x]
+#define DIRECTION_FROM_NATIVE(y) osl_SocketDirectionFromNative(y)
+
+/*****************************************************************************/
+/* enum oslSocketError */
+/*****************************************************************************/
+
+static int SocketError[]= {
+
+ 0, /* no error */
+ WSAENOTSOCK, /* Socket operation on non-socket */
+ WSAEDESTADDRREQ, /* Destination address required */
+ WSAEMSGSIZE, /* Message too long */
+ WSAEPROTOTYPE, /* Protocol wrong type for socket */
+ WSAENOPROTOOPT, /* Protocol not available */
+ WSAEPROTONOSUPPORT, /* Protocol not supported */
+ WSAESOCKTNOSUPPORT, /* Socket type not supported */
+ WSAEOPNOTSUPP, /* Operation not supported on socket */
+ WSAEPFNOSUPPORT, /* Protocol family not supported */
+ WSAEAFNOSUPPORT, /* Address family not supported by */
+ /* protocol family */
+ WSAEADDRINUSE, /* Address already in use */
+ WSAEADDRNOTAVAIL, /* Can't assign requested address */
+ WSAENETDOWN, /* Network is down */
+ WSAENETUNREACH, /* Network is unreachable */
+ WSAENETRESET, /* Network dropped connection because */
+ /* of reset */
+ WSAECONNABORTED, /* Software caused connection abort */
+ WSAECONNRESET, /* Connection reset by peer */
+ WSAENOBUFS, /* No buffer space available */
+ WSAEISCONN, /* Socket is already connected */
+ WSAENOTCONN, /* Socket is not connected */
+ WSAESHUTDOWN, /* Can't send after socket shutdown */
+ WSAETOOMANYREFS, /* Too many references: can't splice */
+ WSAETIMEDOUT, /* Connection timed out */
+ WSAECONNREFUSED, /* Connection refused */
+ WSAEHOSTDOWN, /* Host is down */
+ WSAEHOSTUNREACH, /* No route to host */
+ WSAEWOULDBLOCK, /* call would block on non-blocking socket */
+ WSAEALREADY, /* operation already in progress */
+ WSAEINPROGRESS /* operation now in progress */
+};
+
+/* reverse map */
+static oslSocketError osl_SocketErrorFromNative(int nativeType)
+{
+ oslSocketError i= (oslSocketError)0;
+
+ while(i != osl_Socket_E_InvalidError)
+ {
+ if(SocketError[i] == nativeType)
+ return i;
+
+ i = (oslSocketError)( (int) i + 1);
+ }
+ return i;
+}
+
+/* macros */
+#define ERROR_TO_NATIVE(x) SocketError[x]
+#define ERROR_FROM_NATIVE(y) osl_SocketErrorFromNative(y)
+
+/*****************************************************************************/
+/* oslSocketDialupImpl */
+/*****************************************************************************/
+static oslSocketDialupImpl *pDialupImpl = NULL;
+
+#if 0 /* INTERNAL DEBUG ONLY */
+BOOL WINAPI __osl_autodial_Impl (DWORD dwFlags, DWORD dwReserved)
+{
+ return 0;
+}
+
+BOOL WINAPI __osl_autodialHangup_Impl (DWORD dwReserved)
+{
+ return 1;
+}
+
+BOOL WINAPI __osl_getConnectedState_Impl (LPDWORD lpdwFlags, DWORD dwReserved)
+{
+ if (lpdwFlags)
+ *lpdwFlags = 0;
+ return 0;
+}
+#endif /* INTERNAL DEBUG ONLY */
+
+/*
+ * __osl_createSocketDialupImpl.
+ */
+static oslSocketDialupImpl* __osl_createSocketDialupImpl (void)
+{
+ oslSocketDialupImpl *pImpl;
+ pImpl = (oslSocketDialupImpl*)rtl_allocateZeroMemory( sizeof (oslSocketDialupImpl));
+
+ InitializeCriticalSection (&pImpl->m_hMutex);
+
+ return (pImpl);
+}
+
+/*
+ * __osl_initSocketDialupImpl.
+ */
+static void __osl_initSocketDialupImpl (oslSocketDialupImpl *pImpl)
+{
+#ifdef SOCKET_USE_AUTODIAL
+ if (pImpl)
+ {
+ HINSTANCE hModule;
+
+ EnterCriticalSection (&pImpl->m_hMutex);
+
+ hModule = LoadLibrary (INTERNET_MODULE_NAME);
+ if (!(hModule <= (HINSTANCE)HINSTANCE_ERROR))
+ {
+ pImpl->m_pfnAttemptConnect = (INTERNETATTEMPTCONNECT)
+ (GetProcAddress (hModule, "InternetAttemptConnect"));
+ pImpl->m_pfnAutodial = (INTERNETAUTODIAL)
+ (GetProcAddress (hModule, "InternetAutodial"));
+ pImpl->m_pfnAutodialHangup = (INTERNETAUTODIALHANGUP)
+ (GetProcAddress (hModule, "InternetAutodialHangup"));
+ pImpl->m_pfnGetConnectedState = (INTERNETGETCONNECTEDSTATE)
+ (GetProcAddress (hModule, "InternetGetConnectedState"));
+ pImpl->m_hModule = hModule;
+ }
+
+ LeaveCriticalSection (&pImpl->m_hMutex);
+ }
+#else
+ pImpl = pImpl; /* avoid warnings */
+#endif
+}
+
+/*
+ * __osl_destroySocketDialupImpl.
+ */
+static void __osl_destroySocketDialupImpl (oslSocketDialupImpl *pImpl)
+{
+ if (pImpl)
+ {
+ EnterCriticalSection (&pImpl->m_hMutex);
+
+ if (pImpl->m_dwFlags & INTERNET_CONNECTION_HANGUP)
+ {
+ if (pImpl->m_pfnAutodialHangup)
+ {
+ (pImpl->m_pfnAutodialHangup)(0);
+ pImpl->m_dwFlags &= ~INTERNET_CONNECTION_HANGUP;
+ }
+ }
+
+ if (pImpl->m_hModule)
+ FreeLibrary (pImpl->m_hModule);
+
+ LeaveCriticalSection (&pImpl->m_hMutex);
+ DeleteCriticalSection (&pImpl->m_hMutex);
+
+ rtl_freeMemory (pImpl);
+ }
+}
+
+/*
+ * __osl_querySocketDialupImpl.
+ */
+static sal_Bool __osl_querySocketDialupImpl (void)
+{
+ sal_Bool result;
+
+ if (pDialupImpl == NULL)
+ {
+ pDialupImpl = __osl_createSocketDialupImpl();
+ __osl_initSocketDialupImpl (pDialupImpl);
+ }
+
+ EnterCriticalSection (&pDialupImpl->m_hMutex);
+
+ result = sal_True;
+ if (pDialupImpl->m_pfnGetConnectedState)
+ {
+ DWORD dwFlags = 0;
+
+ result = (sal_Bool)(pDialupImpl->m_pfnGetConnectedState)(&dwFlags, 0);
+ pDialupImpl->m_dwFlags |= dwFlags;
+ }
+
+ LeaveCriticalSection (&pDialupImpl->m_hMutex);
+ return (result);
+}
+
+/*
+ * __osl_attemptSocketDialupImpl.
+ */
+static sal_Bool __osl_attemptSocketDialupImpl (void)
+{
+ sal_Bool result;
+
+ if (pDialupImpl == NULL)
+ {
+ pDialupImpl = __osl_createSocketDialupImpl();
+ __osl_initSocketDialupImpl (pDialupImpl);
+ }
+
+ EnterCriticalSection (&pDialupImpl->m_hMutex);
+
+ result = __osl_querySocketDialupImpl();
+ if (!result)
+ {
+ result = sal_True;
+ if (pDialupImpl->m_pfnAutodial)
+ {
+ result = (sal_Bool)(pDialupImpl->m_pfnAutodial)(0, 0);
+ if (result)
+ pDialupImpl->m_dwFlags |= INTERNET_CONNECTION_HANGUP;
+ else
+ WSASetLastError (WSAENETDOWN);
+ }
+ }
+
+ LeaveCriticalSection (&pDialupImpl->m_hMutex);
+ return (result);
+}
+
+/*****************************************************************************/
+/* oslSocketImpl */
+/*****************************************************************************/
+static sal_uInt32 g_nSocketImpl = 0;
+
+#if OSL_DEBUG_LEVEL > 1
+static sal_uInt32 g_nSocketAddr = 0;
+struct LeakWarning
+{
+ ~LeakWarning()
+ {
+ if( g_nSocketImpl )
+ OSL_TRACE( "sal_socket: %d socket instances leak\n" , g_nSocketImpl );
+ if( g_nSocketAddr )
+ OSL_TRACE( "sal_socket: %d socket address instances leak\n" , g_nSocketAddr );
+ }
+};
+LeakWarning socketWarning;
+#endif
+
+/*
+ * __osl_createSocketImpl.
+ */
+oslSocket __osl_createSocketImpl(SOCKET Socket)
+{
+ oslSocket pSockImpl = (oslSocket) rtl_allocateZeroMemory( sizeof(struct oslSocketImpl));
+ pSockImpl->m_Socket = Socket;
+ pSockImpl->m_nRefCount = 1;
+
+ g_nSocketImpl++;
+
+ return (pSockImpl);
+}
+
+/*
+ * __osl_destroySocketImpl.
+ */
+void __osl_destroySocketImpl(oslSocketImpl *pImpl)
+{
+ if (pImpl)
+ {
+ if (--g_nSocketImpl == 0)
+ {
+ __osl_destroySocketDialupImpl (pDialupImpl);
+ pDialupImpl = NULL;
+ }
+ rtl_freeMemory (pImpl);
+ }
+}
+/*****************************************************************************/
+static oslSocketAddr __osl_createSocketAddr( )
+{
+ oslSocketAddr pAddr = (oslSocketAddr) rtl_allocateZeroMemory( sizeof( struct oslSocketAddrImpl ));
+ pAddr->m_nRefCount = 1;
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketAddr ++;
+#endif
+ return pAddr;
+}
+
+static oslSocketAddr __osl_createSocketAddrWithFamily(
+ oslAddrFamily family, sal_Int32 port, sal_uInt32 nAddr )
+{
+ OSL_ASSERT( family == osl_Socket_FamilyInet );
+
+ oslSocketAddr pAddr = __osl_createSocketAddr();
+ switch( family )
+ {
+ case osl_Socket_FamilyInet:
+ {
+ struct sockaddr_in* pInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ pInetAddr->sin_family = FAMILY_TO_NATIVE(osl_Socket_FamilyInet);
+ pInetAddr->sin_addr.s_addr = nAddr;
+ pInetAddr->sin_port = (sal_uInt16)(port&0xffff);
+ break;
+ }
+ default:
+ pAddr->m_sockaddr.sa_family = FAMILY_TO_NATIVE(family);
+ }
+ return pAddr;
+}
+
+static oslSocketAddr __osl_createSocketAddrFromSystem( struct sockaddr *pSystemSockAddr )
+{
+ oslSocketAddr pAddr = __osl_createSocketAddr();
+ memcpy( &(pAddr->m_sockaddr), pSystemSockAddr, sizeof( sockaddr ) );
+ return pAddr;
+}
+
+static void __osl_destroySocketAddr( oslSocketAddr addr )
+{
+#if OSL_DEBUG_LEVEL > 1
+ g_nSocketAddr --;
+#endif
+ rtl_freeMemory( addr );
+}
+/*****************************************************************************/
+/* osl_createEmptySocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createEmptySocketAddr(oslAddrFamily Family)
+{
+ oslSocketAddr pAddr = 0;
+
+ /* is it an internet-Addr? */
+ if (Family == osl_Socket_FamilyInet)
+ {
+ pAddr = __osl_createSocketAddrWithFamily(Family, 0 , htonl(INADDR_ANY) );
+ }
+ else
+ {
+ pAddr = __osl_createSocketAddrWithFamily( Family , 0 , 0 );
+ }
+
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_copySocketAddr */
+/*****************************************************************************/
+// @deprecated, to be removed
+oslSocketAddr SAL_CALL osl_copySocketAddr(oslSocketAddr Addr)
+{
+ oslSocketAddr pCopy = 0;
+ if (Addr)
+ {
+ pCopy = __osl_createSocketAddr();
+
+ if (pCopy)
+ memcpy(&(pCopy->m_sockaddr),&(Addr->m_sockaddr), sizeof(struct sockaddr));
+ }
+ return pCopy;
+}
+
+/*****************************************************************************/
+/* osl_isEqualSocketAddr */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isEqualSocketAddr(oslSocketAddr Addr1, oslSocketAddr Addr2)
+{
+ struct sockaddr* pAddr1= &(Addr1->m_sockaddr);
+ struct sockaddr* pAddr2= &(Addr2->m_sockaddr);
+
+ OSL_ASSERT(pAddr1);
+ OSL_ASSERT(pAddr2);
+
+ if (pAddr1->sa_family == pAddr2->sa_family)
+ {
+ switch (pAddr1->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in* pInetAddr1= (struct sockaddr_in*)pAddr1;
+ struct sockaddr_in* pInetAddr2= (struct sockaddr_in*)pAddr2;
+
+ if ((pInetAddr1->sin_family == pInetAddr2->sin_family) &&
+ (pInetAddr1->sin_addr.s_addr == pInetAddr2->sin_addr.s_addr) &&
+ (pInetAddr1->sin_port == pInetAddr2->sin_port))
+ return (sal_True);
+ }
+
+ default:
+ {
+ return (memcmp(pAddr1, Addr2, sizeof(struct sockaddr)) == 0);
+ }
+ }
+ }
+
+ return (sal_False);
+}
+
+/*****************************************************************************/
+/* osl_createInetBroadcastAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createInetBroadcastAddr (
+ rtl_uString *strDottedAddr,
+ sal_Int32 Port)
+{
+ sal_uInt32 nAddr = OSL_INADDR_NONE;
+
+ if (strDottedAddr && strDottedAddr->length)
+ {
+ /* Dotted host address for limited broadcast */
+ rtl_String *pDottedAddr = NULL;
+
+ rtl_uString2String (
+ &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ nAddr = inet_addr (pDottedAddr->buffer);
+ rtl_string_release (pDottedAddr);
+ }
+
+ if (nAddr != OSL_INADDR_NONE)
+ {
+ /* Limited broadcast */
+ nAddr = ntohl(nAddr);
+ if (IN_CLASSA(nAddr))
+ {
+ nAddr &= IN_CLASSA_NET;
+ nAddr |= IN_CLASSA_HOST;
+ }
+ else if (IN_CLASSB(nAddr))
+ {
+ nAddr &= IN_CLASSB_NET;
+ nAddr |= IN_CLASSB_HOST;
+ }
+ else if (IN_CLASSC(nAddr))
+ {
+ nAddr &= IN_CLASSC_NET;
+ nAddr |= IN_CLASSC_HOST;
+ }
+ else
+ {
+ /* No broadcast in class D */
+ return ((oslSocketAddr)NULL);
+ }
+ nAddr = htonl(nAddr);
+ }
+
+ oslSocketAddr pAddr =
+ __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons( (sal_uInt16) Port), nAddr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createInetSocketAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_createInetSocketAddr (
+ rtl_uString *strDottedAddr,
+ sal_Int32 Port)
+{
+ DWORD Addr;
+ rtl_String *pDottedAddr=NULL;
+
+ rtl_uString2String(
+ &pDottedAddr, strDottedAddr->buffer, strDottedAddr->length,
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ Addr= inet_addr (pDottedAddr->buffer);
+ rtl_string_release (pDottedAddr);
+
+ oslSocketAddr pAddr = 0;
+ if(Addr != -1)
+ {
+ pAddr = __osl_createSocketAddrWithFamily( osl_Socket_FamilyInet, htons( (sal_uInt16)Port), Addr );
+ }
+ return pAddr;
+}
+
+oslSocketResult SAL_CALL osl_setAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence *pByteSeq )
+{
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( pByteSeq );
+
+ oslSocketResult res = osl_Socket_Error;
+ if( pAddr && pByteSeq )
+ {
+ OSL_ASSERT( pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE( osl_Socket_FamilyInet ) );
+ OSL_ASSERT( pByteSeq->nElements == 4 );
+ struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
+ memcpy( &(pSystemInetAddr->sin_addr) , pByteSeq->elements , 4 );
+ res = osl_Socket_Ok;
+ }
+ return res;
+}
+
+/** Returns the addr field in the struct sockaddr. ppByteSeq is in network byteorder. *ppByteSeq may
+ either be 0 or contain a constructed sal_Sequence.
+ */
+oslSocketResult SAL_CALL osl_getAddrOfSocketAddr( oslSocketAddr pAddr, sal_Sequence **ppByteSeq )
+{
+ OSL_ASSERT( pAddr );
+ OSL_ASSERT( ppByteSeq );
+
+ oslSocketResult res = osl_Socket_Error;
+ if( pAddr && ppByteSeq )
+ {
+ struct sockaddr_in * pSystemInetAddr = (struct sockaddr_in * ) &(pAddr->m_sockaddr);
+ rtl_byte_sequence_constructFromArray( ppByteSeq , (sal_Int8 *) &(pSystemInetAddr->sin_addr),4);
+ res = osl_Socket_Ok;
+ }
+ return res;
+}
+
+/*****************************************************************************/
+/* oslHostAddr */
+/*****************************************************************************/
+struct oslHostAddrImpl {
+ rtl_uString *pHostName;
+ oslSocketAddr pSockAddr;
+} ;
+
+static oslHostAddr __osl_hostentToHostAddr (const struct hostent *he)
+{
+ oslHostAddr pAddr= NULL;
+ oslSocketAddr pSocketAddr = 0;
+
+ rtl_uString *cn= NULL;
+
+ if ((he == NULL) || (he->h_name == NULL) || (he->h_addr_list[0] == NULL))
+ return ((oslHostAddr)NULL);
+
+ rtl_string2UString(
+ &cn, he->h_name, strlen(he->h_name),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(cn != 0);
+
+ pSocketAddr = __osl_createSocketAddr();
+
+ if (pSocketAddr == NULL)
+ {
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pSocketAddr->m_sockaddr.sa_family = he->h_addrtype;
+ if (pSocketAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ struct sockaddr_in *sin= (struct sockaddr_in *)&(pSocketAddr->m_sockaddr);
+ memcpy (
+ &(sin->sin_addr.s_addr),
+ he->h_addr_list[0],
+ he->h_length);
+ }
+ else
+ {
+ /* unknown address family */
+ /* future extensions for new families might be implemented here */
+
+ OSL_TRACE("_osl_hostentToHostAddr(): unknown address family.\n");
+ OSL_ASSERT(sal_False);
+
+ __osl_destroySocketAddr( pSocketAddr );
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr= (oslHostAddr )rtl_allocateMemory (sizeof (struct oslHostAddrImpl));
+
+ if (pAddr == NULL)
+ {
+ __osl_destroySocketAddr( pSocketAddr );
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr->pHostName= cn;
+ pAddr->pSockAddr= pSocketAddr;
+
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_createHostAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddr (
+ rtl_uString *strHostname,
+ const oslSocketAddr pSocketAddr)
+{
+ oslHostAddr pAddr;
+ rtl_uString *cn= NULL;
+
+ if ((strHostname == NULL) || (strHostname->length == 0) || (pSocketAddr == NULL))
+ return ((oslHostAddr)NULL);
+
+ rtl_uString_newFromString( &cn, strHostname);
+
+ if ( ! pSocketAddr )
+ {
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr= (oslHostAddr)rtl_allocateMemory (sizeof (struct oslHostAddrImpl));
+
+ if (pAddr == NULL)
+ {
+ rtl_uString_release(cn);
+ return ((oslHostAddr)NULL);
+ }
+
+ pAddr->pHostName= cn;
+ pAddr->pSockAddr= osl_copySocketAddr( pSocketAddr );
+
+ return ((oslHostAddr)pAddr);
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByName */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByName(rtl_uString *strHostname)
+{
+ if ((strHostname == NULL) || (strHostname->length == 0))
+ return ((oslHostAddr)NULL);
+
+ if (__osl_attemptSocketDialupImpl())
+ {
+ struct hostent *he;
+ rtl_String *Hostname= NULL;
+
+ rtl_uString2String(
+ &Hostname, strHostname->buffer, strHostname->length,
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ he= gethostbyname (Hostname->buffer);
+
+ rtl_string_release (Hostname);
+ return __osl_hostentToHostAddr (he);
+ }
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_createHostAddrByAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_createHostAddrByAddr(const oslSocketAddr pAddr)
+{
+ if (pAddr == NULL)
+ return ((oslHostAddr)NULL);
+
+ if (pAddr->m_sockaddr.sa_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ {
+ const struct sockaddr_in *sin= (const struct sockaddr_in *)&(pAddr->m_sockaddr);
+
+ if (sin->sin_addr.s_addr == htonl(INADDR_ANY))
+ return ((oslHostAddr)NULL);
+
+ if (__osl_attemptSocketDialupImpl())
+ {
+ struct hostent *he;
+ he= gethostbyaddr ((const sal_Char *)&(sin->sin_addr),
+ sizeof (sin->sin_addr),
+ sin->sin_family);
+ return __osl_hostentToHostAddr (he);
+ }
+ }
+
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_copyHostAddr */
+/*****************************************************************************/
+oslHostAddr SAL_CALL osl_copyHostAddr(const oslHostAddr Addr)
+{
+ oslHostAddr pAddr= (oslHostAddr)Addr;
+
+ if (pAddr)
+ return osl_createHostAddr (pAddr->pHostName, pAddr->pSockAddr);
+ else
+ return ((oslHostAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_getHostnameOfHostAddr(
+ const oslHostAddr pAddr, rtl_uString **strHostname)
+{
+ if (pAddr)
+ rtl_uString_assign (strHostname, pAddr->pHostName);
+ else
+ rtl_uString_new (strHostname);
+}
+
+/*****************************************************************************/
+/* osl_getSocketAddrOfHostAddr */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getSocketAddrOfHostAddr(const oslHostAddr pAddr)
+{
+ if (pAddr)
+ return (const oslSocketAddr)(pAddr->pSockAddr);
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+/* osl_destroyHostAddr */
+/*****************************************************************************/
+void SAL_CALL osl_destroyHostAddr(oslHostAddr pAddr)
+{
+ if (pAddr)
+ {
+ if (pAddr->pHostName)
+ rtl_uString_release (pAddr->pHostName);
+ if (pAddr->pSockAddr)
+ osl_destroySocketAddr( pAddr->pSockAddr );
+
+ rtl_freeMemory (pAddr);
+ }
+}
+
+/*****************************************************************************/
+/* osl_getLocalHostname */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getLocalHostname (rtl_uString **strLocalHostname)
+{
+ static sal_Unicode LocalHostname[256] = {0};
+
+ if (rtl_ustr_getLength(LocalHostname) == 0)
+ {
+ sal_Char Host[256]= "";
+ if (gethostname(Host, sizeof(Host)) == 0)
+ {
+ /* check if we have an FQDN */
+ if (strchr(Host, '.') == NULL)
+ {
+ oslHostAddr pAddr;
+ rtl_uString *hostName= NULL;
+
+ rtl_string2UString(
+ &hostName, Host, strlen(Host),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(hostName != 0);
+
+ /* no, determine it via dns */
+ pAddr = osl_createHostAddrByName(hostName);
+ rtl_uString_release (hostName);
+
+ if (pAddr && pAddr->pHostName)
+ memcpy(LocalHostname, pAddr->pHostName->buffer, sizeof(sal_Unicode)*(rtl_ustr_getLength(pAddr->pHostName->buffer)+1));
+ else
+ memset(LocalHostname, 0, sizeof(LocalHostname));
+
+ osl_destroyHostAddr ((oslHostAddr)pAddr);
+ }
+ }
+ }
+
+ if (rtl_ustr_getLength(LocalHostname) > 0)
+ {
+ rtl_uString_newFromStr (strLocalHostname, LocalHostname);
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_resolveHostname */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_resolveHostname(rtl_uString* strHostname)
+{
+ oslHostAddr pAddr=
+ (oslHostAddr )osl_createHostAddrByName (strHostname);
+ if (pAddr)
+ {
+ oslSocketAddr SockAddr = osl_copySocketAddr( pAddr->pSockAddr );
+ osl_destroyHostAddr(pAddr);
+ return (SockAddr);
+ }
+ return ((oslSocketAddr)NULL);
+}
+
+/*****************************************************************************/
+/* osl_getServicePort */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getServicePort (
+ rtl_uString* strServicename,
+ rtl_uString* strProtocol)
+{
+ struct servent* ps;
+
+ rtl_String *str_Servicename=NULL;
+ rtl_String *str_Protocol=NULL;
+
+ rtl_uString2String(
+ &str_Servicename,
+ rtl_uString_getStr(strServicename),
+ rtl_uString_getLength(strServicename),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+ rtl_uString2String(
+ &str_Protocol,
+ rtl_uString_getStr(strProtocol),
+ rtl_uString_getLength(strProtocol),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+
+ ps= getservbyname(
+ rtl_string_getStr(str_Servicename),
+ rtl_string_getStr(str_Protocol));
+
+ rtl_string_release( str_Servicename );
+ rtl_string_release( str_Protocol );
+
+ if (ps != 0)
+ return ntohs(ps->s_port);
+
+ return OSL_INVALID_PORT;
+}
+
+/*****************************************************************************/
+/* osl_destroySocketAddr */
+/*****************************************************************************/
+void SAL_CALL osl_destroySocketAddr(oslSocketAddr pAddr)
+{
+ __osl_destroySocketAddr( pAddr );
+}
+
+/*****************************************************************************/
+/* osl_getFamilyOfSocketAddr */
+/*****************************************************************************/
+oslAddrFamily SAL_CALL osl_getFamilyOfSocketAddr(oslSocketAddr pAddr)
+{
+ if (pAddr)
+ return FAMILY_FROM_NATIVE(pAddr->m_sockaddr.sa_family);
+ else
+ return osl_Socket_FamilyInvalid;
+}
+
+/*****************************************************************************/
+/* osl_getInetPortOfSocketAddr */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getInetPortOfSocketAddr(oslSocketAddr pAddr)
+{
+ if( pAddr )
+ {
+ struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ if ( (pSystemInetAddr->sin_family == FAMILY_TO_NATIVE(osl_Socket_FamilyInet)))
+ return ntohs(pSystemInetAddr->sin_port);
+ }
+ return OSL_INVALID_PORT;
+}
+
+/*****************************************************************************/
+/* osl_setInetPortOfSocketAddr */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setInetPortOfSocketAddr (
+ oslSocketAddr pAddr,
+ sal_Int32 Port)
+{
+ if (pAddr == NULL)
+ return sal_False;
+
+ struct sockaddr_in* pSystemInetAddr= (struct sockaddr_in*)&(pAddr->m_sockaddr);
+
+ if (pSystemInetAddr->sin_family != FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ return sal_False;
+
+ pSystemInetAddr->sin_port= htons((short)Port);
+ return sal_True;
+}
+
+/*****************************************************************************/
+/* osl_getHostnameOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getHostnameOfSocketAddr (
+ oslSocketAddr Addr,
+ rtl_uString **strHostName)
+{
+ oslHostAddr pAddr= osl_createHostAddrByAddr (Addr);
+
+ if (pAddr)
+ {
+ rtl_uString_newFromString(strHostName, pAddr->pHostName);
+
+ osl_destroyHostAddr(pAddr);
+
+ return osl_Socket_Ok;
+ }
+
+ return osl_Socket_Error;
+}
+
+/*****************************************************************************/
+/* osl_getDottedInetAddrOfSocketAddr */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_getDottedInetAddrOfSocketAddr (
+ oslSocketAddr pAddr,
+ rtl_uString **strDottedInetAddr)
+{
+ sal_Char *pDotted;
+
+ if (pAddr == NULL)
+ return osl_Socket_Error;
+
+ struct sockaddr_in *pSystemInetAddr = (struct sockaddr_in*) &(pAddr->m_sockaddr);
+ if (pSystemInetAddr->sin_family != FAMILY_TO_NATIVE(osl_Socket_FamilyInet))
+ return osl_Socket_Error;
+
+ pDotted = inet_ntoa (pSystemInetAddr->sin_addr);
+ rtl_string2UString(
+ strDottedInetAddr, pDotted, strlen (pDotted),
+ RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(*strDottedInetAddr != 0);
+
+ return osl_Socket_Ok;
+}
+
+/*****************************************************************************/
+/* osl_createSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_createSocket (
+ oslAddrFamily Family,
+ oslSocketType Type,
+ oslProtocol Protocol)
+{
+ /* alloc memory */
+ oslSocket pSocket = __osl_createSocketImpl(0);
+
+ if (pSocket == NULL)
+ return 0;
+
+ /* create socket */
+ pSocket->m_Socket= socket(FAMILY_TO_NATIVE(Family),
+ TYPE_TO_NATIVE(Type),
+ PROTOCOL_TO_NATIVE(Protocol));
+
+ /* creation failed => free memory */
+ if(pSocket->m_Socket == OSL_INVALID_SOCKET)
+ {
+ __osl_destroySocketImpl(pSocket);
+ pSocket= 0;
+ }
+ else
+ {
+ pSocket->m_Flags = 0;
+ pSocket->m_CloseCallback = NULL;
+ pSocket->m_CallbackArg = NULL;
+ }
+
+ return pSocket;
+}
+
+void SAL_CALL osl_acquireSocket( oslSocket pSocket )
+{
+ osl_incrementInterlockedCount( &(pSocket->m_nRefCount) );
+}
+
+void SAL_CALL osl_releaseSocket( oslSocket pSocket )
+{
+ if( pSocket && 0 == osl_decrementInterlockedCount( &(pSocket->m_nRefCount) ) )
+ {
+ osl_closeSocket( pSocket );
+ __osl_destroySocketImpl( pSocket );
+ }
+}
+
+/*****************************************************************************/
+/* osl_closeSocket */
+/*****************************************************************************/
+void SAL_CALL osl_closeSocket(oslSocket pSocket)
+{
+ /* socket already invalid */
+ if(pSocket==0)
+ return;
+
+ /* close */
+ closesocket(pSocket->m_Socket);
+
+ pSocket->m_Socket = OSL_INVALID_SOCKET;
+
+ /* registrierten Callback ausfuehren */
+ if (pSocket->m_CloseCallback != NULL)
+ {
+ pSocket->m_CloseCallback(pSocket->m_CallbackArg);
+ }
+}
+
+/*****************************************************************************/
+/* osl_getLocalAddrOfSocket */
+/* Note that I rely on the fact that oslSocketAddr and struct sockaddr */
+/* are the same! I don't like it very much but see no other easy way */
+/* to conceal the struct sockaddr from the eyes of the user. */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getLocalAddrOfSocket(oslSocket pSocket)
+{
+ struct sockaddr Addr;
+ int AddrLen;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return ((oslSocketAddr)NULL);
+
+ AddrLen= sizeof(struct sockaddr);
+
+ if (getsockname(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
+ return ((oslSocketAddr)NULL);
+
+ oslSocketAddr pAddr = __osl_createSocketAddrFromSystem( &Addr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_getPeerAddrOfSocket */
+/*****************************************************************************/
+oslSocketAddr SAL_CALL osl_getPeerAddrOfSocket(oslSocket pSocket)
+{
+ struct sockaddr Addr;
+ int AddrLen;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return ((oslSocketAddr)NULL);
+
+ AddrLen= sizeof(struct sockaddr);
+
+ if (getpeername(pSocket->m_Socket, &Addr, &AddrLen) == OSL_SOCKET_ERROR)
+ return ((oslSocketAddr)NULL);
+
+ oslSocketAddr pAddr = __osl_createSocketAddrFromSystem( &Addr );
+ return pAddr;
+}
+
+/*****************************************************************************/
+/* osl_bindAddrToSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_bindAddrToSocket ( oslSocket pSocket, oslSocketAddr pAddr)
+{
+ OSL_ASSERT( pAddr );
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return (bind(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR);
+}
+
+/*****************************************************************************/
+/* osl_connectSocketTo */
+/*****************************************************************************/
+oslSocketResult SAL_CALL osl_connectSocketTo (
+ oslSocket pSocket,
+ oslSocketAddr pAddr,
+ const TimeValue* pTimeout)
+{
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ if (pAddr == NULL) /* EDESTADDRREQ */
+ return osl_Socket_Error;
+
+ if (!__osl_attemptSocketDialupImpl()) /* ENETDOWN */
+ return osl_Socket_Error;
+
+ if (pTimeout == NULL)
+ {
+ if(connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) == OSL_SOCKET_ERROR)
+ return osl_Socket_Error;
+ else
+ return osl_Socket_Ok;
+ }
+ else
+ {
+ fd_set fds;
+ int error;
+ struct timeval tv;
+ unsigned long Param;
+ oslSocketResult Result= osl_Socket_Ok;
+
+ if (pSocket->m_Flags & OSL_SOCKET_FLAGS_NONBLOCKING)
+ {
+ if (connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) == OSL_SOCKET_ERROR)
+ {
+ switch (WSAGetLastError())
+ {
+ case WSAEWOULDBLOCK:
+ case WSAEINPROGRESS:
+ return osl_Socket_InProgress;
+
+ default:
+ return osl_Socket_Error;
+ }
+ }
+ else
+ return osl_Socket_Ok;
+ }
+
+ /* set socket temporarily to non-blocking */
+ Param= 1;
+ OSL_VERIFY(ioctlsocket(
+ pSocket->m_Socket, FIONBIO, &Param) != OSL_SOCKET_ERROR);
+
+ /* initiate connect */
+ if (connect(pSocket->m_Socket,
+ &(pAddr->m_sockaddr),
+ sizeof(struct sockaddr)) != OSL_SOCKET_ERROR)
+ {
+ /* immediate connection */
+
+ Param= 0;
+ ioctlsocket(pSocket->m_Socket, FIONBIO, &Param);
+
+ return osl_Socket_Ok;
+ }
+ else
+ {
+ error = WSAGetLastError();
+
+ /* really an error or just delayed? */
+ if (error != WSAEWOULDBLOCK && error != WSAEINPROGRESS)
+ {
+ Param= 0;
+ ioctlsocket(pSocket->m_Socket, FIONBIO, &Param);
+
+ return osl_Socket_Error;
+ }
+ }
+
+ /* prepare select set for socket */
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ /* divide milliseconds into seconds and microseconds */
+ tv.tv_sec= pTimeout->Seconds;
+ tv.tv_usec= pTimeout->Nanosec / 1000L;
+
+ /* select */
+ error= select(pSocket->m_Socket+1,
+ 0,
+ &fds,
+ 0,
+ &tv);
+
+ if (error > 0) /* connected */
+ {
+ OSL_POSTCOND(
+ FD_ISSET(pSocket->m_Socket, &fds),
+ "osl_connectSocketTo(): select returned but socket not set\n");
+
+ Result= osl_Socket_Ok;
+
+ }
+ else if(error < 0) /* error */
+ {
+ /* errno == EBADF: most probably interrupted by close() */
+ if(WSAGetLastError() == WSAEBADF)
+ {
+ /* do not access pSockImpl because it is about to be or */
+ /* already destroyed */
+ return osl_Socket_Interrupted;
+ }
+ else
+ Result= osl_Socket_Error;
+
+ }
+ else /* timeout */
+ Result= osl_Socket_TimedOut;
+
+
+ /* clean up */
+ Param= 0;
+ ioctlsocket(pSocket->m_Socket, FIONBIO, &Param);
+
+ return Result;
+ }
+}
+
+/*****************************************************************************/
+/* osl_listenOnSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_listenOnSocket (
+ oslSocket pSocket,
+ sal_Int32 MaxPendingConnections)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return (listen(pSocket->m_Socket,
+ MaxPendingConnections == -1 ?
+ SOMAXCONN :
+ MaxPendingConnections) != OSL_SOCKET_ERROR);
+}
+
+/*****************************************************************************/
+/* osl_acceptConnectionOnSocket */
+/*****************************************************************************/
+oslSocket SAL_CALL osl_acceptConnectionOnSocket (
+ oslSocket pSocket,
+ oslSocketAddr* ppAddr)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return ((oslSocket)NULL);
+
+ SOCKET Connection;
+ if(ppAddr)
+ {
+ if( *ppAddr )
+ {
+ osl_destroySocketAddr( *ppAddr );
+ *ppAddr = 0;
+ }
+ int AddrLen= sizeof(struct sockaddr);
+
+ /* user wants to know peer Addr */
+ struct sockaddr Addr;
+
+ Connection= accept(pSocket->m_Socket, &Addr, &AddrLen);
+ OSL_ASSERT(AddrLen == sizeof(struct sockaddr));
+
+ if(Connection != OSL_SOCKET_ERROR)
+ *ppAddr= __osl_createSocketAddrFromSystem(&Addr);
+ else
+ *ppAddr = NULL;
+ }
+ else
+ {
+ /* user is not interested in peer-addr */
+ Connection= accept(pSocket->m_Socket, 0, 0);
+ }
+
+ /* accept failed? */
+ if(Connection == OSL_SOCKET_ERROR)
+ return ((oslSocket)NULL);
+
+ /* alloc memory */
+ oslSocket pConnectionSocket;
+ pConnectionSocket= __osl_createSocketImpl(Connection);
+
+ pConnectionSocket->m_Flags = 0;
+ pConnectionSocket->m_CloseCallback = NULL;
+ pConnectionSocket->m_CallbackArg = NULL;
+
+ return pConnectionSocket;
+}
+
+/*****************************************************************************/
+/* osl_receiveSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveSocket (
+ oslSocket pSocket,
+ void* pBuffer,
+ sal_uInt32 BytesToRead,
+ oslSocketMsgFlag Flag)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ return recv(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToRead,
+ MSG_FLAG_TO_NATIVE(Flag));
+}
+
+/*****************************************************************************/
+/* osl_receiveFromSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_receiveFromSocket (
+ oslSocket pSocket,
+ oslSocketAddr SenderAddr,
+ void* pBuffer,
+ sal_uInt32 BufferSize,
+ oslSocketMsgFlag Flag)
+{
+ struct sockaddr *pSystemSockAddr = 0;
+ int AddrLen = 0;
+ if( SenderAddr )
+ {
+ AddrLen = sizeof( struct sockaddr );
+ pSystemSockAddr = &(SenderAddr->m_sockaddr);
+ }
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ return recvfrom(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BufferSize,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ &AddrLen);
+}
+
+/*****************************************************************************/
+/* osl_sendSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendSocket (
+ oslSocket pSocket,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ return send(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag));
+}
+
+/*****************************************************************************/
+/* osl_sendToSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_sendToSocket (
+ oslSocket pSocket,
+ oslSocketAddr ReceiverAddr,
+ const void* pBuffer,
+ sal_uInt32 BytesToSend,
+ oslSocketMsgFlag Flag)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ /* ReceiverAddr might be 0 when used on a connected socket. */
+ /* Then sendto should behave like send. */
+
+ struct sockaddr *pSystemSockAddr = 0;
+ if( ReceiverAddr )
+ pSystemSockAddr = &(ReceiverAddr->m_sockaddr);
+
+ return sendto(pSocket->m_Socket,
+ (sal_Char*)pBuffer,
+ BytesToSend,
+ MSG_FLAG_TO_NATIVE(Flag),
+ pSystemSockAddr,
+ pSystemSockAddr == 0 ? 0 : sizeof(struct sockaddr));
+}
+
+/*****************************************************************************/
+/* osl_readSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_readSocket( oslSocket pSocket, void *pBuffer, sal_Int32 n )
+{
+ sal_uInt8 * Ptr = (sal_uInt8 *)pBuffer;
+
+ OSL_ASSERT( pSocket);
+
+ /* loop until all desired bytes were read or an error occured */
+ sal_uInt32 BytesRead= 0;
+ sal_uInt32 BytesToRead= n;
+ while (BytesToRead > 0)
+ {
+ sal_Int32 RetVal;
+ RetVal= osl_receiveSocket(pSocket,
+ Ptr,
+ BytesToRead,
+ osl_Socket_MsgNormal);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToRead -= RetVal;
+ BytesRead += RetVal;
+ Ptr += RetVal;
+ }
+
+ return BytesRead;
+}
+
+/*****************************************************************************/
+/* osl_writeSocket */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_writeSocket( oslSocket pSocket, const void *pBuffer, sal_Int32 n )
+{
+ OSL_ASSERT( pSocket );
+
+ /* loop until all desired bytes were send or an error occured */
+ sal_uInt32 BytesSend= 0;
+ sal_uInt32 BytesToSend= n;
+ sal_uInt8 *Ptr = ( sal_uInt8 * )pBuffer;
+ while (BytesToSend > 0)
+ {
+ sal_Int32 RetVal;
+
+ RetVal= osl_sendSocket( pSocket,Ptr,BytesToSend,osl_Socket_MsgNormal);
+
+ /* error occured? */
+ if(RetVal <= 0)
+ {
+ break;
+ }
+
+ BytesToSend -= RetVal;
+ BytesSend += RetVal;
+ Ptr += RetVal;
+
+ }
+ return BytesSend;
+}
+
+
+/*****************************************************************************/
+/* osl_isReceiveReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isReceiveReady (
+ oslSocket pSocket,
+ const TimeValue* pTimeout)
+{
+ fd_set fds;
+ struct timeval tv;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ if (pTimeout)
+ {
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ return (select(pSocket->m_Socket + 1, /* no of sockets to monitor */
+ &fds, /* check read operations */
+ 0, /* check write ops */
+ 0, /* ckeck for OOB */
+ (pTimeout) ? &tv : 0)==1); /* use timeout? */
+}
+
+/*****************************************************************************/
+/* osl_isSendReady */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isSendReady (
+ oslSocket pSocket,
+ const TimeValue* pTimeout)
+{
+ fd_set fds;
+ struct timeval tv;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ if (pTimeout)
+ {
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ return (select(pSocket->m_Socket + 1, /* no of sockets to monitor */
+ 0, /* check read operations */
+ &fds, /* check write ops */
+ 0, /* ckeck for OOB */
+ (pTimeout) ? &tv : 0)==1); /* use timeout? */
+}
+
+/*****************************************************************************/
+/* osl_isExceptionPending */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isExceptionPending (
+ oslSocket pSocket,
+ const TimeValue* pTimeout)
+{
+ fd_set fds;
+ struct timeval tv;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ FD_ZERO(&fds);
+ FD_SET(pSocket->m_Socket, &fds);
+
+ if (pTimeout)
+ {
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ return (select(pSocket->m_Socket + 1, /* no of sockets to monitor */
+ 0, /* check read operations */
+ 0, /* check write ops */
+ &fds, /* ckeck for OOB */
+ (pTimeout) ? &tv : 0)==1); /* use timeout? */
+}
+
+/*****************************************************************************/
+/* osl_shutdownSocket */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_shutdownSocket (
+ oslSocket pSocket,
+ oslSocketDirection Direction)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return (shutdown(pSocket->m_Socket, DIRECTION_TO_NATIVE(Direction))==0);
+}
+
+/*****************************************************************************/
+/* osl_getSocketOption */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_getSocketOption (
+ oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_Error;
+
+ if (getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ (int*)&BufferLen) == -1)
+ {
+ return -1;
+ }
+
+ return (sal_Int32)BufferLen;
+}
+
+/*****************************************************************************/
+/* osl_setSocketOption */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setSocketOption (
+ oslSocket pSocket,
+ oslSocketOptionLevel Level,
+ oslSocketOption Option,
+ void* pBuffer,
+ sal_uInt32 BufferLen)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return(setsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(Level),
+ OPTION_TO_NATIVE(Option),
+ (sal_Char*)pBuffer,
+ BufferLen) == 0);
+}
+
+/*****************************************************************************/
+/* osl_enableNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_enableNonBlockingMode ( oslSocket pSocket, sal_Bool On)
+{
+ unsigned long Param= On ? 1 : 0;
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ pSocket->m_Flags = Param ?
+ (pSocket->m_Flags | OSL_SOCKET_FLAGS_NONBLOCKING) :
+ (pSocket->m_Flags & ~OSL_SOCKET_FLAGS_NONBLOCKING) ;
+
+ return (
+ ioctlsocket(pSocket->m_Socket, FIONBIO, &Param) != OSL_SOCKET_ERROR);
+}
+
+/*****************************************************************************/
+/* osl_isNonBlockingMode */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isNonBlockingMode(oslSocket pSocket)
+{
+ if (pSocket == NULL) /* ENOTSOCK */
+ return sal_False;
+
+ return (sal_Bool)((pSocket->m_Flags & OSL_SOCKET_FLAGS_NONBLOCKING) != 0);
+}
+
+/*****************************************************************************/
+/* osl_getSocketType */
+/*****************************************************************************/
+oslSocketType SAL_CALL osl_getSocketType(oslSocket pSocket)
+{
+ int Type=0;
+ int TypeSize= sizeof(Type);
+
+ if (pSocket == NULL) /* ENOTSOCK */
+ return osl_Socket_TypeInvalid;
+
+ if(getsockopt(pSocket->m_Socket,
+ OPTION_LEVEL_TO_NATIVE(osl_Socket_LevelSocket),
+ OPTION_TO_NATIVE(osl_Socket_OptionType),
+ (sal_Char *)&Type,
+ &TypeSize) == -1)
+ {
+ /* error */
+ return osl_Socket_TypeInvalid;
+ }
+
+ return TYPE_FROM_NATIVE(Type);
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketErrorDescription */
+/*****************************************************************************/
+void SAL_CALL osl_getLastSocketErrorDescription (
+ oslSocket /*Socket*/,
+ rtl_uString **strError)
+{
+ int error;
+
+ switch(error = WSAGetLastError())
+ {
+ case WSAENOTSOCK:
+ rtl_uString_newFromAscii (strError, "WSAENOTSOCK, Socket operation on non-socket. A socket created in one process is used by another process.");
+ break;
+
+ case WSAEDESTADDRREQ:
+ rtl_uString_newFromAscii (strError, "WSAEDESTADDRREQ, Destination Addr required");
+ break;
+
+ case WSAEMSGSIZE:
+ rtl_uString_newFromAscii (strError, "WSAEMSGSIZE, Message too long");
+ break;
+
+ case WSAEPROTOTYPE:
+ rtl_uString_newFromAscii (strError, "WSAEPROTOTYPE, Protocol wrong type for socket");
+ break;
+
+ case WSAENOPROTOOPT:
+ rtl_uString_newFromAscii (strError, "WSAENOPROTOOPT, Protocol not available");
+ break;
+
+ case WSAEPROTONOSUPPORT:
+ rtl_uString_newFromAscii (strError, "WSAEPROTONOSUPPORT, Protocol not supported");
+ break;
+
+ case WSAESOCKTNOSUPPORT:
+ rtl_uString_newFromAscii (strError, "WSAESOCKTNOSUPPORT, Socket type not supported");
+ break;
+
+ case WSAEOPNOTSUPP:
+ rtl_uString_newFromAscii (strError, "WSAEOPNOTSUPP, Operation not supported on socket");
+ break;
+
+ case WSAEPFNOSUPPORT:
+ rtl_uString_newFromAscii (strError, "WSAEPFNOSUPPORT, Protocol family not supported");
+ break;
+
+ case WSAEAFNOSUPPORT:
+ rtl_uString_newFromAscii (strError, "WSEAFNOSUPPORT, Addr family not supported by protocol family");
+ break;
+
+ case WSAEADDRINUSE:
+ rtl_uString_newFromAscii (strError, "WSAEADDRINUSE, Triggered by bind() because a process went down without closing a socket.");
+ break;
+
+ case WSAEADDRNOTAVAIL:
+ rtl_uString_newFromAscii (strError, "WSAEADDRNOTAVAIL, Can't assign requested Addr");
+ break;
+
+ case WSAENETDOWN:
+ rtl_uString_newFromAscii (strError, "WSAENETDOWN, Network is down");
+ break;
+
+ case WSAENETUNREACH:
+ rtl_uString_newFromAscii (strError, "WSAENETUNREACH, Network is unreachable");
+ break;
+
+ case WSAENETRESET:
+ rtl_uString_newFromAscii (strError, "WSAENETRESET, Network dropped connection or reset");
+ break;
+
+ case WSAECONNABORTED:
+ rtl_uString_newFromAscii (strError, "WSAECONNABORTED, Software caused connection abort");
+ break;
+
+ case WSAECONNRESET:
+ rtl_uString_newFromAscii (strError, "WSAECONNRESET, Connection reset by peer");
+ break;
+
+ case WSAENOBUFS:
+ rtl_uString_newFromAscii (strError, "WSAENOBUFS, No buffer space available.");
+ break;
+
+ case WSAEISCONN:
+ rtl_uString_newFromAscii (strError, "WSAEISCONN, Socket is already connected");
+ break;
+
+ case WSAENOTCONN:
+ rtl_uString_newFromAscii (strError, "WSAENOTCONN, Socket is not connected");
+ break;
+
+ case WSAESHUTDOWN:
+ rtl_uString_newFromAscii (strError, "WSAESHUTDOWN, Can't send after socket shutdown");
+ break;
+
+ case WSAETIMEDOUT:
+ rtl_uString_newFromAscii (strError, "WSAETIMEDOUT, Connection timed out");
+ break;
+
+ case WSAECONNREFUSED:
+ rtl_uString_newFromAscii (strError, "WSAECONNREFUSED, Connection refused");
+ break;
+
+ case WSAEHOSTDOWN:
+ rtl_uString_newFromAscii (strError, "WSAEHOSTDOWN, Networking subsystem not started");
+ break;
+
+ case WSAEHOSTUNREACH:
+ rtl_uString_newFromAscii (strError, "WSAEHOSTUNREACH, No route to host");
+ break;
+
+ case WSAEWOULDBLOCK:
+ rtl_uString_newFromAscii (strError, "WSAEWOULDBLOCK, Operation would block");
+ break;
+
+ case WSAEINPROGRESS:
+ rtl_uString_newFromAscii (strError, "WSAEINPROGRESS, Operation now in progress");
+ break;
+
+ case WSAEALREADY:
+ rtl_uString_newFromAscii (strError, "WSAEALREADY, Operation already in progress");
+ break;
+
+ case WSAEINTR:
+ rtl_uString_newFromAscii (strError, "WSAEALREADY, Operation was interrupted");
+ break;
+
+ case WSAEBADF:
+ rtl_uString_newFromAscii (strError, "WSAEBADF, Bad file number");
+ break;
+
+ case WSAEACCES:
+ rtl_uString_newFromAscii (strError, "WSAEACCES, Access is denied");
+ break;
+
+ case WSAEFAULT:
+ rtl_uString_newFromAscii (strError, "WSAEFAULT, Bad memory Addr");
+ break;
+
+ case WSAEINVAL:
+ rtl_uString_newFromAscii (strError, "WSAEINVAL, The socket has not been bound with bind() or is already connected");
+ break;
+
+ case WSAEMFILE:
+ rtl_uString_newFromAscii (strError, "WSAEMFILE, No more file descriptors are available");
+ break;
+
+ case WSAETOOMANYREFS:
+ rtl_uString_newFromAscii (strError, "WSAETOOMANYREFS, Undocumented WinSock error");
+ break;
+
+ case WSAENAMETOOLONG:
+ rtl_uString_newFromAscii (strError, "WSAENAMETOOLONG, Undocumented WinSock error");
+ break;
+
+ case WSAENOTEMPTY:
+ rtl_uString_newFromAscii (strError, "WSAENOTEMPTY, Undocumented WinSock error");
+ break;
+
+ case WSAEPROCLIM:
+ rtl_uString_newFromAscii (strError, "WSAEPROCLIM, Undocumented WinSock error");
+ break;
+
+ case WSAEUSERS:
+ rtl_uString_newFromAscii (strError, "WSAEUSERS, Undocumented WinSock error");
+ break;
+
+ case WSAEDQUOT:
+ rtl_uString_newFromAscii (strError, "WSAEDQUOT, Undocumented WinSock error");
+ break;
+
+ case WSAESTALE:
+ rtl_uString_newFromAscii (strError, "WSAESTALE, Undocumented WinSock error");
+ break;
+
+ case WSAEREMOTE:
+ rtl_uString_newFromAscii (strError, "WSAEREMOTE, Undocumented WinSock error");
+ break;
+
+ case WSAEDISCON:
+ rtl_uString_newFromAscii (strError, "WSAEDISCON, Circuit was gracefully terminated");
+ break;
+
+ case WSASYSNOTREADY:
+ rtl_uString_newFromAscii (strError, "WSASYSNOTREADY, The underlying network subsystem is not ready for network communication");
+ break;
+
+ case WSAVERNOTSUPPORTED:
+ rtl_uString_newFromAscii (strError, "WSAVERNOTSUPPORTED, The version of Windows Sockets API support requested is not provided by this particular Windows Sockets implementation");
+ break;
+
+ case WSANOTINITIALISED:
+ rtl_uString_newFromAscii (strError, "WSANOTINITIALISED, WSAStartup() has not been called");
+ break;
+
+ case WSAHOST_NOT_FOUND:
+ rtl_uString_newFromAscii (strError, "WSAHOST_NOT_FOUND, Authoritative answer host not found");
+ break;
+
+ case WSATRY_AGAIN:
+ rtl_uString_newFromAscii (strError, "WSATRY_AGAIN, Non-authoritative answer host not found or SERVERFAIL");
+ break;
+
+ case WSANO_RECOVERY:
+ rtl_uString_newFromAscii (strError, "WSANO_RECOVERY, Non recoverable errors, FORMERR, REFUSED, NOTIMP");
+ break;
+
+ case WSANO_DATA:
+ rtl_uString_newFromAscii (strError, "WSANO_DATA or WSANO_ADDRESS, Valid name, no data record of requested type");
+ break;
+
+ default:
+ {
+ sal_Unicode message[128];
+
+ wsprintfW(reinterpret_cast<LPWSTR>(message), L"Unknown WinSock Error Number %d", error);
+ rtl_uString_newFromStr (strError, message);
+ }
+
+ return;
+
+ }
+}
+
+/*****************************************************************************/
+/* osl_getLastSocketError */
+/*****************************************************************************/
+oslSocketError SAL_CALL osl_getLastSocketError(oslSocket /*Socket*/)
+{
+ return ERROR_FROM_NATIVE(WSAGetLastError());
+}
+
+/*****************************************************************************/
+/* SocketSet */
+/*****************************************************************************/
+typedef struct _TSocketSetImpl
+{
+ fd_set m_Set; /* the set of descriptors */
+
+} TSocketSetImpl;
+
+/*****************************************************************************/
+/* osl_createSocketSet */
+/*****************************************************************************/
+oslSocketSet SAL_CALL osl_createSocketSet()
+{
+ TSocketSetImpl* pSet;
+
+ pSet = (TSocketSetImpl*) rtl_allocateMemory(sizeof(TSocketSetImpl));
+
+ if(pSet)
+ {
+ FD_ZERO(&pSet->m_Set);
+ }
+
+ return (oslSocketSet)pSet;
+}
+
+/*****************************************************************************/
+/* osl_destroySocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_destroySocketSet (oslSocketSet Set)
+{
+ if(Set)
+ rtl_freeMemory(Set);
+}
+
+/*****************************************************************************/
+/* osl_clearSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_clearSocketSet (oslSocketSet Set)
+{
+ TSocketSetImpl* pSet;
+
+ pSet= (TSocketSetImpl*)Set;
+
+ if (pSet)
+ FD_ZERO(&pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_addToSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_addToSocketSet (
+ oslSocketSet Set,
+ oslSocket Socket)
+{
+ TSocketSetImpl* pSet;
+ oslSocketImpl* pSockImpl;
+
+ pSet= (TSocketSetImpl*)Set;
+ pSockImpl= (oslSocketImpl*)Socket;
+
+ if (pSet && pSockImpl)
+ FD_SET(pSockImpl->m_Socket, &pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_removeFromSocketSet */
+/*****************************************************************************/
+void SAL_CALL osl_removeFromSocketSet (
+ oslSocketSet Set,
+ oslSocket Socket)
+{
+ TSocketSetImpl* pSet;
+ oslSocketImpl* pSockImpl;
+
+ pSet= (TSocketSetImpl*)Set;
+ pSockImpl= (oslSocketImpl*)Socket;
+
+ if (pSet && pSockImpl)
+ FD_CLR(pSockImpl->m_Socket, &pSet->m_Set);
+}
+
+/*****************************************************************************/
+/* osl_isInSocketSet */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isInSocketSet (
+ oslSocketSet Set,
+ oslSocket Socket)
+{
+ TSocketSetImpl* pSet;
+ oslSocketImpl* pSockImpl;
+
+ pSet= (TSocketSetImpl*)Set;
+ pSockImpl= (oslSocketImpl*)Socket;
+
+ if (pSet && pSockImpl)
+ return (FD_ISSET(pSockImpl->m_Socket, &pSet->m_Set) != 0);
+ else
+ return sal_False;
+}
+
+/*****************************************************************************/
+/* osl_demultiplexSocketEvents */
+/*****************************************************************************/
+sal_Int32 SAL_CALL osl_demultiplexSocketEvents (
+ oslSocketSet IncomingSet,
+ oslSocketSet OutgoingSet,
+ oslSocketSet OutOfBandSet,
+ const TimeValue* pTimeout)
+{
+ int MaxHandle= 0;
+ struct timeval tv;
+ TSocketSetImpl* pInSet;
+ TSocketSetImpl* pOutSet;
+ TSocketSetImpl* pOOBSet;
+
+ if(pTimeout)
+ {
+ /* divide milliseconds into seconds and microseconds */
+ tv.tv_sec = pTimeout->Seconds;
+ tv.tv_usec = pTimeout->Nanosec / 1000L;
+ }
+
+ /* map opaque data to impl-types */
+ pInSet= (TSocketSetImpl*)IncomingSet;
+ pOutSet= (TSocketSetImpl*)OutgoingSet;
+ pOOBSet= (TSocketSetImpl*)OutOfBandSet;
+
+ return select(MaxHandle, /* redundant in WIN32 */
+ pInSet ? &pInSet->m_Set : 0,
+ pOutSet ? &pOutSet->m_Set : 0,
+ pOOBSet ? &pOOBSet->m_Set : 0,
+ pTimeout ? &tv : 0);
+}
+
+}
diff --git a/sal/osl/w32/sockimpl.h b/sal/osl/w32/sockimpl.h
new file mode 100644
index 000000000000..d1278ee8e6ac
--- /dev/null
+++ b/sal/osl/w32/sockimpl.h
@@ -0,0 +1,108 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _OSL_SOCKETIMPL_H_
+#define _OSL_SOCKETIMPL_H_
+
+#include <osl/socket.h>
+#include <osl/interlck.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************/
+/* oslSocketImpl */
+/*****************************************************************************/
+#define OSL_SOCKET_FLAGS_NONBLOCKING 0x0001
+
+typedef void* (SAL_CALL * oslCloseCallback) (void*);
+
+struct oslSocketImpl {
+ oslInterlockedCount m_nRefCount;
+ SOCKET m_Socket;
+ int m_Flags;
+ oslCloseCallback m_CloseCallback;
+ void* m_CallbackArg;
+};
+
+struct oslSocketAddrImpl
+{
+ struct sockaddr m_sockaddr;
+ oslInterlockedCount m_nRefCount;
+};
+
+oslSocket __osl_createSocketImpl(SOCKET Socket);
+void __osl_destroySocketImpl(oslSocket pImpl);
+
+/*****************************************************************************/
+/* oslSocketDialupImpl */
+/*****************************************************************************/
+#define INTERNET_MODULE_NAME "wininet.dll"
+
+#define INTERNET_CONNECTION_MODEM 0x00000001L
+#define INTERNET_CONNECTION_LAN 0x00000002L
+#define INTERNET_CONNECTION_HANGUP 0x80000000L
+
+typedef DWORD (WINAPI *INTERNETATTEMPTCONNECT) (
+ DWORD dwReserved);
+typedef BOOL (WINAPI *INTERNETAUTODIAL) (
+ DWORD dwFlags, DWORD dwReserved);
+typedef BOOL (WINAPI *INTERNETAUTODIALHANGUP) (
+ DWORD dwReserved);
+typedef BOOL (WINAPI *INTERNETGETCONNECTEDSTATE) (
+ LPDWORD lpdwFlags, DWORD dwReserved);
+
+typedef struct osl_socket_dialup_impl_st
+{
+ CRITICAL_SECTION m_hMutex;
+ HINSTANCE m_hModule;
+ INTERNETATTEMPTCONNECT m_pfnAttemptConnect;
+ INTERNETAUTODIAL m_pfnAutodial;
+ INTERNETAUTODIALHANGUP m_pfnAutodialHangup;
+ INTERNETGETCONNECTEDSTATE m_pfnGetConnectedState;
+ DWORD m_dwFlags;
+} oslSocketDialupImpl;
+
+static oslSocketDialupImpl* __osl_createSocketDialupImpl (void);
+static void __osl_initSocketDialupImpl (oslSocketDialupImpl *pImpl);
+static void __osl_destroySocketDialupImpl (oslSocketDialupImpl *pImpl);
+
+static sal_Bool __osl_querySocketDialupImpl (void);
+static sal_Bool __osl_attemptSocketDialupImpl (void);
+
+/*****************************************************************************/
+/* The End */
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/sal/osl/w32/system.h b/sal/osl/w32/system.h
new file mode 100644
index 000000000000..1bd86994e6ce
--- /dev/null
+++ b/sal/osl/w32/system.h
@@ -0,0 +1,126 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#if OSL_DEBUG_LEVEL == 0
+# define NO_DEBUG_CRT
+#endif
+
+#ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0400
+# define _CTYPE_DISABLE_MACROS /* wg. dynamischer C-Runtime MH */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <limits.h>
+#include <process.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <share.h>
+#include <direct.h>
+
+/* Must define this else build breaks because Winsock2.h
+ includes Windows.h and without WIN32_LEAN_AND_MEAN
+ also includes mswsock.h which needs a forward typedef
+ of SOCKET ...
+*/
+#define WIN32_LEAN_AND_MEAN
+
+#ifdef GCC
+ // windows.h includes winsock2.h
+ // if _WIN32_WINNT > 0x0400
+ // so someone cannot include winsock.h
+ // at the same time without patching
+ // windows.h
+ #include <windows.h>
+#ifdef __MINGW32__
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+#endif
+ #include <shlobj.h>
+ #ifndef NO_DEBUG_CRT
+ #include <crtdbg.h>
+ #endif
+#else
+ // winsock2.h includes windows.h
+ #pragma warning(push,1) /* disable warnings within system headers */
+ #pragma warning(disable:4917)
+ #include <winsock2.h>
+ #include <wsipx.h>
+ #include <shlobj.h>
+ #ifndef NO_DEBUG_CRT
+ #include <crtdbg.h>
+ #endif
+ #pragma warning(pop)
+#endif
+
+#define _MAX_CMD 4096 /* maximum length of commandline */
+/* #define _MAX_ENV 4096 maximum length of environment var (isn't used anywhere) */
+
+#ifdef GCC
+ # ifndef SA_FAMILY_DECL
+ # define SA_FAMILY_DECL short sa_family
+ # endif
+
+ typedef struct sockaddr_ipx {
+ SA_FAMILY_DECL;
+ char sa_netnum[4];
+ char sa_nodenum[6];
+ unsigned short sa_socket;
+ } SOCKADDR_IPX;
+
+ # define NSPROTO_IPX 1000
+ # define NSPROTO_SPX 1256
+ # define NSPROTO_SPXII 1257
+#endif // #ifdef GCC
+
+#ifdef _DLL_
+
+#ifdef __cplusplus
+ extern "C" DWORD g_dwPlatformId;
+#else
+ extern DWORD g_dwPlatformId;
+#endif // #ifdef __cplusplus
+
+ #define IS_NT (g_dwPlatformId == VER_PLATFORM_WIN32_NT)
+#else
+
+#ifdef __cplusplus
+ extern "C" DWORD GetPlatformId(void);
+#else
+ extern DWORD GetPlatformId(void);
+#endif // #ifdef __cplusplus
+
+ #define IS_NT (GetPlatformId() == VER_PLATFORM_WIN32_NT)
+#endif // #ifdef _DLL_
+
diff --git a/sal/osl/w32/tempfile.cxx b/sal/osl/w32/tempfile.cxx
new file mode 100644
index 000000000000..6a3d2549004a
--- /dev/null
+++ b/sal/osl/w32/tempfile.cxx
@@ -0,0 +1,274 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#define _UNICODE
+#define _WIN32_WINNT_0x0500
+#include "systools/win32/uwinapi.h"
+
+#include "osl/file.h"
+
+#include "file_error.h"
+#include "file_url.h"
+#include "path_helper.hxx"
+
+#include "osl/diagnose.h"
+
+#include <malloc.h>
+#include <tchar.h>
+
+//#####################################################
+#define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0])))
+
+// Allocate n number of t's on the stack return a pointer to it in p
+#ifdef __MINGW32__
+#define STACK_ALLOC(p, t, n) (p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t)));
+#else
+#define STACK_ALLOC(p, t, n) __try {(p) = reinterpret_cast<t*>(_alloca((n)*sizeof(t)));} \
+ __except(EXCEPTION_EXECUTE_HANDLER) {(p) = 0;}
+#endif
+
+extern "C" oslFileHandle SAL_CALL osl_createFileHandleFromOSHandle(HANDLE hFile, sal_uInt32 uFlags);
+
+//#####################################################
+// Temp file functions
+//#####################################################
+
+static oslFileError osl_setup_base_directory_impl_(
+ rtl_uString* pustrDirectoryURL,
+ rtl_uString** ppustr_base_dir)
+{
+ rtl_uString* dir_url = 0;
+ rtl_uString* dir = 0;
+ oslFileError error = osl_File_E_None;
+
+ if (pustrDirectoryURL)
+ rtl_uString_assign(&dir_url, pustrDirectoryURL);
+ else
+ error = osl_getTempDirURL(&dir_url);
+
+ if (osl_File_E_None == error)
+ {
+ error = _osl_getSystemPathFromFileURL(dir_url, &dir, sal_False);
+ rtl_uString_release(dir_url);
+ }
+
+ if (osl_File_E_None == error )
+ {
+ rtl_uString_assign(ppustr_base_dir, dir);
+ rtl_uString_release(dir);
+ }
+
+ return error;
+}
+
+//#####################################################
+static oslFileError osl_setup_createTempFile_impl_(
+ rtl_uString* pustrDirectoryURL,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL,
+ rtl_uString** ppustr_base_dir,
+ sal_Bool* b_delete_on_close)
+{
+ oslFileError osl_error;
+
+ OSL_PRECOND(((0 != pHandle) || (0 != ppustrTempFileURL)), "Invalid parameter!");
+
+ if ((0 == pHandle) && (0 == ppustrTempFileURL))
+ {
+ osl_error = osl_File_E_INVAL;
+ }
+ else
+ {
+ osl_error = osl_setup_base_directory_impl_(
+ pustrDirectoryURL, ppustr_base_dir);
+
+ *b_delete_on_close = (sal_Bool)(0 == ppustrTempFileURL);
+ }
+
+ return osl_error;
+}
+
+//#####################################################
+static oslFileError osl_win32_GetTempFileName_impl_(
+ rtl_uString* base_directory, LPWSTR temp_file_name)
+{
+ oslFileError osl_error = osl_File_E_None;
+
+ if (0 == GetTempFileNameW(
+ reinterpret_cast<LPCWSTR>(rtl_uString_getStr(base_directory)),
+ L"",
+ 0,
+ temp_file_name))
+ {
+ osl_error = oslTranslateFileError(GetLastError());
+ }
+
+ return osl_error;
+}
+
+//#####################################################
+static sal_Bool osl_win32_CreateFile_impl_(
+ LPCWSTR file_name, sal_Bool b_delete_on_close, oslFileHandle* p_handle)
+{
+ DWORD flags = FILE_ATTRIBUTE_NORMAL;
+ HANDLE hFile;
+
+ OSL_ASSERT(p_handle);
+
+ if (b_delete_on_close)
+ flags |= FILE_FLAG_DELETE_ON_CLOSE;
+
+ hFile = CreateFileW(
+ file_name,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ TRUNCATE_EXISTING,
+ flags,
+ NULL);
+
+ // @@@ ERROR HANDLING @@@
+ if (IsValidHandle(hFile))
+ *p_handle = osl_createFileHandleFromOSHandle(hFile, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
+
+ return (sal_Bool)IsValidHandle(hFile);
+}
+
+//#############################################
+static oslFileError osl_createTempFile_impl_(
+ rtl_uString* base_directory,
+ LPWSTR tmp_name,
+ sal_Bool b_delete_on_close,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL)
+{
+ oslFileError osl_error;
+
+ do
+ {
+ osl_error = osl_win32_GetTempFileName_impl_(base_directory, tmp_name);
+
+ /* if file could not be opened try again */
+
+ if ((osl_File_E_None != osl_error) || (0 == pHandle) ||
+ osl_win32_CreateFile_impl_(tmp_name, b_delete_on_close, pHandle))
+ break;
+
+ } while(1); // try until success
+
+ if ((osl_File_E_None == osl_error) && !b_delete_on_close)
+ {
+ rtl_uString* pustr = 0;
+ rtl_uString_newFromStr(&pustr, reinterpret_cast<const sal_Unicode*>(tmp_name));
+ osl_getFileURLFromSystemPath(pustr, ppustrTempFileURL);
+ rtl_uString_release(pustr);
+ }
+
+ return osl_error;
+}
+
+//#############################################
+oslFileError SAL_CALL osl_createTempFile(
+ rtl_uString* pustrDirectoryURL,
+ oslFileHandle* pHandle,
+ rtl_uString** ppustrTempFileURL)
+{
+ rtl_uString* base_directory = 0;
+ LPWSTR tmp_name;
+ sal_Bool b_delete_on_close;
+ oslFileError osl_error;
+
+ osl_error = osl_setup_createTempFile_impl_(
+ pustrDirectoryURL,
+ pHandle,
+ ppustrTempFileURL,
+ &base_directory,
+ &b_delete_on_close);
+
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+
+ /* allocate enough space on the stack, the file name can not be longer than MAX_PATH */
+ STACK_ALLOC(tmp_name, WCHAR, (rtl_uString_getLength(base_directory) + MAX_PATH));
+
+ if (tmp_name)
+ {
+ osl_createTempFile_impl_(
+ base_directory,
+ tmp_name,
+ b_delete_on_close,
+ pHandle,
+ ppustrTempFileURL);
+ }
+ else // stack alloc failed
+ {
+ osl_error = osl_File_E_NOMEM;
+ }
+
+ if (base_directory)
+ rtl_uString_release(base_directory);
+
+ return osl_error;
+}
+
+//#############################################
+oslFileError SAL_CALL osl_getTempDirURL(rtl_uString** pustrTempDir)
+{
+ ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
+ LPWSTR lpBuffer = ::osl::mingw_reinterpret_cast<LPWSTR>(aBuffer);
+ DWORD nBufferLength = aBuffer.getBufSizeInSymbols() - 1;
+
+ DWORD nLength;
+ oslFileError error;
+
+ nLength = GetTempPathW( aBuffer.getBufSizeInSymbols(), lpBuffer );
+
+ if ( nLength > nBufferLength )
+ {
+ // the provided path has invalid length
+ error = osl_File_E_NOENT;
+ }
+ else if ( nLength )
+ {
+ rtl_uString *ustrTempPath = NULL;
+
+ if ( '\\' == lpBuffer[nLength-1] )
+ lpBuffer[nLength-1] = 0;
+
+ rtl_uString_newFromStr( &ustrTempPath, reinterpret_cast<const sal_Unicode*>(lpBuffer) );
+
+ error = osl_getFileURLFromSystemPath( ustrTempPath, pustrTempDir );
+
+ rtl_uString_release( ustrTempPath );
+ }
+ else
+ error = oslTranslateFileError( GetLastError() );
+
+ return error;
+}
+
diff --git a/sal/osl/w32/thread.c b/sal/osl/w32/thread.c
new file mode 100644
index 000000000000..88ce87cdf175
--- /dev/null
+++ b/sal/osl/w32/thread.c
@@ -0,0 +1,593 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/thread.h>
+#include <rtl/alloc.h>
+#include <osl/time.h>
+#include <osl/interlck.h>
+#include <rtl/tencinfo.h>
+
+/*
+ Thread-data structure hidden behind oslThread:
+*/
+typedef struct _osl_TThreadImpl
+{
+ HANDLE m_hThread; /* OS-handle used for all thread-functions */
+ unsigned m_ThreadId; /* identifier for this thread */
+ sal_Int32 m_nTerminationRequested;
+ oslWorkerFunction m_WorkerFunction;
+ void* m_pData;
+
+} osl_TThreadImpl;
+
+#define THREADIMPL_FLAGS_TERMINATE 0x0001
+
+static unsigned __stdcall oslWorkerWrapperFunction(void* pData);
+static oslThread oslCreateThread(oslWorkerFunction pWorker, void* pThreadData, sal_uInt32 nFlags);
+
+/*****************************************************************************/
+/* oslWorkerWrapperFunction */
+/*****************************************************************************/
+static unsigned __stdcall oslWorkerWrapperFunction(void* pData)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)pData;
+
+ /* Initialize COM */
+
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+ /* call worker-function with data */
+
+ pThreadImpl->m_WorkerFunction(pThreadImpl->m_pData);
+
+ CoUninitialize();
+
+ return (0);
+}
+
+/*****************************************************************************/
+/* oslCreateThread */
+/*****************************************************************************/
+static oslThread oslCreateThread(oslWorkerFunction pWorker,
+ void* pThreadData,
+ sal_uInt32 nFlags)
+{
+ osl_TThreadImpl* pThreadImpl;
+
+ /* alloc mem. for our internal data structure */
+ pThreadImpl= malloc(sizeof(osl_TThreadImpl));
+
+ OSL_ASSERT(pThreadImpl);
+
+ if ( pThreadImpl == 0 )
+ {
+ return 0;
+ }
+
+ pThreadImpl->m_WorkerFunction= pWorker;
+ pThreadImpl->m_pData= pThreadData;
+ pThreadImpl->m_nTerminationRequested= 0;
+
+ pThreadImpl->m_hThread=
+ (HANDLE)_beginthreadex(NULL, /* no security */
+ 0, /* default stack-size */
+ oslWorkerWrapperFunction, /* worker-function */
+ pThreadImpl, /* provide worker-function with data */
+ nFlags, /* start thread immediately or suspended */
+ &pThreadImpl->m_ThreadId);
+
+ if(pThreadImpl->m_hThread == 0)
+ {
+ /* create failed */
+ free(pThreadImpl);
+ return 0;
+ }
+
+ return (oslThread)pThreadImpl;
+}
+
+/*****************************************************************************/
+/* osl_createThread */
+/*****************************************************************************/
+oslThread SAL_CALL osl_createThread(oslWorkerFunction pWorker,
+ void* pThreadData)
+{
+ return oslCreateThread(pWorker, pThreadData, 0);
+}
+
+/*****************************************************************************/
+/* osl_createSuspendedThread */
+/*****************************************************************************/
+oslThread SAL_CALL osl_createSuspendedThread(oslWorkerFunction pWorker,
+ void* pThreadData)
+{
+ return oslCreateThread(pWorker, pThreadData, CREATE_SUSPENDED);
+}
+
+/*****************************************************************************/
+/* osl_getThreadIdentifier */
+/*****************************************************************************/
+oslThreadIdentifier SAL_CALL osl_getThreadIdentifier(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ if (pThreadImpl != NULL)
+ return ((oslThreadIdentifier)pThreadImpl->m_ThreadId);
+ else
+ return ((oslThreadIdentifier)GetCurrentThreadId());
+}
+
+/*****************************************************************************/
+/* osl_destroyThread */
+/*****************************************************************************/
+void SAL_CALL osl_destroyThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ if (Thread == 0) /* valid ptr? */
+ {
+ /* thread already destroyed or not created */
+ return;
+ }
+
+ /* !!!! _exitthreadex does _not_ call CloseHandle !!! */
+ CloseHandle( pThreadImpl->m_hThread );
+
+ /* free memory */
+ free(Thread);
+}
+
+/*****************************************************************************/
+/* osl_resumeThread */
+/*****************************************************************************/
+void SAL_CALL osl_resumeThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ OSL_ASSERT(pThreadImpl); /* valid ptr? */
+
+ ResumeThread(pThreadImpl->m_hThread);
+}
+
+/*****************************************************************************/
+/* osl_suspendThread */
+/*****************************************************************************/
+void SAL_CALL osl_suspendThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ OSL_ASSERT(pThreadImpl); /* valid ptr? */
+
+ SuspendThread(pThreadImpl->m_hThread);
+}
+
+/*****************************************************************************/
+/* osl_setThreadPriority */
+/*****************************************************************************/
+void SAL_CALL osl_setThreadPriority(oslThread Thread,
+ oslThreadPriority Priority)
+{
+ int winPriority;
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ OSL_ASSERT(pThreadImpl); /* valid ptr? */
+
+
+ /* map enum to WIN32 levels
+ it would be faster and more elegant to preset
+ the enums, but that would require an #ifdef in
+ the exported header, which is not desired.
+ */
+ switch(Priority) {
+
+ case osl_Thread_PriorityHighest:
+ winPriority= THREAD_PRIORITY_HIGHEST;
+ break;
+
+ case osl_Thread_PriorityAboveNormal:
+ winPriority= THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+
+ case osl_Thread_PriorityNormal:
+ winPriority= THREAD_PRIORITY_NORMAL;
+ break;
+
+ case osl_Thread_PriorityBelowNormal:
+ winPriority= THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+
+ case osl_Thread_PriorityLowest:
+ winPriority= THREAD_PRIORITY_LOWEST;
+ break;
+
+ case osl_Thread_PriorityUnknown:
+ OSL_ASSERT(FALSE); /* only fools try this...*/
+
+ /* let release-version behave friendly */
+ return;
+
+ default:
+ OSL_ASSERT(FALSE); /* enum expanded, but forgotten here...*/
+
+ /* let release-version behave friendly */
+ return;
+ }
+
+ SetThreadPriority(pThreadImpl->m_hThread, winPriority);
+}
+
+/*****************************************************************************/
+/* osl_getThreadPriority */
+/*****************************************************************************/
+oslThreadPriority SAL_CALL osl_getThreadPriority(const oslThread Thread)
+{
+ int winPriority;
+ oslThreadPriority Priority;
+
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments ?*/
+ if(pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ return osl_Thread_PriorityUnknown;
+ }
+
+ winPriority=
+ GetThreadPriority(pThreadImpl->m_hThread);
+
+
+ if(winPriority == THREAD_PRIORITY_ERROR_RETURN)
+ {
+ return osl_Thread_PriorityUnknown;
+ }
+
+ /* map WIN32 priority to enum */
+ switch(winPriority)
+ {
+ case THREAD_PRIORITY_TIME_CRITICAL:
+ case THREAD_PRIORITY_HIGHEST:
+ Priority= osl_Thread_PriorityHighest;
+ break;
+
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ Priority= osl_Thread_PriorityAboveNormal;
+ break;
+
+ case THREAD_PRIORITY_NORMAL:
+ Priority= osl_Thread_PriorityNormal;
+ break;
+
+ case THREAD_PRIORITY_BELOW_NORMAL:
+ Priority= osl_Thread_PriorityBelowNormal;
+ break;
+
+ case THREAD_PRIORITY_IDLE:
+ case THREAD_PRIORITY_LOWEST:
+ Priority= osl_Thread_PriorityLowest;
+ break;
+
+ default:
+ OSL_ASSERT(FALSE); /* WIN32 API changed, incorporate new prio-level! */
+
+ /* release-version behaves friendly */
+ Priority= osl_Thread_PriorityUnknown;
+ }
+
+ return Priority;
+}
+
+/*****************************************************************************/
+/* osl_isThreadRunning */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_isThreadRunning(const oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments ?*/
+ if(pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ return sal_False;
+ }
+
+ return (sal_Bool)(WaitForSingleObject(pThreadImpl->m_hThread, 0) != WAIT_OBJECT_0);
+}
+
+/*****************************************************************************/
+/* osl_joinWithThread */
+/*****************************************************************************/
+void SAL_CALL osl_joinWithThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments?*/
+ if(pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ /* assume thread is not running */
+ return;
+ }
+
+ WaitForSingleObject(pThreadImpl->m_hThread, INFINITE);
+}
+
+/*****************************************************************************/
+/* osl_waitThread */
+/*****************************************************************************/
+void SAL_CALL osl_waitThread(const TimeValue* pDelay)
+{
+ if (pDelay)
+ {
+ DWORD millisecs = pDelay->Seconds * 1000L + pDelay->Nanosec / 1000000L;
+
+ Sleep(millisecs);
+ }
+}
+
+/*****************************************************************************/
+/* osl_terminateThread */
+/*****************************************************************************/
+void SAL_CALL osl_terminateThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ /* invalid arguments?*/
+ if (pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ /* assume thread is not running */
+ return;
+ }
+
+ osl_incrementInterlockedCount(&(pThreadImpl->m_nTerminationRequested));
+}
+
+
+/*****************************************************************************/
+/* osl_scheduleThread */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_scheduleThread(oslThread Thread)
+{
+ osl_TThreadImpl* pThreadImpl= (osl_TThreadImpl*)Thread;
+
+ osl_yieldThread();
+
+ /* invalid arguments?*/
+ if (pThreadImpl==0 || pThreadImpl->m_hThread==0)
+ {
+ /* assume thread is not running */
+ return sal_False;
+ }
+
+ return (sal_Bool)(0 == pThreadImpl->m_nTerminationRequested);
+}
+
+/*****************************************************************************/
+/* osl_yieldThread */
+/*****************************************************************************/
+void SAL_CALL osl_yieldThread(void)
+{
+ Sleep(0);
+}
+
+typedef struct _TLS
+{
+ DWORD dwIndex;
+ oslThreadKeyCallbackFunction pfnCallback;
+ struct _TLS *pNext, *pPrev;
+} TLS, *PTLS;
+
+static PTLS g_pThreadKeyList = NULL;
+CRITICAL_SECTION g_ThreadKeyListCS;
+
+static void AddKeyToList( PTLS pTls )
+{
+ if ( pTls )
+ {
+ EnterCriticalSection( &g_ThreadKeyListCS );
+
+ pTls->pNext = g_pThreadKeyList;
+ pTls->pPrev = 0;
+
+ if ( g_pThreadKeyList )
+ g_pThreadKeyList->pPrev = pTls;
+
+ g_pThreadKeyList = pTls;
+
+ LeaveCriticalSection( &g_ThreadKeyListCS );
+ }
+}
+
+static void RemoveKeyFromList( PTLS pTls )
+{
+ if ( pTls )
+ {
+ EnterCriticalSection( &g_ThreadKeyListCS );
+ if ( pTls->pPrev )
+ pTls->pPrev->pNext = pTls->pNext;
+ else
+ {
+ OSL_ASSERT( pTls == g_pThreadKeyList );
+ g_pThreadKeyList = pTls->pNext;
+ }
+
+ if ( pTls->pNext )
+ pTls->pNext->pPrev = pTls->pPrev;
+ LeaveCriticalSection( &g_ThreadKeyListCS );
+ }
+}
+
+void SAL_CALL _osl_callThreadKeyCallbackOnThreadDetach(void)
+{
+ PTLS pTls;
+
+
+ EnterCriticalSection( &g_ThreadKeyListCS );
+ pTls = g_pThreadKeyList;
+ while ( pTls )
+ {
+ if ( pTls->pfnCallback )
+ {
+ void *pValue = TlsGetValue( pTls->dwIndex );
+
+ if ( pValue )
+ pTls->pfnCallback( pValue );
+ }
+
+ pTls = pTls->pNext;
+ }
+ LeaveCriticalSection( &g_ThreadKeyListCS );
+}
+
+/*****************************************************************************/
+/* osl_createThreadKey */
+/*****************************************************************************/
+oslThreadKey SAL_CALL osl_createThreadKey(oslThreadKeyCallbackFunction pCallback)
+{
+ PTLS pTls = rtl_allocateMemory( sizeof(TLS) );
+
+ if ( pTls )
+ {
+ pTls->pfnCallback = pCallback;
+ if ( (DWORD)-1 == (pTls->dwIndex = TlsAlloc()) )
+ {
+ rtl_freeMemory( pTls );
+ pTls = 0;
+ }
+ else
+ AddKeyToList( pTls );
+ }
+
+ return ((oslThreadKey)pTls);
+}
+
+/*****************************************************************************/
+/* osl_destroyThreadKey */
+/*****************************************************************************/
+void SAL_CALL osl_destroyThreadKey(oslThreadKey Key)
+{
+ if (Key != 0)
+ {
+ PTLS pTls = (PTLS)Key;
+
+ RemoveKeyFromList( pTls );
+ TlsFree( pTls->dwIndex );
+ rtl_freeMemory( pTls );
+ }
+}
+
+/*****************************************************************************/
+/* osl_getThreadKeyData */
+/*****************************************************************************/
+void* SAL_CALL osl_getThreadKeyData(oslThreadKey Key)
+{
+ if (Key != 0)
+ {
+ PTLS pTls = (PTLS)Key;
+
+ return (TlsGetValue( pTls->dwIndex ));
+ }
+
+ return (NULL);
+}
+
+/*****************************************************************************/
+/* osl_setThreadKeyData */
+/*****************************************************************************/
+sal_Bool SAL_CALL osl_setThreadKeyData(oslThreadKey Key, void *pData)
+{
+ if (Key != 0)
+ {
+ PTLS pTls = (PTLS)Key;
+ void* pOldData = NULL;
+ BOOL fSuccess;
+
+ if ( pTls->pfnCallback )
+ pOldData = TlsGetValue( pTls->dwIndex );
+
+ fSuccess = TlsSetValue( pTls->dwIndex, pData );
+
+ if ( fSuccess && pTls->pfnCallback && pOldData )
+ pTls->pfnCallback( pOldData );
+
+ return (sal_Bool)(fSuccess != FALSE);
+ }
+
+ return (sal_False);
+}
+
+
+/*****************************************************************************/
+/* osl_getThreadTextEncoding */
+/*****************************************************************************/
+
+DWORD g_dwTLSTextEncodingIndex = (DWORD)-1;
+
+
+rtl_TextEncoding SAL_CALL osl_getThreadTextEncoding(void)
+{
+ DWORD dwEncoding;
+ rtl_TextEncoding _encoding;
+ BOOL gotACP;
+
+ if ( (DWORD)-1 == g_dwTLSTextEncodingIndex )
+ g_dwTLSTextEncodingIndex = TlsAlloc();
+
+ dwEncoding = (DWORD)TlsGetValue( g_dwTLSTextEncodingIndex );
+ _encoding = LOWORD(dwEncoding);
+ gotACP = HIWORD(dwEncoding);
+
+
+ if ( !gotACP )
+ {
+ char *pszEncoding;
+
+ if ( NULL != (pszEncoding = getenv( "SOLAR_USER_RTL_TEXTENCODING" )) )
+ _encoding = (rtl_TextEncoding)atoi(pszEncoding);
+ else
+ _encoding = rtl_getTextEncodingFromWindowsCodePage( GetACP() );
+
+ TlsSetValue( g_dwTLSTextEncodingIndex, (LPVOID)MAKELONG( _encoding, TRUE ) );
+ }
+
+ return _encoding;
+}
+
+/*****************************************************************************/
+/* osl_getThreadTextEncoding */
+/*****************************************************************************/
+rtl_TextEncoding SAL_CALL osl_setThreadTextEncoding( rtl_TextEncoding Encoding )
+{
+ rtl_TextEncoding oldEncoding = osl_getThreadTextEncoding();
+
+ TlsSetValue( g_dwTLSTextEncodingIndex, (LPVOID)MAKELONG( Encoding, TRUE) );
+
+ return oldEncoding;
+}
+
+
+
diff --git a/sal/osl/w32/time.c b/sal/osl/w32/time.c
new file mode 100644
index 000000000000..a4d0b6fffbad
--- /dev/null
+++ b/sal/osl/w32/time.c
@@ -0,0 +1,216 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "system.h"
+
+#include <osl/diagnose.h>
+#include <osl/time.h>
+#include <sys/timeb.h>
+
+extern sal_Bool TimeValueToFileTime(const TimeValue *cpTimeVal, FILETIME *pFTime);
+
+extern BOOL FileTimeToTimeValue( const FILETIME *cpFTime, TimeValue *pTimeVal );
+
+//--------------------------------------------------
+// osl_getSystemTime
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getSystemTime(TimeValue* pTimeVal)
+{
+ SYSTEMTIME SystemTime;
+ FILETIME CurTime, OffTime;
+ __int64 Value;
+
+ OSL_ASSERT(pTimeVal != 0);
+
+ GetSystemTime(&SystemTime);
+ SystemTimeToFileTime(&SystemTime, &CurTime);
+
+ SystemTime.wYear = 1970;
+ SystemTime.wMonth = 1;
+ SystemTime.wDayOfWeek = 0;
+ SystemTime.wDay = 1;
+ SystemTime.wHour = 0;
+ SystemTime.wMinute = 0;
+ SystemTime.wSecond = 0;
+ SystemTime.wMilliseconds = 0;
+
+ SystemTimeToFileTime(&SystemTime, &OffTime);
+
+ Value = *((__int64 *)&CurTime) - *((__int64 *)&OffTime);
+
+ pTimeVal->Seconds = (unsigned long) (Value / 10000000L);
+ pTimeVal->Nanosec = (unsigned long)((Value % 10000000L) * 100);
+
+ return (sal_True);
+}
+
+//--------------------------------------------------
+// osl_getDateTimeFromTimeValue
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getDateTimeFromTimeValue( TimeValue* pTimeVal, oslDateTime* pDateTime )
+{
+ FILETIME aFileTime;
+ SYSTEMTIME aSystemTime;
+
+ if ( TimeValueToFileTime(pTimeVal, &aFileTime) )
+ {
+ if ( FileTimeToSystemTime( &aFileTime, &aSystemTime ) )
+ {
+ pDateTime->NanoSeconds = pTimeVal->Nanosec;
+
+ pDateTime->Seconds = aSystemTime.wSecond;
+ pDateTime->Minutes = aSystemTime.wMinute;
+ pDateTime->Hours = aSystemTime.wHour;
+ pDateTime->Day = aSystemTime.wDay;
+ pDateTime->DayOfWeek = aSystemTime.wDayOfWeek;
+ pDateTime->Month = aSystemTime.wMonth;
+ pDateTime->Year = aSystemTime.wYear;
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+//--------------------------------------------------
+// osl_getTimeValueFromDateTime
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getTimeValueFromDateTime( oslDateTime* pDateTime, TimeValue* pTimeVal )
+{
+ FILETIME aFileTime;
+ SYSTEMTIME aSystemTime;
+
+ aSystemTime.wMilliseconds = 0;
+ aSystemTime.wSecond = pDateTime->Seconds;
+ aSystemTime.wMinute = pDateTime->Minutes;
+ aSystemTime.wHour = pDateTime->Hours;
+ aSystemTime.wDay = pDateTime->Day;
+ aSystemTime.wDayOfWeek = pDateTime->DayOfWeek;
+ aSystemTime.wMonth = pDateTime->Month;
+ aSystemTime.wYear = pDateTime->Year;
+
+ if ( SystemTimeToFileTime( &aSystemTime, &aFileTime ) )
+ {
+ if (FileTimeToTimeValue( &aFileTime, pTimeVal ) )
+ {
+ pTimeVal->Nanosec = pDateTime->NanoSeconds;
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+
+//--------------------------------------------------
+// osl_getLocalTimeFromSystemTime
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getLocalTimeFromSystemTime( TimeValue* pSystemTimeVal, TimeValue* pLocalTimeVal )
+{
+ TIME_ZONE_INFORMATION aTimeZoneInformation;
+ DWORD Success;
+ sal_Int64 bias;
+
+ // get timezone information
+ if ( ( Success=GetTimeZoneInformation( &aTimeZoneInformation ) ) != TIME_ZONE_ID_INVALID)
+ {
+ bias=aTimeZoneInformation.Bias;
+
+ // add bias for daylight saving time
+ if ( Success== TIME_ZONE_ID_DAYLIGHT )
+ bias+=aTimeZoneInformation.DaylightBias;
+
+ if ( (sal_Int64) pSystemTimeVal->Seconds > ( bias * 60 ) )
+ {
+ pLocalTimeVal->Seconds = (sal_uInt32) (pSystemTimeVal->Seconds - ( bias * 60) );
+ pLocalTimeVal->Nanosec = pSystemTimeVal->Nanosec;
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+//--------------------------------------------------
+// osl_getSystemTimeFromLocalTime
+//--------------------------------------------------
+
+sal_Bool SAL_CALL osl_getSystemTimeFromLocalTime( TimeValue* pLocalTimeVal, TimeValue* pSystemTimeVal )
+{
+ TIME_ZONE_INFORMATION aTimeZoneInformation;
+ DWORD Success;
+ sal_Int64 bias;
+
+ // get timezone information
+ if ( ( Success=GetTimeZoneInformation( &aTimeZoneInformation ) ) != TIME_ZONE_ID_INVALID)
+ {
+ bias=aTimeZoneInformation.Bias;
+
+ // add bias for daylight saving time
+ if ( Success== TIME_ZONE_ID_DAYLIGHT )
+ bias+=aTimeZoneInformation.DaylightBias;
+
+ if ( (sal_Int64) pLocalTimeVal->Seconds + ( bias * 60 ) > 0 )
+ {
+ pSystemTimeVal->Seconds = (sal_uInt32) ( pLocalTimeVal->Seconds + ( bias * 60) );
+ pSystemTimeVal->Nanosec = pLocalTimeVal->Nanosec;
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+
+static struct _timeb startTime;
+static sal_Bool bGlobalTimer = sal_False;
+
+sal_uInt32 SAL_CALL osl_getGlobalTimer(void)
+{
+ struct _timeb currentTime;
+ sal_uInt32 nSeconds;
+
+ if ( bGlobalTimer == sal_False )
+ {
+ _ftime( &startTime );
+ bGlobalTimer=sal_True;
+ }
+
+ _ftime( &currentTime );
+
+ nSeconds = (sal_uInt32)( currentTime.time - startTime.time );
+
+ return ( nSeconds * 1000 ) + (long)( currentTime.millitm - startTime.millitm );
+}
+
diff --git a/sal/osl/w32/util.c b/sal/osl/w32/util.c
new file mode 100644
index 000000000000..f4d8cbf52d20
--- /dev/null
+++ b/sal/osl/w32/util.c
@@ -0,0 +1,37 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "osl/util.h"
+
+
+
+extern sal_Bool SAL_CALL osl_getEthernetAddress( sal_uInt8 *pAddr )
+{
+ pAddr = pAddr; /* avoid warnings */
+ return sal_False;
+}
+