summaryrefslogtreecommitdiff
path: root/sal/osl/unx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/unx')
-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
45 files changed, 23540 insertions, 0 deletions
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_ */
+